annotate widgets/Panner.cpp @ 1553:76e4302a3fc2

Fix note numbering - ensure stable across whole track (as it used to be, but without scanning all notes in paint in order to do that)
author Chris Cannam
date Fri, 22 Nov 2019 14:12:50 +0000
parents d39db4673676
children
rev   line source
Chris@172 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@172 2
Chris@172 3 /*
Chris@172 4 Sonic Visualiser
Chris@172 5 An audio file viewer and annotation editor.
Chris@172 6 Centre for Digital Music, Queen Mary, University of London.
Chris@182 7 This file copyright 2006 QMUL.
Chris@172 8
Chris@172 9 This program is free software; you can redistribute it and/or
Chris@172 10 modify it under the terms of the GNU General Public License as
Chris@172 11 published by the Free Software Foundation; either version 2 of the
Chris@172 12 License, or (at your option) any later version. See the file
Chris@172 13 COPYING included with this distribution for more information.
Chris@172 14 */
Chris@172 15
Chris@172 16 #include "Panner.h"
Chris@172 17
Chris@172 18 #include <QMouseEvent>
Chris@172 19 #include <QPaintEvent>
Chris@172 20 #include <QWheelEvent>
Chris@172 21 #include <QPainter>
Chris@172 22
Chris@1238 23 #include "WidgetScale.h"
Chris@1238 24
Chris@172 25 #include <iostream>
Chris@181 26 #include <cmath>
Martin@175 27
Chris@172 28 Panner::Panner(QWidget *parent) :
Chris@172 29 QWidget(parent),
Chris@172 30 m_rectX(0),
Chris@172 31 m_rectY(0),
Chris@172 32 m_rectWidth(1),
Chris@173 33 m_rectHeight(1),
Chris@256 34 m_scrollUnit(0),
Chris@173 35 m_defaultCentreX(0),
Chris@173 36 m_defaultCentreY(0),
Chris@173 37 m_defaultsSet(false),
Chris@174 38 m_thumbColour(palette().highlightedText().color()),
Chris@174 39 m_backgroundAlpha(255),
Chris@174 40 m_thumbAlpha(255),
Chris@858 41 m_clicked(false),
Chris@858 42 m_dragStartX(0),
Chris@858 43 m_dragStartY(0)
Chris@172 44 {
Chris@172 45 }
Chris@172 46
Chris@172 47 Panner::~Panner()
Chris@172 48 {
Chris@172 49 }
Chris@172 50
Chris@172 51 void
Chris@174 52 Panner::setAlpha(int backgroundAlpha, int thumbAlpha)
Chris@174 53 {
Chris@174 54 m_backgroundAlpha = backgroundAlpha;
Chris@174 55 m_thumbAlpha = thumbAlpha;
Chris@174 56 }
Chris@174 57
Chris@174 58 void
Chris@256 59 Panner::setScrollUnit(float unit)
Chris@256 60 {
Chris@256 61 m_scrollUnit = unit;
Chris@256 62 }
Chris@256 63
Chris@256 64 void
Chris@256 65 Panner::scroll(bool up)
Chris@256 66 {
Chris@1303 67 scroll(up, 1);
Chris@1303 68 }
Chris@1303 69
Chris@1303 70 void
Chris@1303 71 Panner::scroll(bool up, int count)
Chris@1303 72 {
Chris@256 73 float unit = m_scrollUnit;
Chris@256 74 if (unit == 0.f) {
Chris@256 75 unit = float(m_rectHeight) / (6 * float(height()));
Chris@908 76 if (unit < 0.01f) unit = 0.01f;
Chris@256 77 }
Chris@256 78
Chris@256 79 if (!up) {
Chris@1310 80 m_rectY += unit * float(count);
Chris@256 81 } else {
Chris@1310 82 m_rectY -= unit * float(count);
Chris@256 83 }
Chris@256 84
Chris@256 85 normalise();
Chris@256 86 emitAndUpdate();
Chris@256 87 }
Chris@256 88
Chris@256 89 void
Chris@172 90 Panner::mousePressEvent(QMouseEvent *e)
Chris@172 91 {
Chris@188 92 if (e->button() == Qt::MidButton ||
Chris@188 93 ((e->button() == Qt::LeftButton) &&
Chris@188 94 (e->modifiers() & Qt::ControlModifier))) {
Chris@188 95 resetToDefault();
Chris@188 96 } else if (e->button() == Qt::LeftButton) {
Chris@173 97 m_clicked = true;
Chris@173 98 m_clickPos = e->pos();
Chris@173 99 m_dragStartX = m_rectX;
Chris@173 100 m_dragStartY = m_rectY;
Chris@173 101 }
Chris@172 102 }
Chris@172 103
Chris@172 104 void
Chris@172 105 Panner::mouseDoubleClickEvent(QMouseEvent *e)
Chris@172 106 {
Chris@188 107 if (e->button() != Qt::LeftButton) {
Chris@188 108 return;
Chris@188 109 }
Chris@188 110
Chris@188 111 emit doubleClicked();
Chris@172 112 }
Chris@172 113
Chris@172 114 void
Chris@172 115 Panner::mouseMoveEvent(QMouseEvent *e)
Chris@172 116 {
Chris@173 117 if (!m_clicked) return;
Chris@173 118
Chris@173 119 float dx = float(e->pos().x() - m_clickPos.x()) / float(width());
Chris@173 120 float dy = float(e->pos().y() - m_clickPos.y()) / float(height());
Chris@173 121
Chris@173 122 m_rectX = m_dragStartX + dx;
Chris@173 123 m_rectY = m_dragStartY + dy;
Chris@173 124
Chris@173 125 normalise();
Chris@174 126 repaint();
Chris@174 127 emit rectExtentsChanged(m_rectX, m_rectY, m_rectWidth, m_rectHeight);
Chris@174 128 emit rectCentreMoved(centreX(), centreY());
Chris@172 129 }
Chris@172 130
Chris@172 131 void
Chris@172 132 Panner::mouseReleaseEvent(QMouseEvent *e)
Chris@172 133 {
Chris@173 134 if (!m_clicked) return;
Chris@173 135
Chris@173 136 mouseMoveEvent(e);
Chris@173 137 m_clicked = false;
Chris@172 138 }
Chris@172 139
Chris@172 140 void
Chris@172 141 Panner::wheelEvent(QWheelEvent *e)
Chris@172 142 {
Chris@1303 143 int delta = m_wheelCounter.count(e);
Chris@1303 144 scroll(delta > 0, abs(delta));
Chris@172 145 }
Chris@172 146
Chris@172 147 void
Chris@189 148 Panner::enterEvent(QEvent *)
Chris@189 149 {
Chris@189 150 emit mouseEntered();
Chris@189 151 }
Chris@189 152
Chris@189 153 void
Chris@189 154 Panner::leaveEvent(QEvent *)
Chris@189 155 {
Chris@189 156 emit mouseLeft();
Chris@189 157 }
Chris@189 158
Chris@189 159 void
Chris@249 160 Panner::paintEvent(QPaintEvent *)
Chris@172 161 {
Chris@172 162 QPainter paint(this);
Chris@172 163 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@173 164
Chris@1478 165 QColor bg(palette().window().color());
Chris@174 166 bg.setAlpha(m_backgroundAlpha);
Chris@173 167
Chris@1238 168 int penWidth = WidgetScale::scalePixelSize(1);
Chris@1238 169 if (penWidth < 1) penWidth = 1;
Chris@1238 170 paint.setPen(QPen(palette().dark().color(), penWidth));
Chris@1238 171
Chris@173 172 paint.setBrush(bg);
Chris@1238 173 paint.drawRect(penWidth/2, penWidth/2,
Chris@1238 174 width()-penWidth/2-1, height()-penWidth/2-1);
Chris@173 175
Chris@174 176 QColor hl(m_thumbColour);
Chris@174 177 hl.setAlpha(m_thumbAlpha);
Chris@173 178
Chris@173 179 paint.setBrush(hl);
Chris@173 180
Chris@908 181 int rw = int(lrintf(float(width() - 1) * m_rectWidth));
Chris@908 182 int rh = int(lrintf(float(height() - 1) * m_rectHeight));
Chris@437 183 if (rw < 2) rw = 2;
Chris@437 184 if (rh < 2) rh = 2;
Chris@437 185
Chris@908 186 paint.drawRect(int(lrintf(float(width()) * m_rectX)),
Chris@908 187 int(lrintf(float(height()) * m_rectY)),
Chris@437 188 rw, rh);
Chris@172 189 }
Chris@172 190
Chris@172 191 void
Chris@172 192 Panner::normalise()
Chris@172 193 {
Chris@908 194 if (m_rectWidth > 1.f) m_rectWidth = 1.f;
Chris@908 195 if (m_rectHeight > 1.f) m_rectHeight = 1.f;
Chris@908 196 if (m_rectX + m_rectWidth > 1.f) m_rectX = 1.f - m_rectWidth;
Chris@172 197 if (m_rectX < 0) m_rectX = 0;
Chris@908 198 if (m_rectY + m_rectHeight > 1.f) m_rectY = 1.f - m_rectHeight;
Chris@172 199 if (m_rectY < 0) m_rectY = 0;
Chris@173 200
Chris@173 201 if (!m_defaultsSet) {
Chris@173 202 m_defaultCentreX = centreX();
Chris@173 203 m_defaultCentreY = centreY();
Chris@173 204 m_defaultsSet = true;
Chris@173 205 }
Chris@172 206 }
Chris@172 207
Chris@172 208 void
Chris@172 209 Panner::emitAndUpdate()
Chris@172 210 {
Chris@172 211 emit rectExtentsChanged(m_rectX, m_rectY, m_rectWidth, m_rectHeight);
Chris@173 212 emit rectCentreMoved(centreX(), centreY());
Chris@172 213 update();
Chris@172 214 }
Chris@172 215
Chris@172 216 void
Chris@188 217 Panner::getRectExtents(float &x0, float &y0, float &width, float &height)
Chris@188 218 {
Chris@188 219 x0 = m_rectX;
Chris@188 220 y0 = m_rectY;
Chris@188 221 width = m_rectWidth;
Chris@188 222 height = m_rectHeight;
Chris@188 223 }
Chris@188 224
Chris@188 225 void
Chris@172 226 Panner::setRectExtents(float x0, float y0, float width, float height)
Chris@172 227 {
Chris@587 228 // SVDEBUG << "Panner::setRectExtents(" << x0 << ", " << y0 << ", "
Chris@585 229 // << width << ", " << height << ")" << endl;
Chris@174 230
Chris@172 231 if (m_rectX == x0 &&
Chris@172 232 m_rectY == y0 &&
Chris@172 233 m_rectWidth == width &&
Chris@172 234 m_rectHeight == height) {
Chris@172 235 return;
Chris@172 236 }
Chris@173 237
Chris@172 238 m_rectX = x0;
Chris@172 239 m_rectY = y0;
Chris@172 240 m_rectWidth = width;
Chris@172 241 m_rectHeight = height;
Chris@173 242
Chris@172 243 normalise();
Chris@172 244 emitAndUpdate();
Chris@172 245 }
Chris@172 246
Chris@172 247 void
Chris@172 248 Panner::setRectWidth(float width)
Chris@172 249 {
Chris@172 250 if (m_rectWidth == width) return;
Chris@172 251 m_rectWidth = width;
Chris@172 252 normalise();
Chris@172 253 emitAndUpdate();
Chris@172 254 }
Chris@172 255
Chris@172 256 void
Chris@172 257 Panner::setRectHeight(float height)
Chris@172 258 {
Chris@172 259 if (m_rectHeight == height) return;
Chris@172 260 m_rectHeight = height;
Chris@172 261 normalise();
Chris@172 262 emitAndUpdate();
Chris@172 263 }
Chris@172 264
Chris@172 265 void
Chris@172 266 Panner::setRectCentreX(float x)
Chris@172 267 {
Chris@172 268 float x0 = x - m_rectWidth/2;
Chris@172 269 if (x0 == m_rectX) return;
Chris@172 270 m_rectX = x0;
Chris@172 271 normalise();
Chris@172 272 emitAndUpdate();
Chris@172 273 }
Chris@172 274
Chris@172 275 void
Chris@172 276 Panner::setRectCentreY(float y)
Chris@172 277 {
Chris@173 278 float y0 = y - m_rectHeight/2;
Chris@172 279 if (y0 == m_rectY) return;
Chris@172 280 m_rectY = y0;
Chris@172 281 normalise();
Chris@172 282 emitAndUpdate();
Chris@172 283 }
Chris@172 284
Chris@172 285 QSize
Chris@172 286 Panner::sizeHint() const
Chris@172 287 {
Chris@172 288 return QSize(30, 30);
Chris@172 289 }
Chris@172 290
Chris@173 291 void
Chris@173 292 Panner::setDefaultRectCentre(float cx, float cy)
Chris@173 293 {
Chris@173 294 m_defaultCentreX = cx;
Chris@173 295 m_defaultCentreY = cy;
Chris@173 296 m_defaultsSet = true;
Chris@173 297 }
Chris@172 298
Chris@173 299 void
Chris@173 300 Panner::resetToDefault()
Chris@173 301 {
Chris@173 302 float x0 = m_defaultCentreX - m_rectWidth/2;
Chris@173 303 float y0 = m_defaultCentreY - m_rectHeight/2;
Chris@173 304 if (x0 == m_rectX && y0 == m_rectY) return;
Chris@173 305 m_rectX = x0;
Chris@173 306 m_rectY = y0;
Chris@173 307 normalise();
Chris@173 308 emitAndUpdate();
Chris@173 309 }
Chris@172 310
Chris@173 311