1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2016 Werner Schweer
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2
9 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #include "stafflines.h"
14 #include "system.h"
15 #include "measure.h"
16 #include "score.h"
17 #include "stafftype.h"
18 #include "staff.h"
19 
20 // Anatomy of StaffLines:
21 //
22 //    step         - The possible vertical positions of a note are counted as steps.
23 //                   The top staff line is step position zero.
24 //    lines        - number of visible staff lines
25 //    lineDistance - The distance between lines, measured in step units. A standard five line
26 //                   staff has a line distance of two steps.
27 //    stepDistance - The distance between steps measured in scaled spatium/2 units. A standard five
28 //                   line staff has a step distance of 0.5 which results in a line distance of
29 //                   one spatium. The spatium unit is scaled by staff size.
30 //    yoffset      - vertical offset to align with other staves of different height
31 //    stepOffset   - This value changes the staff line step numbering.
32 //
33 
34 namespace Ms {
35 
36 //---------------------------------------------------------
37 //   StaffLines
38 //---------------------------------------------------------
39 
StaffLines(Score * s)40 StaffLines::StaffLines(Score* s)
41    : Element(s)
42       {
43       setSelectable(false);
44       }
45 
46 //---------------------------------------------------------
47 //   pagePos
48 //---------------------------------------------------------
49 
pagePos() const50 QPointF StaffLines::pagePos() const
51       {
52       System* system = measure()->system();
53       return QPointF(measure()->x() + system->x(), system->staff(staffIdx())->y() + system->y());
54       }
55 
56 //---------------------------------------------------------
57 //   canvasPos
58 //---------------------------------------------------------
59 
canvasPos() const60 QPointF StaffLines::canvasPos() const
61       {
62       QPointF p(pagePos());
63       Element* e = parent();
64       while (e) {
65             if (e->type() == ElementType::PAGE) {
66                   p += e->pos();
67                   break;
68                   }
69             e = e->parent();
70             }
71       return p;
72       }
73 
74 //---------------------------------------------------------
75 //   layout
76 //---------------------------------------------------------
77 
layout()78 void StaffLines::layout()
79       {
80       layoutForWidth(measure()->width());
81       }
82 
83 //---------------------------------------------------------
84 //   layoutForWidth
85 //---------------------------------------------------------
86 
layoutForWidth(qreal w)87 void StaffLines::layoutForWidth(qreal w)
88       {
89       const Staff* s = staff();
90       qreal _spatium = spatium();
91       qreal dist     = _spatium;
92       setPos(QPointF(0.0, 0.0));
93       int _lines;
94       if (s) {
95             setMag(s->mag(measure()->tick()));
96             setVisible(!s->invisible(measure()->tick()));
97             setColor(s->color(measure()->tick()));
98             const StaffType* st = s->staffType(measure()->tick());
99             dist         *= st->lineDistance().val();
100             _lines        = st->lines();
101             rypos()       = st->yoffset().val() * _spatium;
102 //            if (_lines == 1)
103 //                  rypos() = 2 * _spatium;
104             }
105       else {
106             _lines = 5;
107             setColor(MScore::defaultColor);
108             }
109       lw       = score()->styleS(Sid::staffLineWidth).val() * _spatium;
110       qreal x1 = pos().x();
111       qreal x2 = x1 + w;
112       qreal y  = pos().y();
113       bbox().setRect(x1, -lw * .5 + y, w, (_lines-1) * dist + lw);
114 
115       if (_lines == 1) {
116             qreal extraSize = _spatium;
117             bbox().adjust(0, -extraSize, 0, extraSize);
118             }
119       else if (_lines == 0) {
120             bbox().adjust(0, -2 * dist, 0, 2*dist);
121             }
122 
123       lines.clear();
124       for (int i = 0; i < _lines; ++i) {
125             lines.push_back(QLineF(x1, y, x2, y));
126             y += dist;
127             }
128       }
129 
130 //---------------------------------------------------------
131 //   layoutPartialWidth
132 ///   Layout staff lines for the specified width only, aligned
133 ///   to the left or right of the measure
134 //---------------------------------------------------------
135 
layoutPartialWidth(qreal w,qreal wPartial,bool alignRight)136 void StaffLines::layoutPartialWidth(qreal w, qreal wPartial, bool alignRight)
137       {
138       const Staff* s = staff();
139       qreal _spatium = spatium();
140       wPartial *= spatium();
141       qreal dist     = _spatium;
142       setPos(QPointF(0.0, 0.0));
143       int _lines;
144       if (s) {
145             setMag(s->mag(measure()->tick()));
146             setColor(s->color(measure()->tick()));
147             const StaffType* st = s->staffType(measure()->tick());
148             dist         *= st->lineDistance().val();
149             _lines        = st->lines();
150             rypos()       = st->yoffset().val() * _spatium;
151             }
152       else {
153             _lines = 5;
154             setColor(MScore::defaultColor);
155             }
156       lw       = score()->styleS(Sid::staffLineWidth).val() * _spatium;
157       qreal x1 = pos().x();
158       qreal x2 = x1 + w;
159       qreal y  = pos().y();
160       bbox().setRect(x1, -lw * .5 + y, w, (_lines-1) * dist + lw);
161 
162       if (_lines == 1) {
163             qreal extraSize = _spatium;
164             bbox().adjust(0, -extraSize, 0, extraSize);
165       }
166 
167       lines.clear();
168       for (int i = 0; i < _lines; ++i) {
169             if (alignRight)
170                   lines.push_back(QLineF(x2-wPartial, y, x2, y));
171             else
172                   lines.push_back(QLineF(x1, y, x1 + wPartial, y));
173             y += dist;
174             }
175       }
176 
177 //---------------------------------------------------------
178 //   draw
179 //---------------------------------------------------------
180 
draw(QPainter * painter) const181 void StaffLines::draw(QPainter* painter) const
182       {
183       painter->setPen(QPen(curColor(), lw, Qt::SolidLine, Qt::FlatCap));
184       painter->drawLines(lines);
185       }
186 
187 //---------------------------------------------------------
188 //   y1
189 //---------------------------------------------------------
190 
y1() const191 qreal StaffLines::y1() const
192       {
193       System* system = measure()->system();
194 /*      if (system == 0 || staffIdx() >= system->staves()->size())
195             return 0.0;
196       */
197       return system->staff(staffIdx())->y() + ipos().y();
198       }
199 
200 }
201 
202 
203