385 lines
11 KiB
C++
385 lines
11 KiB
C++
//=============================================================================
|
|
// MusE Score
|
|
// Linux Music Score Editor
|
|
// $Id:$
|
|
//
|
|
// Copyright (C) 2009 Werner Schweer and others
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License version 2.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
//=============================================================================
|
|
|
|
#include "ruler.h"
|
|
#include "libmscore/score.h"
|
|
|
|
namespace Ms {
|
|
|
|
#if 0 // yet(?) unused
|
|
static const int MAP_OFFSET = 480;
|
|
#endif
|
|
|
|
QPixmap* Ruler::markIcon[3];
|
|
|
|
static const char* rmark_xpm[]={
|
|
"18 18 2 1",
|
|
"# c #0000ff",
|
|
". c None",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"........##########",
|
|
"........#########.",
|
|
"........########..",
|
|
"........#######...",
|
|
"........######....",
|
|
"........#####.....",
|
|
"........####......",
|
|
"........###.......",
|
|
"........##........",
|
|
"........##........",
|
|
"........##........"};
|
|
static const char* lmark_xpm[]={
|
|
"18 18 2 1",
|
|
"# c #0000ff",
|
|
". c None",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"##########........",
|
|
".#########........",
|
|
"..########........",
|
|
"...#######........",
|
|
"....######........",
|
|
".....#####........",
|
|
"......####........",
|
|
".......###........",
|
|
"........##........",
|
|
"........##........",
|
|
"........##........"};
|
|
static const char* cmark_xpm[]={
|
|
"18 18 2 1",
|
|
"# c #ff0000",
|
|
". c None",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"..................",
|
|
"##################",
|
|
".################.",
|
|
"..##############..",
|
|
"...############...",
|
|
"....##########....",
|
|
".....########.....",
|
|
"......######......",
|
|
".......####.......",
|
|
"........##........",
|
|
"........##........",
|
|
"........##........"};
|
|
|
|
|
|
//---------------------------------------------------------
|
|
// Ruler
|
|
//---------------------------------------------------------
|
|
|
|
Ruler::Ruler(QWidget* parent)
|
|
: QWidget(parent)
|
|
{
|
|
if (markIcon[0] == 0) {
|
|
markIcon[0] = new QPixmap(cmark_xpm);
|
|
markIcon[1] = new QPixmap(lmark_xpm);
|
|
markIcon[2] = new QPixmap(rmark_xpm);
|
|
}
|
|
setMouseTracking(true);
|
|
magStep = 0;
|
|
_xpos = 0;
|
|
_xmag = 0.1;
|
|
_timeType = TType::TICKS;
|
|
_font2.setPixelSize(14);
|
|
_font2.setBold(true);
|
|
_font1.setPixelSize(10);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setScore
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::setScore(Score* s, Pos* lc)
|
|
{
|
|
_score = s;
|
|
_locator = lc;
|
|
if (_score)
|
|
_cursor.setContext(_score->tempomap(), _score->sigmap());
|
|
setEnabled(_score != 0);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setXmag
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::setMag(double x, double /*y*/)
|
|
{
|
|
if (_xmag != x) {
|
|
_xmag = x;
|
|
|
|
int tpix = (480 * 4) * _xmag;
|
|
magStep = 0;
|
|
if (tpix < 64)
|
|
magStep = 1;
|
|
if (tpix < 32)
|
|
magStep = 2;
|
|
if (tpix <= 16)
|
|
magStep = 3;
|
|
if (tpix < 8)
|
|
magStep = 4;
|
|
if (tpix <= 4)
|
|
magStep = 5;
|
|
if (tpix <= 2)
|
|
magStep = 6;
|
|
update();
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setXpos
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::setXpos(int val)
|
|
{
|
|
_xpos = val;
|
|
update();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// pix2pos
|
|
//---------------------------------------------------------
|
|
|
|
Pos Ruler::pix2pos(int x) const
|
|
{
|
|
int val = lrint((x + 5 + _xpos)/_xmag - 480);
|
|
if (val < 0)
|
|
val = 0;
|
|
return Pos(_score->tempomap(), _score->sigmap(), val, _timeType);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// pos2pix
|
|
//---------------------------------------------------------
|
|
|
|
int Ruler::pos2pix(const Pos& p) const
|
|
{
|
|
// return lrint((p.time(_timeType) + 480) * _xmag) - _xpos - 5;
|
|
return lrint((p.time(_timeType) + 480) * _xmag) - _xpos - 1;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// paintEvent
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::paintEvent(QPaintEvent* e)
|
|
{
|
|
QPainter p(this);
|
|
const QRect& r = e->rect();
|
|
|
|
static const int mag[7] = {
|
|
1, 1, 2, 5, 10, 20, 50
|
|
};
|
|
|
|
int x = r.x();
|
|
int w = r.width();
|
|
int y = rulerHeight - 16;
|
|
int h = 16; // 14;
|
|
int y1 = r.y();
|
|
int rh = r.height();
|
|
if (y1 < rulerHeight) {
|
|
rh -= rulerHeight - y1;
|
|
y1 = rulerHeight;
|
|
}
|
|
int y2 = y1 + rh;
|
|
|
|
if (x < (-_xpos))
|
|
x = -_xpos;
|
|
|
|
if (!_score)
|
|
return;
|
|
|
|
Pos pos1 = pix2pos(x);
|
|
Pos pos2 = pix2pos(x+w);
|
|
|
|
//---------------------------------------------------
|
|
// draw raster
|
|
//---------------------------------------------------
|
|
|
|
int bar1, bar2, beat, tick;
|
|
|
|
pos1.mbt(&bar1, &beat, &tick);
|
|
pos2.mbt(&bar2, &beat, &tick);
|
|
|
|
int n = mag[magStep];
|
|
|
|
bar1 = (bar1 / n) * n; // round down
|
|
if (bar1 && n >= 2)
|
|
bar1 -= 1;
|
|
bar2 = ((bar2 + n - 1) / n) * n; // round up
|
|
|
|
for (int bar = bar1; bar <= bar2;) {
|
|
Pos stick(_score->tempomap(), _score->sigmap(), bar, 0, 0);
|
|
if (magStep) {
|
|
p.setFont(_font2);
|
|
int x = pos2pix(stick);
|
|
QString s;
|
|
s.setNum(bar + 1);
|
|
|
|
p.setPen(Qt::black);
|
|
p.drawLine(x, y, x, y + h);
|
|
QRect r = QRect(x+2, y, 1000, h);
|
|
p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, s);
|
|
p.setPen(Qt::lightGray);
|
|
if (x > 0)
|
|
p.drawLine(x, y1, x, y2);
|
|
}
|
|
else {
|
|
SigEvent sig = stick.timesig();
|
|
int z = sig.timesig().numerator();
|
|
for (int beat = 0; beat < z; beat++) {
|
|
Pos xx(_score->tempomap(), _score->sigmap(), bar, beat, 0);
|
|
int xp = pos2pix(xx);
|
|
if (xp < 0)
|
|
continue;
|
|
QString s;
|
|
QRect r(xp+2, y + 1, 1000, h);
|
|
int y3;
|
|
int num;
|
|
if (beat == 0) {
|
|
num = bar + 1;
|
|
y3 = y + 2;
|
|
p.setFont(_font2);
|
|
}
|
|
else {
|
|
num = beat + 1;
|
|
y3 = y + 8;
|
|
p.setFont(_font1);
|
|
r.moveTop(r.top() + 1);
|
|
}
|
|
s.setNum(num);
|
|
p.setPen(Qt::black);
|
|
p.drawLine(xp, y3, xp, y+h);
|
|
p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, s);
|
|
p.setPen(beat == 0 ? Qt::lightGray : Qt::gray);
|
|
if (xp > 0)
|
|
p.drawLine(xp, y1, xp, y2);
|
|
}
|
|
}
|
|
if (bar == 0 && n >= 2)
|
|
bar += (n-1);
|
|
else
|
|
bar += n;
|
|
}
|
|
//
|
|
// draw mouse cursor marker
|
|
//
|
|
p.setPen(Qt::black);
|
|
if (_cursor.valid()) {
|
|
int xp = pos2pix(_cursor);
|
|
if (xp >= x && xp < x+w)
|
|
p.drawLine(xp, 0, xp, rulerHeight);
|
|
}
|
|
static const QColor lcColors[3] = { Qt::red, Qt::blue, Qt::blue };
|
|
for (int i = 0; i < 3; ++i) {
|
|
if (!_locator[i].valid())
|
|
continue;
|
|
p.setPen(lcColors[i]);
|
|
int xp = pos2pix(_locator[i]);
|
|
QPixmap* pm = markIcon[i];
|
|
// int pw = (pm->width() + 1) / 2;
|
|
int pw = pm->width() / 2;
|
|
int x1 = x - pw;
|
|
int x2 = x + w + pw;
|
|
if (xp >= x1 && xp < x2)
|
|
p.drawPixmap(xp - pw, y-2, *pm);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// mousePressEvent
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::mousePressEvent(QMouseEvent* e)
|
|
{
|
|
moveLocator(e);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// mouseMoveEvent
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::mouseMoveEvent(QMouseEvent* e)
|
|
{
|
|
moveLocator(e);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// moveLocator
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::moveLocator(QMouseEvent* e)
|
|
{
|
|
Pos pos(pix2pos(e->pos().x()));
|
|
if (e->buttons() & Qt::LeftButton)
|
|
emit locatorMoved(0, pos);
|
|
else if (e->buttons() & Qt::MidButton)
|
|
emit locatorMoved(1, pos);
|
|
else if (e->buttons() & Qt::RightButton)
|
|
emit locatorMoved(2, pos);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// leaveEvent
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::leaveEvent(QEvent*)
|
|
{
|
|
_cursor.setInvalid();
|
|
emit posChanged(_cursor);
|
|
update();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setPos
|
|
//---------------------------------------------------------
|
|
|
|
void Ruler::setPos(const Pos& pos)
|
|
{
|
|
if (_cursor != pos) {
|
|
int x1 = pos2pix(_cursor);
|
|
int x2 = pos2pix(pos);
|
|
if (x1 > x2) {
|
|
int tmp = x2;
|
|
x2 = x1;
|
|
x1 = tmp;
|
|
}
|
|
update(QRect(x1-1, 0, x2-x1+2, height()));
|
|
_cursor = pos;
|
|
}
|
|
}
|
|
}
|
|
|