summaryrefslogtreecommitdiff
path: root/muse2/awl/tcanvas.cpp
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2010-11-28 21:14:50 +0000
committerTim E. Real <termtech@rogers.com>2010-11-28 21:14:50 +0000
commit8dc8689a009a3702bf4135e628f9d63df8b2ea36 (patch)
treefea6d4781b06fabfb24255751df95de750099830 /muse2/awl/tcanvas.cpp
parentb121a3b91f0e288934c4d78161ff1d20f96ff861 (diff)
Added AWL files
Diffstat (limited to 'muse2/awl/tcanvas.cpp')
-rw-r--r--muse2/awl/tcanvas.cpp1871
1 files changed, 1871 insertions, 0 deletions
diff --git a/muse2/awl/tcanvas.cpp b/muse2/awl/tcanvas.cpp
new file mode 100644
index 00000000..6ec4f68f
--- /dev/null
+++ b/muse2/awl/tcanvas.cpp
@@ -0,0 +1,1871 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by 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 "tcanvas.h"
+#include "al/al.h"
+#include "al/sig.h"
+#include "al/tempo.h"
+#include "../muse/gconfig.h"
+#include "../muse/icons.h"
+
+#include "metronom.xpm"
+#include "clock.xpm"
+
+#ifdef __APPLE__
+ inline double exp10(double a) { return pow(10.0, a); }
+#endif
+
+static QIcon* clockIcon;
+static QIcon* metronomIcon;
+
+FollowMode TimeCanvas::followMode = FOLLOW_JUMP;
+QPixmap* TimeCanvas::octave;
+QPixmap* TimeCanvas::mk1;
+QPixmap* TimeCanvas::mk2;
+QPixmap* TimeCanvas::mk3;
+QPixmap* TimeCanvas::mk4;
+
+enum DragType {
+ DRAG_RULER,
+ DRAG_CANVASA, DRAG_CANVAS_B,
+ DRAG_PANELA, DRAG_PANELB,
+ DRAG_OTHER
+ };
+
+//---------------------------------------------------------
+// TimeCanvas
+//---------------------------------------------------------
+
+TimeCanvas::TimeCanvas(TimeCanvasType t)
+ : QFrame()
+ {
+ setAttribute(Qt::WA_NoSystemBackground, true);
+
+ _yFit = false;
+ _tool = PointerTool;
+ type = t;
+ _timeType = AL::TICKS;
+ marker = 0;
+ showCursor = false;
+ ctrlHeight = 0;
+ curPitch = -1;
+ mouseInB = false;
+ dragType = DRAG_OTHER;
+ followPos = true;
+
+ // set default color
+ canvasBackgroundColor = QColor(0x71, 0x8d, 0xbe);
+
+ if (clockIcon == 0) {
+ clockIcon = new QIcon(QPixmap(clock_xpm));
+ metronomIcon = new QIcon(QPixmap(metronom_xpm));
+ }
+ button = Qt::NoButton;
+ grid = new QGridLayout;
+ grid->setMargin(0);
+ grid->setSpacing(1);
+ setLayout(grid);
+
+ _widget = new QWidget;
+ _widget->setAttribute(Qt::WA_NoSystemBackground);
+ _widget->setAttribute(Qt::WA_StaticContents);
+ _widget->installEventFilter(this);
+ _widget->setMouseTracking(true);
+ _widget->setAcceptDrops(true);
+
+ // allow to set slider position before slider range
+ // is known:
+
+ pos1.setTick(0);
+ pos2.setTick(INT_MAX);
+
+ hmag = new QSlider(Qt::Horizontal);
+ hmag->setRange(0, 100);
+ _xmagMin = 0.001;
+ _xmagMax = 0.3;
+ _xmag = 0.04;
+ hmag->setValue(xmag2s(_xmag));
+
+ vmag = 0;
+ if (type != TIME_CANVAS_DRUMEDIT) {
+ vmag = new QSlider(Qt::Vertical);
+ vmag->setRange(0, 100);
+ vmag->setPageStep(1);
+ }
+ _ymag = 1.0;
+
+ hbar = new QScrollBar(Qt::Horizontal);
+ hbar->setRange(0, INT_MAX);
+ vbar = new QScrollBar(Qt::Vertical);
+ timeTypeButton = new QToolButton;
+ timeTypeButton->setFixedSize(20, rulerHeight);
+ setTimeType1(AL::TICKS);
+ yRange = 0;
+
+ switch(type) {
+ case TIME_CANVAS_PIANOROLL:
+ _ymagMin = 0.5;
+ _ymagMax = 3.0;
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ initPianoroll();
+ break;
+ case TIME_CANVAS_DRUMEDIT:
+ _ymagMin = 1.0;
+ _ymagMax = 1.0;
+ yRange = drumHeight * 128;
+ break;
+ case TIME_CANVAS_WAVEEDIT:
+ _xmagMin = 0.001;
+ _xmagMax = 100.0;
+ _xmag = 0.04;
+ _ymagMin = 1.0;
+ _ymagMax = 10.0;
+ _ymag = 1.0;
+ break;
+ default:
+ _ymagMin = 1.0;
+ _ymagMax = 1.0;
+ break;
+ }
+ updateGeometry();
+ if (type == TIME_CANVAS_PIANOROLL || type == TIME_CANVAS_DRUMEDIT
+ || type == TIME_CANVAS_WAVEEDIT) {
+ addCtrlButton = new QPushButton(tr("Ctrl"), _widget);
+ addCtrlButton->setGeometry(1, 1, rPanelA.width()-4, rulerHeight-4);
+ addCtrlButton->setToolTip(tr("Add Controller View"));
+ connect(addCtrlButton, SIGNAL(clicked()), SLOT(addCtrlClicked()));
+ }
+
+ grid->addWidget(_widget, 0, 0, 3, 2);
+ grid->addWidget(hbar, 3, 0, Qt::AlignVCenter);
+ grid->addWidget(hmag, 3, 1, Qt::AlignVCenter);
+ grid->addWidget(timeTypeButton, 0, 2);
+ grid->addWidget(vbar, 1, 2, Qt::AlignHCenter);
+ if (vmag)
+ grid->addWidget(vmag, 2, 2, Qt::AlignHCenter);
+
+ grid->setColumnStretch(0, 100);
+ grid->setRowStretch(1, 100);
+
+ _raster = 0;
+ updateScrollBars();
+ connect(hbar, SIGNAL(valueChanged(int)), SLOT(moveX(int)));
+ connect(vbar, SIGNAL(valueChanged(int)), SLOT(moveY(int)));
+ connect(hmag, SIGNAL(valueChanged(int)), SLOT(scaleX(int)));
+ if (vmag)
+ connect(vmag, SIGNAL(valueChanged(int)), SLOT(scaleY(int)));
+ connect(timeTypeButton, SIGNAL(clicked()), SLOT(toggleTimeType()));
+ }
+
+//---------------------------------------------------------
+// resizeController
+//---------------------------------------------------------
+
+void TimeCanvas::resizeController(int h)
+ {
+ if (h == ctrlHeight)
+ return;
+ int updateH = h > ctrlHeight ? h : ctrlHeight;
+ ctrlHeight = h;
+ updateGeometry();
+ updateScrollBars();
+ widget()->update(0, widget()->height() - updateH, widget()->width(), updateH);
+ }
+
+//---------------------------------------------------------
+// eventFilter
+//---------------------------------------------------------
+
+bool TimeCanvas::eventFilter(QObject* obj, QEvent* event)
+ {
+ if (obj != _widget)
+ return QFrame::eventFilter(obj, event);
+
+ switch(event->type()) {
+ case QEvent::Paint:
+ {
+ QPainter p(_widget);
+ canvasPaintEvent(((QPaintEvent*)event)->rect(), p);
+ }
+ return true;
+
+ case QEvent::Resize:
+ updateGeometry();
+ updateScrollBars();
+ layout();
+ return false;
+
+ case QEvent::MouseButtonDblClick:
+ {
+ QMouseEvent* me = (QMouseEvent*)event;
+ QPoint p(me->pos());
+ button = me->button();
+ keyState = me->modifiers();
+ mouseDoubleClick(me);
+ }
+ return true;
+
+ case QEvent::MouseButtonPress:
+ {
+ QMouseEvent* me = (QMouseEvent*)event;
+ keyState = me->modifiers();
+ button = me->button();
+ QPoint p(me->pos());
+ int x = p.x() - rRuler.x();
+ bool shift = keyState & Qt::ShiftModifier;
+
+ if (rRuler.contains(p)) {
+ dragType = DRAG_RULER;
+ if (shift) {
+ AL::Pos pos(pix2pos(x));
+ if (button == Qt::LeftButton)
+ emit addMarker(pos);
+ else if (button == Qt::RightButton)
+ emit removeMarker(pos);
+ return true;
+ }
+ }
+ else {
+ dragType = DRAG_OTHER;
+ mousePress(me);
+ }
+ }
+ // go on with MouseMove
+
+ case QEvent::MouseMove:
+ {
+ QMouseEvent* me = (QMouseEvent*)event;
+ keyState = me->modifiers();
+ button = me->buttons();
+ QPoint p(me->pos());
+ AL::Pos pos(pix2pos(p.x()-rCanvasA.x()));
+
+ if (dragType == DRAG_OTHER) {
+ if (button == 0 && (rPanelB.contains(p) || rCanvasB.contains(p))) {
+ if (!mouseInB) {
+ mouseInB = true;
+ enterB();
+ }
+ }
+ else {
+ if (button == 0 && mouseInB) {
+ mouseInB = false;
+ leaveB();
+ }
+ }
+
+ if (showCursor && p.x() < rCanvasA.x()) {
+ showCursor = false;
+ widget()->update(rRuler);
+ emit cursorPos(cursor, showCursor);
+ }
+
+ if (p.x() >= rCanvasA.x() && (cursor != pos)) {
+ int x1 = pos2pix(cursor) + rCanvasA.x();
+ int x2 = pos2pix(pos) + rCanvasA.x();
+ QRect r1(x1-1, 0, 2, rRuler.height());
+ QRect r2(x2-1, 0, 2, rRuler.height());
+ widget()->update(rRuler & (r1 | r2));
+ cursor = pos;
+ showCursor = true;
+ emit cursorPos(cursor, showCursor);
+ }
+
+ if (rRuler.contains(p)) {
+ int b = me->buttons();
+ if (b == 0)
+ return true;
+ int i = 0;
+ if (b & Qt::MidButton)
+ i = 1;
+ else if (b & Qt::RightButton)
+ i = 2;
+ if (keyState & Qt::ShiftModifier)
+ emit addMarker(i);
+ emit posChanged(i, pos);
+ }
+ else {
+ mouseMove(p);
+ }
+ }
+ else if (dragType == DRAG_RULER) {
+ int b = me->buttons();
+ if (b == 0)
+ return true;
+ int i = 0;
+ if (b & Qt::MidButton)
+ i = 1;
+ else if (b & Qt::RightButton)
+ i = 2;
+ if (keyState & Qt::ShiftModifier)
+ emit addMarker(i);
+ emit posChanged(i, pos);
+ }
+ }
+ return true;
+
+ case QEvent::MouseButtonRelease:
+ {
+ QMouseEvent* me = (QMouseEvent*)event;
+ button = Qt::NoButton;
+ keyState = me->modifiers();
+ mouseRelease(me);
+ dragType = DRAG_OTHER;
+ }
+ return true;
+
+ case QEvent::DragEnter:
+ dragEnter((QDragEnterEvent*)event);
+ return true;
+
+ case QEvent::Drop:
+ drop((QDropEvent*)event);
+ return true;
+
+ case QEvent::DragMove:
+ dragMove((QDragMoveEvent*)event);
+ return true;
+
+ case QEvent::DragLeave:
+ dragLeave((QDragLeaveEvent*)event);
+ return true;
+
+ case QEvent::Leave:
+ {
+ emit cursorPos(cursor, false);
+ showCursor = false;
+ emit pitchChanged(-1);
+ curPitch = -1;
+ QRect r(rRuler);
+ if (!rPanelA.isEmpty())
+ r |= rPanelA;
+ widget()->update(r);
+
+ if (mouseInB) {
+ mouseInB = false;
+ // button = ((QMouseEvent*)event)->buttons();
+ leaveB();
+ }
+ }
+ return false;
+
+ case QEvent::Wheel:
+ {
+ QWheelEvent* e = (QWheelEvent*)event;
+ if (e->orientation() != Qt::Vertical)
+ return true;
+ if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) {
+ //
+ // xmag
+ //
+ int oldx = e->x() - rCanvasA.x();
+ AL::Pos pos(pix2pos(oldx));
+ int step = e->delta() / 120;
+ if (step > 0) {
+ for (int i = 0; i< step; ++i)
+ _xmag *= 1.1;
+ }
+ else {
+ for (int i = 0; i < -step; ++i)
+ _xmag *= 0.9;
+ }
+ if (_xmag < _xmagMin)
+ _xmag = _xmagMin;
+ else if (_xmag > _xmagMax)
+ _xmag = _xmagMax;
+ hmag->setValue(xmag2s(_xmag));
+ int newx = pos2pix(pos);
+ updateScrollBars();
+ hbar->setValue(wpos.x() + (newx - oldx));
+ updateRulerMag();
+ magChanged();
+ _widget->update();
+ }
+ else {
+ //
+ // scroll
+ //
+ int step = qMin(QApplication::wheelScrollLines() * vbar->singleStep(), vbar->pageStep());
+ int offset = e->delta() * step / 120;
+ if (vbar->invertedControls())
+ offset = -offset;
+ if (qAbs(offset) < 1)
+ return true;
+ vbar->setValue(vbar->value() + offset);
+ }
+ }
+ return true;
+ default:
+// printf("event %d missed\n", event->type());
+ break;
+ }
+ return false;
+ }
+
+
+
+void TimeCanvas::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down ||
+ e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)
+ keyboardNavigate(e);
+}
+
+//---------------------------------------------------------
+// moveX
+//---------------------------------------------------------
+
+void TimeCanvas::moveX(int x)
+ {
+ int dx = wpos.x() - x;
+ wpos.setX(x);
+
+ int wh = _widget->height();
+
+ if (type == TIME_CANVAS_PIANOROLL || type == TIME_CANVAS_DRUMEDIT
+ || TIME_CANVAS_WAVEEDIT) {
+ _widget->scroll(dx, 0, QRect(rCanvasA.x(), 0, rCanvasA.width(), wh));
+
+ //HACK:
+ // update controller names
+ int w = 100 + ((dx > 0) ? dx : 0);
+ _widget->update(rCanvasB.x(), rCanvasB.y(), w, rCanvasB.height());
+
+ //HACK:
+ // repaint rounded line end (splitter handle for controller
+ // canvas)
+ int x = rCanvasB.x() + rCanvasB.width() - 1;
+ w = 1;
+ if (dx < 0) {
+ x += dx;
+ w -= dx;
+ }
+ _widget->update(x, rCanvasB.y(), w, rCanvasB.height());
+ }
+ else
+ _widget->scroll(dx, 0);
+ emit contentsMoving(wpos.x(), wpos.y());
+ }
+
+//---------------------------------------------------------
+// moveY
+//---------------------------------------------------------
+
+void TimeCanvas::moveY(int y)
+ {
+ int dy = wpos.y() - y;
+ if (dy == 0)
+ return;
+ wpos.setY(y);
+
+ // dont move ruler:
+
+ int ww = _widget->width();
+ int wh = _widget->height();
+
+ QRect r(0, rulerHeight, ww, wh - rulerHeight - ctrlHeight);
+
+ _widget->scroll(0, dy, r);
+ emit contentsMoving(wpos.x(), wpos.y());
+ }
+
+//---------------------------------------------------------
+// setYPos
+//---------------------------------------------------------
+
+void TimeCanvas::setYPos(int y)
+ {
+ setWPos(QPoint(wpos.x(), y));
+ }
+
+//---------------------------------------------------------
+// setWPos
+//---------------------------------------------------------
+
+void TimeCanvas::setWPos(const QPoint& p)
+ {
+ if (wpos != p) {
+ wpos = p;
+ hbar->setValue(wpos.x());
+ vbar->setValue(wpos.y());
+ _widget->update();
+// QCoreApplication::flush();
+ }
+ }
+
+//---------------------------------------------------------
+// paintClockRuler
+//---------------------------------------------------------
+
+void TimeCanvas::paintClockRuler(QPainter& p, const QRect& r)
+ {
+ int x1 = r.x();
+ int x2 = x1 + r.width();
+
+ int y1 = r.y();
+ int rh = r.height();
+ if (y1 < rulerHeight) {
+ rh -= rulerHeight - y1;
+ y1 = rulerHeight;
+ }
+ int y2 = y1 + rh;
+
+ //---------------------------------------------------
+ // draw Marker
+ //---------------------------------------------------
+
+ int y = rulerHeight - 16;
+ p.setPen(Qt::black);
+ p.setFont(_font3);
+ QRect tr(r);
+ tr.setHeight(12);
+
+ if (marker) {
+ for (AL::iMarker m = marker->begin(); m != marker->end(); ++m) {
+ int xp = mapx(int(m->second.frame()));
+ if (xp > x2)
+ break;
+ AL::iMarker mm = m;
+ ++mm;
+ int xe = x2;
+ if (mm != marker->end()) {
+ xe = mapx(mm->first);
+ }
+ QRect tr(xp, 0, x2 - xp, 11);
+ if (m->second.current()) {
+ p.fillRect(tr, Qt::white);
+ }
+ if (r.intersects(tr)) {
+ int x2;
+ AL::iMarker mm = m;
+ ++mm;
+ if (mm != marker->end())
+ x2 = mapx(mm->first);
+ else
+ x2 = xp+200;
+ QRect r = QRect(xp+10, 0, x2-xp, 12);
+ p.drawPixmap(xp, 0, *flagIconS);
+ p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter, m->second.name());
+ }
+ }
+ }
+
+ p.setPen(Qt::black);
+ if (showCursor) {
+ int xp = pos2pix(cursor);
+ if (xp >= x1 && xp < x2)
+ p.drawLine(xp, 0, xp, rulerHeight);
+ }
+
+ AL::Pos p1(pix2pos(x1));
+ AL::Pos p2(pix2pos(x2));
+
+ int sec1 = p1.frame() / AL::sampleRate;
+ int sec2 = (p2.frame() + AL::sampleRate - 1) / AL::sampleRate;
+
+ int sw = lrint(AL::sampleRate * _xmag);
+
+ if (sw > 20) {
+ for (int sec = sec1; sec < sec2; ++sec) {
+ int min = sec / 60;
+ int sr = sec % 60;
+
+ int yy;
+ QString s;
+ if (sr == 0) {
+ p.setFont(_font2);
+ s.sprintf("%d:00", min);
+ yy = y;
+ }
+ else {
+ p.setFont(_font1);
+ s.sprintf("%02d", sr);
+ yy = y + 7;
+ }
+ int xp = pos2pix(AL::Pos(sec * AL::sampleRate, AL::FRAMES));
+// printf(" sec %d min %d sr %d xp %d\n", sec, min, sr, xp);
+ p.setPen(Qt::black);
+ p.drawLine(xp, yy, xp, rulerHeight);
+ p.drawText(xp + 2, rulerHeight - 4, s);
+ p.setPen(sr == 0 ? Qt::lightGray : Qt::gray);
+ p.drawLine(xp, y1, xp, y2);
+ }
+ }
+ else {
+ int min1 = sec1/60;
+ int min2 = (sec2+59)/60;
+ for (int min = min1; min < min2; ++min) {
+ QString s;
+ p.setFont(_font2);
+ s.sprintf("%d", min);
+ int xp = pos2pix(AL::Pos(min * AL::sampleRate * 60, AL::FRAMES));
+ p.setPen(Qt::black);
+ p.drawLine(xp, y, xp, rulerHeight);
+ p.drawText(xp + 2, rulerHeight - 4, s);
+ p.setPen(Qt::lightGray);
+ p.drawLine(xp, y1, xp, y2);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// updateRulerMag
+//---------------------------------------------------------
+
+void TimeCanvas::updateRulerMag()
+ {
+ int bar1, beat, tick;
+ pos1.mbt(&bar1, &beat, &tick);
+ AL::Pos stick(bar1, 0, 0);
+ AL::Pos ntick = AL::Pos(bar1 + 1, 0, 0);
+ int tpix = pos2pix(ntick) - pos2pix(stick);
+ metronomeRulerMag = 0;
+ if (tpix < 64)
+ metronomeRulerMag = 1;
+ if (tpix < 32)
+ metronomeRulerMag = 2;
+ if (tpix <= 16)
+ metronomeRulerMag = 3;
+ if (tpix < 8)
+ metronomeRulerMag = 4;
+ if (tpix <= 4)
+ metronomeRulerMag = 5;
+ if (tpix <= 2)
+ metronomeRulerMag = 6;
+ }
+
+//---------------------------------------------------------
+// paintMetronomRuler
+//---------------------------------------------------------
+
+void TimeCanvas::paintMetronomRuler(QPainter& p, const QRect& r)
+ {
+ static const int mag[7] = {
+ 1, 1, 2, 5, 10, 20, 50
+ };
+
+ int x = r.x();
+ int w = r.width();
+ int y = rulerHeight - 16;
+
+ p.setFont(_font3);
+
+ int h = 14;
+ int y1 = r.y();
+ int rh = r.height();
+ if (y1 < rulerHeight) {
+ rh -= rulerHeight - y1;
+ y1 = rulerHeight;
+ }
+ int y2 = y1 + rh;
+
+ if (x < (MAP_OFFSET - wpos.x()))
+ x = MAP_OFFSET - wpos.x();
+ AL::Pos pos1 = pix2pos(x);
+ AL::Pos pos2 = pix2pos(x+w);
+
+ if (marker) {
+ AL::iMarker start = marker->lower_bound(pos1.tick());
+ if (start != marker->begin())
+ --start;
+ AL::iMarker end = marker->lower_bound(pos2.tick());
+ for (AL::iMarker m = start; m != end; ++m) {
+ AL::Pos pm1(m->second);
+ AL::iMarker m2 = m;
+ ++m2;
+ AL::Pos pm2(pos2);
+ if (m2 != marker->end())
+ pm2 = m2->second;
+
+ int x1 = pos2pix(pm1);
+ int x2 = pos2pix(pm2);
+
+ if (pos[0] >= pm1 && (m2 == marker->end() || pos[0] < pm2))
+ p.fillRect(x1, 0, x2 - x1, 11, Qt::white);
+
+ QRect r = QRect(x1 + 10, 0, x2 - x1, 12);
+ p.drawPixmap(x1, 0, *flagIconS);
+ p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter, m->second.name());
+ }
+ }
+
+ //---------------------------------------------------
+ // draw raster
+ //---------------------------------------------------
+
+ int bar1, bar2, beat, tick;
+ pos1.mbt(&bar1, &beat, &tick);
+ pos2.mbt(&bar2, &beat, &tick);
+
+ int n = mag[metronomeRulerMag];
+
+ 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;) {
+ AL::Pos stick(bar, 0, 0);
+ if (metronomeRulerMag) {
+ 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 {
+ AL::TimeSignature sig = stick.timesig();
+ int z = sig.z;
+ for (int beat = 0; beat < z; beat++) {
+ AL::Pos xx(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 (showCursor) {
+ int xp = pos2pix(cursor);
+ if (xp >= x && xp < x+w)
+ p.drawLine(xp, 0, xp, rulerHeight-1);
+ }
+
+ }
+
+//---------------------------------------------------------
+// tempoChanged
+//---------------------------------------------------------
+
+void TimeCanvas::tempoChanged()
+ {
+ widget()->update(rCanvasA.x(), 0, rCanvasA.width(), widget()->height());
+ }
+
+//---------------------------------------------------------
+// canvasPaintEvent
+//---------------------------------------------------------
+
+void TimeCanvas::canvasPaintEvent(const QRect& r, QPainter& p)
+ {
+ if (r.intersects(rButton)) {
+ p.fillRect(rButton, QColor(0xe0, 0xe0, 0xe0));
+ p.setPen(QPen(Qt::black, 2));
+ int y = rButton.y() + rButton.height() - 1;
+ p.drawLine(rButton.x(), y, rButton.width(), y);
+ }
+ p.setRenderHint(QPainter::TextAntialiasing, true);
+
+ QRect par = r & rPanelA;
+ if (!(par.isEmpty() || rPanelA.isEmpty())) {
+ if (type == TIME_CANVAS_DRUMEDIT) {
+ paintDrumList(p, par);
+ }
+ else if (type == TIME_CANVAS_PIANOROLL) {
+ paintPiano(p, par);
+ }
+ else if (type == TIME_CANVAS_WAVEEDIT) {
+ p.fillRect(par, QColor(0xe0, 0xe0, 0xe0));
+ }
+ }
+
+ QRect pbr(r & rPanelB);
+ QRect hor(r & (rRuler | rCanvasA | rCanvasB));
+ QRect car(r & rCanvasA);
+ QRect cbr(r & rCanvasB);
+
+ bool drawPanelB = !(pbr.isEmpty() || rPanelB.isEmpty());
+ bool drawRuler = !(hor.isEmpty() || (rRuler.isEmpty() && rCanvasA.isEmpty() && rCanvasB.isEmpty()));
+ bool drawCanvasA = !(car.isEmpty() || rCanvasA.isEmpty());
+ bool drawCanvasB = !(cbr.isEmpty() || rCanvasB.isEmpty());
+
+ //
+ // draw canvas background
+ //
+
+ p.setClipRect(r);
+ p.setBrushOrigin(QPoint(car.x() + wpos.x(), car.y() + wpos.y()));
+ if (drawCanvasA) {
+ if (canvasBackgroundPixmap.isNull()) {
+ if (type == TIME_CANVAS_DRUMEDIT || type == TIME_CANVAS_PIANOROLL
+ || type == TIME_CANVAS_WAVEEDIT) {
+ QRect rr(car);
+ // paint inactive area different
+ // (darker)
+ QColor c = canvasBackgroundColor.darker(150);
+ int x1 = pos2pix(partPos1) + rCanvasA.x();
+ if (rr.x() < x1) {
+ QRect r(rr.x(), rr.y(), x1-rr.x(), rr.height());
+ p.fillRect(r, c);
+ rr.adjust(x1-rr.x(), 0, 0, 0);
+ }
+ int x2 = pos2pix(partPos2) + rCanvasA.x();
+ int xx2 = rr.x() + rr.width();
+ if (xx2 > x2) {
+ if (x2 < rr.x())
+ x2 = rr.x();
+ QRect r(x2, rr.y(), xx2-x2, rr.height());
+ p.fillRect(r, c);
+ rr.adjust(0, 0, -(xx2-x2), 0);
+ }
+ if (!rr.isEmpty()) {
+ p.fillRect(rr, canvasBackgroundColor);
+ }
+ }
+ else
+ p.fillRect(car, canvasBackgroundColor);
+ }
+ else {
+ p.drawTiledPixmap(car, canvasBackgroundPixmap,
+ car.topLeft() + QPoint(wpos));
+ }
+ }
+
+ if (drawCanvasB)
+ p.fillRect(cbr, canvasBackgroundColor);
+
+ //---------------------------------------------------
+ // draw Ruler
+ //---------------------------------------------------
+
+ if (drawRuler) {
+ QRect rrr(r & rRuler);
+ if (!rrr.isEmpty())
+ p.fillRect(rrr, QColor(0xe0, 0xe0, 0xe0));
+ int x1 = hor.x();
+ int x2 = x1 + hor.width();
+ int y1 = rulerHeight - 17;
+ int y2 = rulerHeight - 1;
+
+ p.setPen(QPen(Qt::black, 1));
+ p.drawLine(x1, y1, x2, y1);
+ p.setPen(QPen(Qt::black, 2));
+ p.drawLine(x1, y2, x2, y2);
+
+ QPoint off(rRuler.topLeft());
+ p.translate(off);
+ if (_timeType == AL::TICKS)
+ paintMetronomRuler(p, hor.translated(-off));
+ else
+ paintClockRuler(p, hor.translated(-off));
+ p.translate(-off);
+ }
+
+ if (drawCanvasA) {
+ p.setClipRect(car);
+ paintCanvas(p, car);
+ }
+ p.setRenderHint(QPainter::Antialiasing, false);
+ if (drawPanelB) {
+ p.setClipRect(pbr);
+ QPoint off(rPanelB.topLeft());
+ p.translate(off);
+ paintControllerPanel(p, pbr.translated(-off));
+ p.translate(-off);
+ }
+ if (drawCanvasB) {
+ p.setClipRect(cbr);
+ QPoint off(rCanvasB.topLeft());
+ p.translate(off);
+ paintControllerCanvas(p, cbr.translated(-off));
+ p.translate(-off);
+ }
+ //---------------------------------------------------
+ // draw marker
+ //---------------------------------------------------
+
+ int y1 = r.y();
+ int y2 = y1 + r.height();
+ if (drawRuler) {
+ p.setClipRect(hor);
+ int w = r.width();
+ int x = r.x();
+ int y = rulerHeight - 16;
+ QColor lcColors[3] = { Qt::red, Qt::blue, Qt::blue };
+
+ for (int i = 0; i < 3; ++i) {
+ p.setPen(lcColors[i]);
+ int xp = pos2pix(pos[i]) + rRuler.x();
+ QPixmap* pm = markIcon[i];
+ int pw = (pm->width() + 1) / 2;
+ int x1 = x - pw;
+ int x2 = x + w + pw;
+ if (xp >= x1 && xp < x2) {
+ p.drawPixmap(xp - pw, y-2, *pm);
+ p.drawLine(xp, y1, xp, y2);
+ }
+ }
+ }
+ if (marker) {
+ int yy1 = y1;
+ if (yy1 < rCanvasA.x())
+ yy1 = rCanvasA.x();
+ p.setPen(Qt::green);
+ AL::iMarker start = marker->lower_bound(pos1.tick());
+ if (start != marker->begin())
+ --start;
+ AL::iMarker end = marker->lower_bound(pos2.tick());
+ if (end != marker->end())
+ ++end;
+ for (AL::iMarker m = start; m != end; ++m) {
+ AL::Pos pm(m->second);
+ int x = pos2pix(pm) + rRuler.x();
+ p.drawLine(x, yy1, x, y2);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// paintCanvas
+//---------------------------------------------------------
+
+void TimeCanvas::paintCanvas(QPainter& p, const QRect& cr)
+ {
+ QPoint off(rCanvasA.topLeft());
+
+ if (type == TIME_CANVAS_PIANOROLL) {
+ paintPianorollHorizontalGrid(p, cr);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ }
+ else if (type == TIME_CANVAS_DRUMEDIT) {
+ paintDrumeditHorizontalGrid(p, cr);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ }
+ else
+ off = QPoint(rCanvasA.x(), rCanvasA.y() - wpos.y());
+ p.translate(off);
+ paint(p, cr.translated(-off));
+ p.resetMatrix();
+ }
+
+//---------------------------------------------------------
+// setLocatorPos
+//---------------------------------------------------------
+
+void TimeCanvas::setLocatorPos(int idx, const AL::Pos& val, bool follow)
+ {
+ if (pos[idx] == val)
+ return;
+ QFontMetrics fm(_font2);
+ int fw = fm.width("123") + 2;
+ int w = qMax(markIcon[idx]->width() + 2, fw);
+ int h = widget()->height();
+
+ int x = pos2pix(val);
+ if (idx == 0 && follow && followPos && followMode != FOLLOW_NO) {
+ int scroll = 0;
+ if (followMode == FOLLOW_JUMP) {
+ int x2 = rRuler.width() - 20;
+ if (x2 < 0)
+ x2 = rRuler.width();
+ if (x > x2) {
+ int x1 = 20;
+ if (x1 >= rRuler.width())
+ x1 = 0;
+ scroll = x - x1;
+ }
+ else if (x < 0) {
+ scroll = x - MAP_OFFSET;
+ }
+ }
+ else if (followMode == FOLLOW_CONTINUOUS) {
+ int x1 = rRuler.width() / 2;
+ if (x != x1) {
+ scroll = x - (rRuler.width() / 2);
+ }
+ }
+ if (scroll) {
+ moveX(wpos.x() + scroll);
+ hbar->setValue(wpos.x());
+ }
+ }
+
+ int offset = rRuler.x() - (w/2);
+ int x1 = pos2pix(pos[idx]);
+ int x2 = pos2pix(val);
+ QRect oR(x1 + offset, 0, w, h);
+ QRect nR(x2 + offset, 0, w, h);
+ pos[idx] = val;
+ widget()->update(oR | nR);
+ }
+
+//---------------------------------------------------------
+// setMag
+//---------------------------------------------------------
+
+void TimeCanvas::setMag(double x, double y)
+ {
+ if (_xmag == x && _ymag == y)
+ return;
+ _xmag = x;
+ _ymag = y;
+ if (vmag)
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ hmag->setValue(xmag2s(_xmag));
+ updateScrollBars();
+ updateRulerMag();
+ magChanged();
+ _widget->update();
+ }
+
+//---------------------------------------------------------
+// scaleX
+//---------------------------------------------------------
+
+void TimeCanvas::scaleX(int val)
+ {
+ _xmag = s2xmag(val);
+ updateScrollBars();
+ updateRulerMag();
+ magChanged();
+ _widget->update();
+ }
+
+//---------------------------------------------------------
+// scaleY
+//---------------------------------------------------------
+
+void TimeCanvas::scaleY(int val)
+ {
+ int y = lrint(wpos.y() / _ymag);
+ _ymag = (_ymagMax - _ymagMin) / 100.0 * val + _ymagMin;
+ y = lrint(y * _ymag);
+ wpos.setY(y);
+ updateScrollBars();
+ magChanged();
+ _widget->update();
+ }
+
+//---------------------------------------------------------
+// setRaster
+// r = 1 - no raster
+// 0 - measure raster
+// > 1 - tick raster
+//---------------------------------------------------------
+
+void TimeCanvas::setRaster(int r)
+ {
+ if (_raster != r) {
+ _raster = r;
+ _widget->update();
+ }
+ }
+
+//---------------------------------------------------------
+// setTimeRange
+//---------------------------------------------------------
+
+void TimeCanvas::setTimeRange(const AL::Pos& p1, const AL::Pos& p2)
+ {
+ if (pos1 == p1 && pos2 == p2)
+ return;
+ pos1 = p1;
+ pos2 = p2;
+ updateScrollBars();
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// setEndPos
+//---------------------------------------------------------
+
+void TimeCanvas::setEndPos(const AL::Pos& p2)
+ {
+ if (pos2 == p2)
+ return;
+ pos2 = p2;
+ updateScrollBars();
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// updateScrollBars
+//---------------------------------------------------------
+
+void TimeCanvas::updateScrollBars()
+ {
+ hbar->blockSignals(true);
+ vbar->blockSignals(true);
+
+ int ymax = lrint(yRange * _ymag) - rCanvasA.height();
+ if (ymax < 0)
+ ymax = 0;
+ vbar->setRange(0, ymax);
+ vbar->setPageStep(rCanvasA.height());
+
+ int xmin = lrint(pos1.time(_timeType) * _xmag);
+ unsigned x2 = pos2.time(_timeType);
+ int xmax = lrint(x2 * _xmag) - rCanvasA.width();
+ if (xmax - xmin < 0)
+ xmax = xmin;
+ hbar->setRange(xmin, xmax);
+ hbar->setPageStep(rCanvasA.width());
+ wpos.setX(hbar->value());
+ wpos.setY(vbar->value());
+
+ hbar->blockSignals(false);
+ vbar->blockSignals(false);
+ }
+
+//---------------------------------------------------------
+// setTimeType1
+//---------------------------------------------------------
+
+void TimeCanvas::setTimeType1(AL::TType t)
+ {
+ double conv = 1.0;
+ if (t == AL::TICKS) {
+ timeTypeButton->setIcon(*metronomIcon);
+ if (_timeType == AL::FRAMES)
+ conv = AL::sampleRate / double(AL::division * 120 / 60);
+ }
+ else {
+ timeTypeButton->setIcon(*clockIcon);
+ if (_timeType == AL::TICKS)
+ conv = double(AL::division * 120 / 60) / double(AL::sampleRate);
+ }
+ _timeType = t;
+ _xmag *= conv;
+ _xmagMax *= conv;
+ _xmagMin *= conv;
+
+ updateRulerMag();
+ magChanged();
+ }
+
+//---------------------------------------------------------
+// setTimeType
+//---------------------------------------------------------
+
+void TimeCanvas::setTimeType(AL::TType t)
+ {
+ setTimeType1(t);
+ updateScrollBars();
+ timeTypeChanged();
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// toggleTimeType
+//---------------------------------------------------------
+
+void TimeCanvas::toggleTimeType()
+ {
+ if (_timeType == AL::TICKS)
+ setTimeType(AL::FRAMES);
+ else
+ setTimeType(AL::TICKS);
+ }
+
+//---------------------------------------------------------
+// setMarkerList
+//---------------------------------------------------------
+
+void TimeCanvas::setMarkerList(AL::MarkerList* ml)
+ {
+ if (marker == ml)
+ return;
+ marker = ml;
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// pix2pos
+//---------------------------------------------------------
+
+AL::Pos TimeCanvas::pix2pos(int x) const
+ {
+ int val = lrint((x + wpos.x() - MAP_OFFSET)/_xmag);
+ if (val < 0)
+ val = 0;
+ return AL::Pos(val, _timeType);
+ }
+
+//---------------------------------------------------------
+// pos2pix
+//---------------------------------------------------------
+
+int TimeCanvas::pos2pix(const AL::Pos& p) const
+ {
+ return lrint(p.time(_timeType) * _xmag) + MAP_OFFSET - wpos.x();
+ }
+
+//---------------------------------------------------------
+// mapx
+//---------------------------------------------------------
+
+int TimeCanvas::mapx(int x) const
+ {
+ return lrint(x * _xmag) + MAP_OFFSET - wpos.x();
+ }
+
+//---------------------------------------------------------
+// mapxDev
+//---------------------------------------------------------
+
+int TimeCanvas::mapxDev(int x) const
+ {
+ int val = lrint((x + wpos.x() - MAP_OFFSET)/_xmag);
+ if (val < 0)
+ val = 0;
+ return val;
+ }
+
+//---------------------------------------------------------
+// setCorderWidget
+//---------------------------------------------------------
+
+void TimeCanvas::setCornerWidget(QWidget* w)
+ {
+ grid->addWidget(w, 3, 2);
+ }
+
+//---------------------------------------------------------
+// initPianoroll
+//---------------------------------------------------------
+
+/*
+ 0 1 2 3 4 5 6 7 8 9 10
+ c-2 c-1 C0 C1 C2 C3 C4 C5 C6 C7 C8 - G8
+
+ Grid ve:
+
+ +------------+ ------------------------------
+ 11 | |
+ | b | 7
+ +------+ |
+ 10 | a# +-----+ ..............................
+ +------+ a |
+ 9 | | 6
+ +------+ |
+ 8 | g# +-----+ ..............................
+ +------+ g |
+ 7 | | 5
+ +------+ |
+ 6 | f# +-----+ ..............................
+ +------+ f |
+ 5 | | 4
+ | |
+ +------------+ ------------------------------
+ 4 | |
+ | e | 3
+ +------+ |
+ 3 | d# +-----+ ..............................
+ +------+ d |
+ 2 | | 2
+ +------+ |
+ 1 | c# +-----+ ..............................
+ +------+ c |
+ | | 1
+ 0 | |
+ +------------+ ------------------------------
+ */
+
+void TimeCanvas::initPianoroll()
+ {
+ static const char *oct_xpm[] = {
+ // w h colors
+ "40 91 2 1",
+ ". c #f0f0f0",
+ "# c #000000",
+ // x
+ "####################################### ",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 10
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ", // 7
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 10
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "####################################### ", //----------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 9
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ", // 7
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //--------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 10
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+
+ static const char *mk1_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ",
+ };
+
+ static const char *mk2_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //--------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ };
+
+ static const char *mk3_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "########################################",
+ };
+
+ static const char *mk4_xpm[] = {
+ "40 13 2 1",
+ "# c #ff0000",
+ ". c none",
+ "........................................",
+ "........................................",
+ "........................................",
+ "#######################.................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "#######################.................",
+ "........................................",
+ "........................................",
+ "........................................",
+ };
+
+ if (octave == 0) {
+ octave = new QPixmap(oct_xpm);
+ mk1 = new QPixmap(mk1_xpm);
+ mk2 = new QPixmap(mk2_xpm);
+ mk3 = new QPixmap(mk3_xpm);
+ mk4 = new QPixmap(mk4_xpm);
+ }
+ yRange = keyHeight * 75;
+ }
+
+//---------------------------------------------------------
+// pitch2y
+// y = 0 == origin of rCanvasA
+//---------------------------------------------------------
+
+int TimeCanvas::pitch2y(int pitch) const
+ {
+ int y;
+ if (type == TIME_CANVAS_DRUMEDIT)
+ y = pitch * drumHeight;
+ else {
+ static int tt[] = {
+ 12, 19, 25, 32, 38, 51, 58, 64, 71, 77, 84, 90
+ };
+ y = (75 * keyHeight) - (tt[pitch % 12] + (7 * keyHeight) * (pitch / 12));
+ if (y < 0)
+ y = 0;
+ }
+ return lrint(y - wpos.y() / _ymag);
+ }
+
+//---------------------------------------------------------
+// y2pitch
+// y = 0 == origin of rCanvasA
+//---------------------------------------------------------
+
+int TimeCanvas::y2pitch(int y) const
+ {
+ y = lrint((y + wpos.y()) / _ymag);
+ int pitch;
+ if (type == TIME_CANVAS_DRUMEDIT)
+ pitch = y / drumHeight;
+ else {
+ const int total = (10 * 7 + 5) * keyHeight; // 75 Ganztonschritte
+ y = total - y;
+ int oct = (y / (7 * keyHeight)) * 12;
+ char kt[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
+ };
+ pitch = kt[y % 91] + oct;
+ if (pitch < 0 || pitch > 127)
+ pitch = -1;
+ }
+ return pitch;
+ }
+
+//---------------------------------------------------------
+// paintPiano
+//---------------------------------------------------------
+
+void TimeCanvas::paintPiano(QPainter& p, QRect r)
+ {
+ int d = int(_ymag)+1;
+ qreal x = qreal(r.x());
+ qreal y = (r.y()-rulerHeight-d) / _ymag;
+ if (y < 0.0)
+ y = 0.0;
+ qreal h = (r.height()+d) / _ymag;
+ QPointF offset(x, wpos.y() / _ymag + keyHeight * 2 + y);
+
+ p.translate(0.0, qreal(rulerHeight));
+ p.scale(1.0, _ymag);
+ p.drawTiledPixmap(QRectF(x, y, qreal(r.width()), h), *octave, offset);
+
+ if (curPitch != -1) {
+ int y = pitch2y(curPitch);
+ QPixmap* pm;
+ switch(curPitch % 12) {
+ case 0:
+ case 5:
+ pm = mk3;
+ break;
+ case 2:
+ case 7:
+ case 9:
+ pm = mk2;
+ break;
+ case 4:
+ case 11:
+ pm = mk1;
+ break;
+ default:
+ pm = mk4;
+ break;
+ }
+ p.drawPixmap(0, y, *pm);
+ }
+ p.resetMatrix();
+ }
+
+//---------------------------------------------------------
+// paintPianorollHorizontalGrid
+//---------------------------------------------------------
+
+void TimeCanvas::paintPianorollHorizontalGrid(QPainter& p, QRect r)
+ {
+ qreal offset = rulerHeight - wpos.y();
+ qreal kh = keyHeight * _ymag;
+
+ int x1 = r.x();
+ int x2 = x1 + r.width();
+ if (x1 < pianoWidth)
+ x1 = pianoWidth;
+ qreal y = kh + offset;
+ qreal y1 = r.y() - _ymag;
+ qreal y2 = y1 + r.height() + _ymag;
+ for (int key = 1; key < 75; ++key, y += kh) {
+ if (y < y1)
+ continue;
+ if (y > y2)
+ break;
+ switch (key % 7) {
+ case 2:
+ case 5:
+ p.setPen(QPen(Qt::lightGray));
+ break;
+ default:
+ p.setPen(QPen(Qt::gray));
+ break;
+ }
+ p.drawLine(QLineF(x1, y, x2, y));
+ }
+ }
+
+//---------------------------------------------------------
+// paintDrumeditHorizontalGrid
+//---------------------------------------------------------
+
+void TimeCanvas::paintDrumeditHorizontalGrid(QPainter& p, QRect r)
+ {
+ int offset = rulerHeight - wpos.y();
+
+ p.setPen(QPen(Qt::lightGray));
+ int x1 = r.x();
+ int x2 = x1 + r.width();
+ if (x1 < drumWidth)
+ x1 = drumWidth;
+
+ p.setPen(QPen(Qt::lightGray));
+
+ int y = offset;
+ int y1 = r.y();
+ int y2 = y1 + r.height();
+ for (int i = 0; i < 128; ++i, y += drumHeight) {
+ if (y < y1)
+ continue;
+ if (y > y2)
+ break;
+ p.drawLine(QLine(x1, y, x2, y));
+ }
+ }
+
+//---------------------------------------------------------
+// addCtrlClicked
+//---------------------------------------------------------
+
+void TimeCanvas::addCtrlClicked()
+ {
+ addController();
+ }
+
+//---------------------------------------------------------
+// updateGeometry
+//---------------------------------------------------------
+
+void TimeCanvas::updateGeometry()
+ {
+ int wh = _widget->height();
+ int ww = _widget->width();
+ if (wh < ctrlHeight)
+ ctrlHeight = wh;
+
+ int x1 = 0;
+ if (type == TIME_CANVAS_PIANOROLL)
+ x1 = pianoWidth;
+ else if (type == TIME_CANVAS_DRUMEDIT)
+ x1 = drumWidth;
+ else if (type == TIME_CANVAS_WAVEEDIT)
+ x1 = waveWidth;
+ int y2 = wh - ctrlHeight;
+
+ rPanelA.setRect(0, rulerHeight, x1, wh - rulerHeight - ctrlHeight);
+ rPanelB.setRect(0, y2, x1, ctrlHeight);
+
+ int cw = ww - x1;
+ rRuler.setRect( x1, 0, cw, rulerHeight);
+ rCanvasA.setRect(x1, rulerHeight, cw, wh - rulerHeight - ctrlHeight);
+ rCanvasB.setRect(x1, y2, cw, ctrlHeight);
+
+ rButton.setRect(0, 0, rCanvasA.x(), rPanelA.y());
+
+ if (yRange > 0 && _yFit) {
+ _ymagMin = double(rCanvasA.height()) / double(yRange);
+ if (_ymag < _ymagMin)
+ _ymag = _ymagMin;
+ if (vmag)
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ }
+ }
+
+//---------------------------------------------------------
+// setTool
+//---------------------------------------------------------
+
+void TimeCanvas::setTool(int t)
+ {
+ if (_tool == Tool(t))
+ return;
+ _tool = Tool(t);
+ emit toolChanged(_tool);
+ setCursor();
+ }
+
+//---------------------------------------------------------
+// setCursor
+//---------------------------------------------------------
+
+void TimeCanvas::setCursor()
+ {
+ switch(_tool) {
+ case PencilTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/pencil.xpm"), 4, 15));
+ break;
+ case RubberTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/delete.xpm"), 4, 15));
+ break;
+ case GlueTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/glue.xpm"), 4, 15));
+ break;
+ case CutTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/cut.xpm"), 4, 15));
+ break;
+ case MuteTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/editmute.xmp"), 4, 15));
+ break;
+ default:
+ widget()->setCursor(QCursor(Qt::ArrowCursor));
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// setCanvasBackground
+//---------------------------------------------------------
+
+void TimeCanvas::setCanvasBackground(const QColor& color)
+ {
+ canvasBackgroundPixmap = QPixmap();
+ canvasBackgroundColor = color;
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// setCanvasBackground
+//---------------------------------------------------------
+
+void TimeCanvas::setCanvasBackground(const QPixmap& pm)
+ {
+ canvasBackgroundPixmap = pm;
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// setYMagRange
+//---------------------------------------------------------
+
+void TimeCanvas::setYMagRange(double min, double max)
+ {
+ _ymagMin = min;
+ _ymagMax = max;
+ if (vmag)
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ }
+
+//---------------------------------------------------------
+// setVSize
+//---------------------------------------------------------
+
+void TimeCanvas::setVSize(int val)
+ {
+ if (yRange == val)
+ return;
+ yRange = val;
+ if (_yFit) {
+ _ymagMin = double(rCanvasA.height()) / double(yRange);
+ if (_ymag < _ymagMin)
+ _ymag = _ymagMin;
+ if (vmag)
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ }
+ updateScrollBars();
+ }
+
+//---------------------------------------------------------
+// s2xmag
+// nonlinear xmag behaviour, feels better
+//---------------------------------------------------------
+
+double TimeCanvas::s2xmag(int val)
+ {
+ val = 100 - val;
+ double f = 1.0 - log10(val * val + 1) * 0.25;
+ return (_xmagMax - _xmagMin) * f + _xmagMin;
+ }
+
+//---------------------------------------------------------
+// xmag2s
+//---------------------------------------------------------
+
+int TimeCanvas::xmag2s(double m)
+ {
+ m -= _xmagMin;
+ m /= (_xmagMax - _xmagMin);
+ double val = sqrt(exp10((1.0 - m) * 4.0)-1.0);
+ return lrint(100.0 - val);
+ }
+
+//---------------------------------------------------------
+// setPart
+//---------------------------------------------------------
+
+void TimeCanvas::setPart(const AL::Pos& p1, const AL::Pos& p2)
+ {
+ partPos1 = p1;
+ partPos2 = p2;
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// setFont1
+//---------------------------------------------------------
+
+void TimeCanvas::setFont1(const QFont& f)
+ {
+ _font1 = f;
+ printf("TimeCanvas::setFont1\n");
+ }
+
+//---------------------------------------------------------
+// setFont2
+//---------------------------------------------------------
+
+void TimeCanvas::setFont2(const QFont& f)
+ {
+ _font2 = f;
+ }
+
+//---------------------------------------------------------
+// setFont3
+//---------------------------------------------------------
+
+void TimeCanvas::setFont3(const QFont& f)
+ {
+ _font3 = f;
+ }
+