annotate widgets/Panner.cpp @ 1204:d421df27e184 3.0-integration

Further PropertyBox layout overhaul: avoid crash (/ assertion failure) when property type changes from e.g. colour to colourmap, by replacing the existing widget within the layout rather than trying to repopulate it
author Chris Cannam
date Tue, 20 Dec 2016 10:49:24 +0000
parents 4a578a360011
children 4d0ca1ab4cd0
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@172 23 #include <iostream>
Chris@181 24 #include <cmath>
Martin@175 25
Chris@172 26 Panner::Panner(QWidget *parent) :
Chris@172 27 QWidget(parent),
Chris@172 28 m_rectX(0),
Chris@172 29 m_rectY(0),
Chris@172 30 m_rectWidth(1),
Chris@173 31 m_rectHeight(1),
Chris@256 32 m_scrollUnit(0),
Chris@173 33 m_defaultCentreX(0),
Chris@173 34 m_defaultCentreY(0),
Chris@173 35 m_defaultsSet(false),
Chris@174 36 m_thumbColour(palette().highlightedText().color()),
Chris@174 37 m_backgroundAlpha(255),
Chris@174 38 m_thumbAlpha(255),
Chris@858 39 m_clicked(false),
Chris@858 40 m_dragStartX(0),
Chris@858 41 m_dragStartY(0)
Chris@172 42 {
Chris@172 43 }
Chris@172 44
Chris@172 45 Panner::~Panner()
Chris@172 46 {
Chris@172 47 }
Chris@172 48
Chris@172 49 void
Chris@174 50 Panner::setAlpha(int backgroundAlpha, int thumbAlpha)
Chris@174 51 {
Chris@174 52 m_backgroundAlpha = backgroundAlpha;
Chris@174 53 m_thumbAlpha = thumbAlpha;
Chris@174 54 }
Chris@174 55
Chris@174 56 void
Chris@256 57 Panner::setScrollUnit(float unit)
Chris@256 58 {
Chris@256 59 m_scrollUnit = unit;
Chris@256 60 }
Chris@256 61
Chris@256 62 void
Chris@256 63 Panner::scroll(bool up)
Chris@256 64 {
Chris@256 65 float unit = m_scrollUnit;
Chris@256 66 if (unit == 0.f) {
Chris@256 67 unit = float(m_rectHeight) / (6 * float(height()));
Chris@908 68 if (unit < 0.01f) unit = 0.01f;
Chris@256 69 }
Chris@256 70
Chris@256 71 if (!up) {
Chris@256 72 m_rectY += unit;
Chris@256 73 } else {
Chris@256 74 m_rectY -= unit;
Chris@256 75 }
Chris@256 76
Chris@256 77 normalise();
Chris@256 78 emitAndUpdate();
Chris@256 79 }
Chris@256 80
Chris@256 81 void
Chris@172 82 Panner::mousePressEvent(QMouseEvent *e)
Chris@172 83 {
Chris@188 84 if (e->button() == Qt::MidButton ||
Chris@188 85 ((e->button() == Qt::LeftButton) &&
Chris@188 86 (e->modifiers() & Qt::ControlModifier))) {
Chris@188 87 resetToDefault();
Chris@188 88 } else if (e->button() == Qt::LeftButton) {
Chris@173 89 m_clicked = true;
Chris@173 90 m_clickPos = e->pos();
Chris@173 91 m_dragStartX = m_rectX;
Chris@173 92 m_dragStartY = m_rectY;
Chris@173 93 }
Chris@172 94 }
Chris@172 95
Chris@172 96 void
Chris@172 97 Panner::mouseDoubleClickEvent(QMouseEvent *e)
Chris@172 98 {
Chris@188 99 if (e->button() != Qt::LeftButton) {
Chris@188 100 return;
Chris@188 101 }
Chris@188 102
Chris@188 103 emit doubleClicked();
Chris@172 104 }
Chris@172 105
Chris@172 106 void
Chris@172 107 Panner::mouseMoveEvent(QMouseEvent *e)
Chris@172 108 {
Chris@173 109 if (!m_clicked) return;
Chris@173 110
Chris@173 111 float dx = float(e->pos().x() - m_clickPos.x()) / float(width());
Chris@173 112 float dy = float(e->pos().y() - m_clickPos.y()) / float(height());
Chris@173 113
Chris@173 114 m_rectX = m_dragStartX + dx;
Chris@173 115 m_rectY = m_dragStartY + dy;
Chris@173 116
Chris@173 117 normalise();
Chris@174 118 repaint();
Chris@174 119 emit rectExtentsChanged(m_rectX, m_rectY, m_rectWidth, m_rectHeight);
Chris@174 120 emit rectCentreMoved(centreX(), centreY());
Chris@172 121 }
Chris@172 122
Chris@172 123 void
Chris@172 124 Panner::mouseReleaseEvent(QMouseEvent *e)
Chris@172 125 {
Chris@173 126 if (!m_clicked) return;
Chris@173 127
Chris@173 128 mouseMoveEvent(e);
Chris@173 129 m_clicked = false;
Chris@172 130 }
Chris@172 131
Chris@172 132 void
Chris@172 133 Panner::wheelEvent(QWheelEvent *e)
Chris@172 134 {
Chris@256 135 scroll(e->delta() > 0);
Chris@172 136 }
Chris@172 137
Chris@172 138 void
Chris@189 139 Panner::enterEvent(QEvent *)
Chris@189 140 {
Chris@189 141 emit mouseEntered();
Chris@189 142 }
Chris@189 143
Chris@189 144 void
Chris@189 145 Panner::leaveEvent(QEvent *)
Chris@189 146 {
Chris@189 147 emit mouseLeft();
Chris@189 148 }
Chris@189 149
Chris@189 150 void
Chris@249 151 Panner::paintEvent(QPaintEvent *)
Chris@172 152 {
Chris@172 153 QPainter paint(this);
Chris@172 154 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@173 155
Chris@173 156 QColor bg(palette().background().color());
Chris@174 157 bg.setAlpha(m_backgroundAlpha);
Chris@173 158
Chris@172 159 paint.setPen(palette().dark().color());
Chris@173 160 paint.setBrush(bg);
Chris@438 161 paint.drawRect(0, 0, width()-1, height()-1);
Chris@173 162
Chris@174 163 QColor hl(m_thumbColour);
Chris@174 164 hl.setAlpha(m_thumbAlpha);
Chris@173 165
Chris@173 166 paint.setBrush(hl);
Chris@173 167
Chris@908 168 int rw = int(lrintf(float(width() - 1) * m_rectWidth));
Chris@908 169 int rh = int(lrintf(float(height() - 1) * m_rectHeight));
Chris@437 170 if (rw < 2) rw = 2;
Chris@437 171 if (rh < 2) rh = 2;
Chris@437 172
Chris@908 173 paint.drawRect(int(lrintf(float(width()) * m_rectX)),
Chris@908 174 int(lrintf(float(height()) * m_rectY)),
Chris@437 175 rw, rh);
Chris@172 176 }
Chris@172 177
Chris@172 178 void
Chris@172 179 Panner::normalise()
Chris@172 180 {
Chris@908 181 if (m_rectWidth > 1.f) m_rectWidth = 1.f;
Chris@908 182 if (m_rectHeight > 1.f) m_rectHeight = 1.f;
Chris@908 183 if (m_rectX + m_rectWidth > 1.f) m_rectX = 1.f - m_rectWidth;
Chris@172 184 if (m_rectX < 0) m_rectX = 0;
Chris@908 185 if (m_rectY + m_rectHeight > 1.f) m_rectY = 1.f - m_rectHeight;
Chris@172 186 if (m_rectY < 0) m_rectY = 0;
Chris@173 187
Chris@173 188 if (!m_defaultsSet) {
Chris@173 189 m_defaultCentreX = centreX();
Chris@173 190 m_defaultCentreY = centreY();
Chris@173 191 m_defaultsSet = true;
Chris@173 192 }
Chris@172 193 }
Chris@172 194
Chris@172 195 void
Chris@172 196 Panner::emitAndUpdate()
Chris@172 197 {
Chris@172 198 emit rectExtentsChanged(m_rectX, m_rectY, m_rectWidth, m_rectHeight);
Chris@173 199 emit rectCentreMoved(centreX(), centreY());
Chris@172 200 update();
Chris@172 201 }
Chris@172 202
Chris@172 203 void
Chris@188 204 Panner::getRectExtents(float &x0, float &y0, float &width, float &height)
Chris@188 205 {
Chris@188 206 x0 = m_rectX;
Chris@188 207 y0 = m_rectY;
Chris@188 208 width = m_rectWidth;
Chris@188 209 height = m_rectHeight;
Chris@188 210 }
Chris@188 211
Chris@188 212 void
Chris@172 213 Panner::setRectExtents(float x0, float y0, float width, float height)
Chris@172 214 {
Chris@587 215 // SVDEBUG << "Panner::setRectExtents(" << x0 << ", " << y0 << ", "
Chris@585 216 // << width << ", " << height << ")" << endl;
Chris@174 217
Chris@172 218 if (m_rectX == x0 &&
Chris@172 219 m_rectY == y0 &&
Chris@172 220 m_rectWidth == width &&
Chris@172 221 m_rectHeight == height) {
Chris@172 222 return;
Chris@172 223 }
Chris@173 224
Chris@172 225 m_rectX = x0;
Chris@172 226 m_rectY = y0;
Chris@172 227 m_rectWidth = width;
Chris@172 228 m_rectHeight = height;
Chris@173 229
Chris@172 230 normalise();
Chris@172 231 emitAndUpdate();
Chris@172 232 }
Chris@172 233
Chris@172 234 void
Chris@172 235 Panner::setRectWidth(float width)
Chris@172 236 {
Chris@172 237 if (m_rectWidth == width) return;
Chris@172 238 m_rectWidth = width;
Chris@172 239 normalise();
Chris@172 240 emitAndUpdate();
Chris@172 241 }
Chris@172 242
Chris@172 243 void
Chris@172 244 Panner::setRectHeight(float height)
Chris@172 245 {
Chris@172 246 if (m_rectHeight == height) return;
Chris@172 247 m_rectHeight = height;
Chris@172 248 normalise();
Chris@172 249 emitAndUpdate();
Chris@172 250 }
Chris@172 251
Chris@172 252 void
Chris@172 253 Panner::setRectCentreX(float x)
Chris@172 254 {
Chris@172 255 float x0 = x - m_rectWidth/2;
Chris@172 256 if (x0 == m_rectX) return;
Chris@172 257 m_rectX = x0;
Chris@172 258 normalise();
Chris@172 259 emitAndUpdate();
Chris@172 260 }
Chris@172 261
Chris@172 262 void
Chris@172 263 Panner::setRectCentreY(float y)
Chris@172 264 {
Chris@173 265 float y0 = y - m_rectHeight/2;
Chris@172 266 if (y0 == m_rectY) return;
Chris@172 267 m_rectY = y0;
Chris@172 268 normalise();
Chris@172 269 emitAndUpdate();
Chris@172 270 }
Chris@172 271
Chris@172 272 QSize
Chris@172 273 Panner::sizeHint() const
Chris@172 274 {
Chris@172 275 return QSize(30, 30);
Chris@172 276 }
Chris@172 277
Chris@173 278 void
Chris@173 279 Panner::setDefaultRectCentre(float cx, float cy)
Chris@173 280 {
Chris@173 281 m_defaultCentreX = cx;
Chris@173 282 m_defaultCentreY = cy;
Chris@173 283 m_defaultsSet = true;
Chris@173 284 }
Chris@172 285
Chris@173 286 void
Chris@173 287 Panner::resetToDefault()
Chris@173 288 {
Chris@173 289 float x0 = m_defaultCentreX - m_rectWidth/2;
Chris@173 290 float y0 = m_defaultCentreY - m_rectHeight/2;
Chris@173 291 if (x0 == m_rectX && y0 == m_rectY) return;
Chris@173 292 m_rectX = x0;
Chris@173 293 m_rectY = y0;
Chris@173 294 normalise();
Chris@173 295 emitAndUpdate();
Chris@173 296 }
Chris@172 297
Chris@173 298