1 //=============================================================================
2 // MusE Score
3 // Linux Music Score Editor
4 //
5 // Copyright (C) 2009 Werner Schweer and 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 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "ruler.h"
21 #include "libmscore/score.h"
22
23 namespace Ms {
24
25 #if 0 // yet(?) unused
26 static const int MAP_OFFSET = 480;
27 #endif
28
29 QPixmap* Ruler::markIcon[3];
30
31 static const char* rmark_xpm[]={
32 "18 18 2 1",
33 "# c #0000ff",
34 ". c None",
35 "..................",
36 "..................",
37 "..................",
38 "..................",
39 "..................",
40 "..................",
41 "..................",
42 "........##########",
43 "........#########.",
44 "........########..",
45 "........#######...",
46 "........######....",
47 "........#####.....",
48 "........####......",
49 "........###.......",
50 "........##........",
51 "........##........",
52 "........##........"};
53 static const char* lmark_xpm[]={
54 "18 18 2 1",
55 "# c #0000ff",
56 ". c None",
57 "..................",
58 "..................",
59 "..................",
60 "..................",
61 "..................",
62 "..................",
63 "..................",
64 "##########........",
65 ".#########........",
66 "..########........",
67 "...#######........",
68 "....######........",
69 ".....#####........",
70 "......####........",
71 ".......###........",
72 "........##........",
73 "........##........",
74 "........##........"};
75 static const char* cmark_xpm[]={
76 "18 18 2 1",
77 "# c #ff0000",
78 ". c None",
79 "..................",
80 "..................",
81 "..................",
82 "..................",
83 "..................",
84 "..................",
85 "..................",
86 "##################",
87 ".################.",
88 "..##############..",
89 "...############...",
90 "....##########....",
91 ".....########.....",
92 "......######......",
93 ".......####.......",
94 "........##........",
95 "........##........",
96 "........##........"};
97
98
99 //---------------------------------------------------------
100 // Ruler
101 //---------------------------------------------------------
102
Ruler(QWidget * parent)103 Ruler::Ruler(QWidget* parent)
104 : QWidget(parent)
105 {
106 if (markIcon[0] == 0) {
107 markIcon[0] = new QPixmap(cmark_xpm);
108 markIcon[1] = new QPixmap(lmark_xpm);
109 markIcon[2] = new QPixmap(rmark_xpm);
110 }
111 setMouseTracking(true);
112 _score = nullptr;
113 _locator = nullptr;
114 magStep = 0;
115 _xpos = 0;
116 _xmag = 0.1;
117 _timeType = TType::TICKS;
118 _font2.setPixelSize(14);
119 _font2.setBold(true);
120 _font1.setPixelSize(10);
121 }
122
123 //---------------------------------------------------------
124 // setScore
125 //---------------------------------------------------------
126
setScore(Score * s,Pos * lc)127 void Ruler::setScore(Score* s, Pos* lc)
128 {
129 _score = s;
130 _locator = lc;
131 if (_score)
132 _cursor.setContext(_score->tempomap(), _score->sigmap());
133 setEnabled(_score != 0);
134 }
135
136 //---------------------------------------------------------
137 // setXmag
138 //---------------------------------------------------------
139
setMag(double x,double)140 void Ruler::setMag(double x, double /*y*/)
141 {
142 if (_xmag != x) {
143 _xmag = x;
144
145 int tpix = (480 * 4) * _xmag;
146 magStep = 0;
147 if (tpix < 64)
148 magStep = 1;
149 if (tpix < 32)
150 magStep = 2;
151 if (tpix <= 16)
152 magStep = 3;
153 if (tpix < 8)
154 magStep = 4;
155 if (tpix <= 4)
156 magStep = 5;
157 if (tpix <= 2)
158 magStep = 6;
159 update();
160 }
161 }
162
163 //---------------------------------------------------------
164 // setXpos
165 //---------------------------------------------------------
166
setXpos(int val)167 void Ruler::setXpos(int val)
168 {
169 _xpos = val;
170 update();
171 }
172
173 //---------------------------------------------------------
174 // pix2pos
175 //---------------------------------------------------------
176
pix2pos(int x) const177 Pos Ruler::pix2pos(int x) const
178 {
179 int val = lrint((x + 5 + _xpos)/_xmag - 480);
180 if (val < 0)
181 val = 0;
182 return Pos(_score->tempomap(), _score->sigmap(), val, _timeType);
183 }
184
185 //---------------------------------------------------------
186 // pos2pix
187 //---------------------------------------------------------
188
pos2pix(const Pos & p) const189 int Ruler::pos2pix(const Pos& p) const
190 {
191 // return lrint((p.time(_timeType) + 480) * _xmag) - _xpos - 5;
192 return lrint((p.time(_timeType) + 480) * _xmag) - _xpos - 1;
193 }
194
195 //---------------------------------------------------------
196 // paintEvent
197 //---------------------------------------------------------
198
paintEvent(QPaintEvent * e)199 void Ruler::paintEvent(QPaintEvent* e)
200 {
201 QPainter p(this);
202 const QRect& r = e->rect();
203
204 static const int mag[7] = {
205 1, 1, 2, 5, 10, 20, 50
206 };
207
208 int x = r.x();
209 int w = r.width();
210 int y = rulerHeight - 16;
211 int h = 16; // 14;
212 int y1 = r.y();
213 int rh = r.height();
214 if (y1 < rulerHeight) {
215 rh -= rulerHeight - y1;
216 y1 = rulerHeight;
217 }
218 int y2 = y1 + rh;
219
220 if (x < (-_xpos))
221 x = -_xpos;
222
223 if (!_score)
224 return;
225
226 Pos pos1 = pix2pos(x);
227 Pos pos2 = pix2pos(x+w);
228
229 //---------------------------------------------------
230 // draw raster
231 //---------------------------------------------------
232
233 int bar1, bar2, beat1, tick;
234
235 pos1.mbt(&bar1, &beat1, &tick);
236 pos2.mbt(&bar2, &beat1, &tick);
237
238 int n = mag[magStep];
239
240 bar1 = (bar1 / n) * n; // round down
241 if (bar1 && n >= 2)
242 bar1 -= 1;
243 bar2 = ((bar2 + n - 1) / n) * n; // round up
244
245 for (int bar = bar1; bar <= bar2;) {
246 Pos stick(_score->tempomap(), _score->sigmap(), bar, 0, 0);
247 if (magStep) {
248 p.setFont(_font2);
249 int x1 = pos2pix(stick);
250 QString s;
251 s.setNum(bar + 1);
252
253 p.setPen(Qt::black);
254 p.drawLine(x1, y, x1, y + h);
255 QRect r1 = QRect(x1+2, y, 1000, h);
256 p.drawText(r1, Qt::AlignLeft | Qt::AlignVCenter, s);
257 p.setPen(Qt::lightGray);
258 if (x1 > 0)
259 p.drawLine(x1, y1, x1, y2);
260 }
261 else {
262 SigEvent sig = stick.timesig();
263 int z = sig.timesig().numerator();
264 for (int beat = 0; beat < z; beat++) {
265 Pos xx(_score->tempomap(), _score->sigmap(), bar, beat, 0);
266 int xp = pos2pix(xx);
267 if (xp < 0)
268 continue;
269 QString s;
270 QRect r1(xp+2, y + 1, 1000, h);
271 int y3;
272 int num;
273 if (beat == 0) {
274 num = bar + 1;
275 y3 = y + 2;
276 p.setFont(_font2);
277 }
278 else {
279 num = beat + 1;
280 y3 = y + 8;
281 p.setFont(_font1);
282 r1.moveTop(r1.top() + 1);
283 }
284 s.setNum(num);
285 p.setPen(Qt::black);
286 p.drawLine(xp, y3, xp, y+h);
287 p.drawText(r1, Qt::AlignLeft | Qt::AlignVCenter, s);
288 p.setPen(beat == 0 ? Qt::lightGray : Qt::gray);
289 if (xp > 0)
290 p.drawLine(xp, y1, xp, y2);
291 }
292 }
293 if (bar == 0 && n >= 2)
294 bar += (n-1);
295 else
296 bar += n;
297 }
298 //
299 // draw mouse cursor marker
300 //
301 p.setPen(Qt::black);
302 if (_cursor.valid()) {
303 int xp = pos2pix(_cursor);
304 if (xp >= x && xp < x+w)
305 p.drawLine(xp, 0, xp, rulerHeight);
306 }
307 static const QColor lcColors[3] = { Qt::red, Qt::blue, Qt::blue };
308 for (int i = 0; i < 3; ++i) {
309 if (!_locator[i].valid())
310 continue;
311 p.setPen(lcColors[i]);
312 int xp = pos2pix(_locator[i]);
313 QPixmap* pm = markIcon[i];
314 // int pw = (pm->width() + 1) / 2;
315 int pw = pm->width() / 2;
316 int x1 = x - pw;
317 int x2 = x + w + pw;
318 if (xp >= x1 && xp < x2)
319 p.drawPixmap(xp - pw, y-2, *pm);
320 }
321 }
322
323 //---------------------------------------------------------
324 // mousePressEvent
325 //---------------------------------------------------------
326
mousePressEvent(QMouseEvent * e)327 void Ruler::mousePressEvent(QMouseEvent* e)
328 {
329 moveLocator(e);
330 }
331
332 //---------------------------------------------------------
333 // mouseMoveEvent
334 //---------------------------------------------------------
335
mouseMoveEvent(QMouseEvent * e)336 void Ruler::mouseMoveEvent(QMouseEvent* e)
337 {
338 moveLocator(e);
339 }
340
341 //---------------------------------------------------------
342 // moveLocator
343 //---------------------------------------------------------
344
moveLocator(QMouseEvent * e)345 void Ruler::moveLocator(QMouseEvent* e)
346 {
347 Pos pos(pix2pos(e->pos().x()));
348 if (e->buttons() & Qt::LeftButton)
349 emit locatorMoved(0, pos);
350 else if (e->buttons() & Qt::MidButton)
351 emit locatorMoved(1, pos);
352 else if (e->buttons() & Qt::RightButton)
353 emit locatorMoved(2, pos);
354 }
355
356 //---------------------------------------------------------
357 // leaveEvent
358 //---------------------------------------------------------
359
leaveEvent(QEvent *)360 void Ruler::leaveEvent(QEvent*)
361 {
362 _cursor.setInvalid();
363 emit posChanged(_cursor);
364 update();
365 }
366
367 //---------------------------------------------------------
368 // setPos
369 //---------------------------------------------------------
370
setPos(const Pos & pos)371 void Ruler::setPos(const Pos& pos)
372 {
373 if (_cursor != pos) {
374 int x1 = pos2pix(_cursor);
375 int x2 = pos2pix(pos);
376 if (x1 > x2) {
377 int tmp = x2;
378 x2 = x1;
379 x1 = tmp;
380 }
381 update(QRect(x1-1, 0, x2-x1+2, height()));
382 _cursor = pos;
383 }
384 }
385 }
386
387