1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2013-15 Werner Schweer & others
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 "textcursor.h"
14
15 #include "libmscore/input.h"
16 #include "libmscore/measure.h"
17 #include "libmscore/page.h"
18 #include "libmscore/score.h"
19 #include "libmscore/segment.h"
20 #include "libmscore/staff.h"
21 #include "libmscore/stafftype.h"
22 #include "libmscore/sym.h"
23 #include "libmscore/system.h"
24
25 #include "scoreview.h"
26
27 namespace Ms {
28
29 //---------------------------------------------------------
30 // PositionCursor
31 //---------------------------------------------------------
32
setType(CursorType t)33 void PositionCursor::setType(CursorType t)
34 {
35 _type = t;
36 if (_type == CursorType::LOOP_IN) {
37 // QColor cIn(Qt::green);
38 QColor cIn(0x2456aa);
39 // cIn.setAlpha(90);
40 setColor(cIn);
41 }
42 else if (_type == CursorType::LOOP_OUT) {
43 // QColor cOut(Qt::red);
44 QColor cOut(0x2456aa);
45 // cOut.setAlpha(90);
46 setColor(cOut);
47 }
48 }
49
50 //---------------------------------------------------------
51 // paint
52 //---------------------------------------------------------
53
paint(QPainter * p)54 void PositionCursor::paint(QPainter* p)
55 {
56 if (!visible())
57 return;
58 QPointF points[3];
59 qreal h = _sv->score()->spatium() * 2;
60
61 qreal x = _rect.left();
62 qreal y = _rect.top();
63
64 switch(_type) {
65 case CursorType::LOOP_IN: // draw a right-pointing triangle
66 {
67 qreal tx = x - 1.0;
68 p->setPen(QPen(_color, 2.0, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
69 p->drawLine(x, y, x, _rect.bottom());
70 points[0] = QPointF(tx, y);
71 points[1] = QPointF(tx, y + h);
72 points[2] = QPointF(tx + h, y + h * .5);
73 p->setBrush(_color);
74 p->drawConvexPolygon(points, 3);
75 }
76 break;
77 case CursorType::LOOP_OUT: // draw a left-pointing triangle
78 p->setPen(QPen(_color, 2.0, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
79 p->drawLine(x, y, x, _rect.bottom());
80 points[0] = QPointF(x, y);
81 points[1] = QPointF(x, y + h);
82 points[2] = QPointF(x - h, y + h * .5);
83 p->setBrush(_color);
84 p->drawConvexPolygon(points, 3);
85 break;
86 default: // fill the rectangle and add TAB string marks, if required
87 p->fillRect(_rect, color());
88 if (_sv->score()->noteEntryMode()) {
89 int track = _sv->score()->inputTrack();
90 if (track >= 0) {
91 Staff* staff = _sv->score()->staff(track2staff(track));
92 const StaffType* staffType = staff->staffType(Fraction(0,1));
93 if (staffType && staffType->group() == StaffGroup::TAB)
94 staffType->drawInputStringMarks(p, _sv->score()->inputState().string(),
95 track2voice(track), _rect);
96 }
97 }
98 break;
99 }
100 }
101
102 //---------------------------------------------------------
103 // bbox
104 //---------------------------------------------------------
105
bbox() const106 QRectF PositionCursor::bbox() const
107 {
108 QRectF r;
109 qreal h = _sv->score()->spatium() * 2;
110
111 switch(_type) {
112 case CursorType::LOOP_IN:
113 r.setRect(_rect.x(), _rect.y(), h, _rect.height());
114 break;
115 case CursorType::LOOP_OUT:
116 r.setRect(_rect.x() - h, _rect.y(), h, _rect.height());
117 break;
118 default:
119 r = _rect;
120 break;
121 }
122 return r.adjusted(-2, -2, 2, 2);
123 }
124
125
126 //---------------------------------------------------------
127 // move
128 //---------------------------------------------------------
129
move(const Fraction & t)130 void PositionCursor::move(const Fraction& t)
131 {
132 Fraction tick(t);
133 QRectF r(bbox());
134 //
135 // set mark height for whole system
136 //
137 if (_type == CursorType::LOOP_OUT && tick > Fraction(0,1))
138 tick -= Fraction::fromTicks(1); // tick--
139 Score* score = _sv->score();
140 Measure* measure = score->tick2measureMM(tick);
141 if (measure == 0)
142 return;
143 qreal x = 0.0;
144 const Fraction offset = {0,1}; //??
145
146 Segment* s;
147 for (s = measure->first(SegmentType::ChordRest); s;) {
148 Fraction t1 = s->tick();
149 int x1 = s->canvasPos().x();
150 qreal x2;
151 Fraction t2;
152 Segment* ns = s->next(SegmentType::ChordRest);
153 if (ns) {
154 t2 = ns->tick();
155 x2 = ns->canvasPos().x();
156 }
157 else {
158 t2 = measure->endTick();
159 x2 = measure->canvasPos().x() + measure->width();
160 }
161 t1 += offset;
162 t2 += offset;
163 if (tick >= t1 && tick < t2) {
164 Fraction dt = t2 - t1;
165 qreal dx = x2 - x1;
166 x = x1 + dx * (tick-t1).ticks() / dt.ticks();
167 break;
168 }
169 s = ns;
170 }
171 if (s == 0)
172 return;
173
174 System* system = measure->system();
175 if (system == 0 || system->page() == 0)
176 return;
177 double y = system->staffYpage(0) + system->page()->pos().y();
178 double _spatium = score->spatium();
179
180 qreal mag = _spatium / SPATIUM20;
181 double w = (_spatium * 2.0 + score->scoreFont()->width(SymId::noteheadBlack, mag))/3;
182 double h = 6 * _spatium;
183 //
184 // set cursor height for whole system
185 //
186 double y2 = 0.0;
187
188 for (int i = 0; i < score->nstaves(); ++i) {
189 SysStaff* ss = system->staff(i);
190 if (!ss->show() || !score->staff(i)->show())
191 continue;
192 y2 = ss->y() + ss->bbox().height();
193 }
194 h += y2;
195 y -= 3 * _spatium;
196
197 if (_type == CursorType::LOOP_IN) {
198 x = x - _spatium + w/1.5;
199 }
200 else {
201 x = x - _spatium * .5;
202 }
203 _tick = tick;
204 _rect = QRectF(x, y, w, h);
205 _sv->update(_sv->matrix().mapRect(r | bbox()).toRect().adjusted(-1,-1,1,1));
206 }
207 }
208
209