annotate widgets/Panner.cpp @ 333:e74b56f07c73

* Some work on correct alignment when moving panes during playback * Overhaul alignment for playback frame values (view manager now always refers to reference-timeline values, only the play source deals in playback model timeline values) * When making a selection, ensure the selection regions shown in other panes (and used for playback constraints if appropriate) are aligned correctly. This may be the coolest feature ever implemented in any program ever.
author Chris Cannam
date Thu, 22 Nov 2007 14:17:19 +0000
parents c492902dba40
children 755243c67f59
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@173 39 m_clicked(false)
Chris@172 40 {
Chris@172 41 }
Chris@172 42
Chris@172 43 Panner::~Panner()
Chris@172 44 {
Chris@172 45 }
Chris@172 46
Chris@172 47 void
Chris@174 48 Panner::setAlpha(int backgroundAlpha, int thumbAlpha)
Chris@174 49 {
Chris@174 50 m_backgroundAlpha = backgroundAlpha;
Chris@174 51 m_thumbAlpha = thumbAlpha;
Chris@174 52 }
Chris@174 53
Chris@174 54 void
Chris@256 55 Panner::setScrollUnit(float unit)
Chris@256 56 {
Chris@256 57 m_scrollUnit = unit;
Chris@256 58 }
Chris@256 59
Chris@256 60 void
Chris@256 61 Panner::scroll(bool up)
Chris@256 62 {
Chris@256 63 float unit = m_scrollUnit;
Chris@256 64 if (unit == 0.f) {
Chris@256 65 unit = float(m_rectHeight) / (6 * float(height()));
Chris@256 66 if (unit < 0.01) unit = 0.01;
Chris@256 67 }
Chris@256 68
Chris@256 69 if (!up) {
Chris@256 70 m_rectY += unit;
Chris@256 71 } else {
Chris@256 72 m_rectY -= unit;
Chris@256 73 }
Chris@256 74
Chris@256 75 normalise();
Chris@256 76 emitAndUpdate();
Chris@256 77 }
Chris@256 78
Chris@256 79 void
Chris@172 80 Panner::mousePressEvent(QMouseEvent *e)
Chris@172 81 {
Chris@188 82 if (e->button() == Qt::MidButton ||
Chris@188 83 ((e->button() == Qt::LeftButton) &&
Chris@188 84 (e->modifiers() & Qt::ControlModifier))) {
Chris@188 85 resetToDefault();
Chris@188 86 } else if (e->button() == Qt::LeftButton) {
Chris@173 87 m_clicked = true;
Chris@173 88 m_clickPos = e->pos();
Chris@173 89 m_dragStartX = m_rectX;
Chris@173 90 m_dragStartY = m_rectY;
Chris@173 91 }
Chris@172 92 }
Chris@172 93
Chris@172 94 void
Chris@172 95 Panner::mouseDoubleClickEvent(QMouseEvent *e)
Chris@172 96 {
Chris@188 97 if (e->button() != Qt::LeftButton) {
Chris@188 98 return;
Chris@188 99 }
Chris@188 100
Chris@188 101 emit doubleClicked();
Chris@172 102 }
Chris@172 103
Chris@172 104 void
Chris@172 105 Panner::mouseMoveEvent(QMouseEvent *e)
Chris@172 106 {
Chris@173 107 if (!m_clicked) return;
Chris@173 108
Chris@173 109 float dx = float(e->pos().x() - m_clickPos.x()) / float(width());
Chris@173 110 float dy = float(e->pos().y() - m_clickPos.y()) / float(height());
Chris@173 111
Chris@173 112 m_rectX = m_dragStartX + dx;
Chris@173 113 m_rectY = m_dragStartY + dy;
Chris@173 114
Chris@173 115 normalise();
Chris@174 116 repaint();
Chris@174 117 emit rectExtentsChanged(m_rectX, m_rectY, m_rectWidth, m_rectHeight);
Chris@174 118 emit rectCentreMoved(centreX(), centreY());
Chris@172 119 }
Chris@172 120
Chris@172 121 void
Chris@172 122 Panner::mouseReleaseEvent(QMouseEvent *e)
Chris@172 123 {
Chris@173 124 if (!m_clicked) return;
Chris@173 125
Chris@173 126 mouseMoveEvent(e);
Chris@173 127 m_clicked = false;
Chris@172 128 }
Chris@172 129
Chris@172 130 void
Chris@172 131 Panner::wheelEvent(QWheelEvent *e)
Chris@172 132 {
Chris@256 133 scroll(e->delta() > 0);
Chris@172 134 }
Chris@172 135
Chris@172 136 void
Chris@189 137 Panner::enterEvent(QEvent *)
Chris@189 138 {
Chris@189 139 emit mouseEntered();
Chris@189 140 }
Chris@189 141
Chris@189 142 void
Chris@189 143 Panner::leaveEvent(QEvent *)
Chris@189 144 {
Chris@189 145 emit mouseLeft();
Chris@189 146 }
Chris@189 147
Chris@189 148 void
Chris@249 149 Panner::paintEvent(QPaintEvent *)
Chris@172 150 {
Chris@172 151 QPainter paint(this);
Chris@172 152 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@173 153
Chris@173 154 QColor bg(palette().background().color());
Chris@174 155 bg.setAlpha(m_backgroundAlpha);
Chris@173 156
Chris@172 157 paint.setPen(palette().dark().color());
Chris@173 158 paint.setBrush(bg);
Chris@173 159 paint.drawRect(0, 0, width(), height());
Chris@173 160
Chris@174 161 QColor hl(m_thumbColour);
Chris@174 162 hl.setAlpha(m_thumbAlpha);
Chris@173 163
Chris@173 164 paint.setBrush(hl);
Chris@173 165
Chris@173 166 paint.drawRect(lrintf(width() * m_rectX),
Chris@173 167 lrintf(height() * m_rectY),
Chris@173 168 lrintf(width() * m_rectWidth),
Chris@173 169 lrintf(height() * m_rectHeight));
Chris@172 170 }
Chris@172 171
Chris@172 172 void
Chris@172 173 Panner::normalise()
Chris@172 174 {
Chris@172 175 if (m_rectWidth > 1.0) m_rectWidth = 1.0;
Chris@172 176 if (m_rectHeight > 1.0) m_rectHeight = 1.0;
Chris@172 177 if (m_rectX + m_rectWidth > 1.0) m_rectX = 1.0 - m_rectWidth;
Chris@172 178 if (m_rectX < 0) m_rectX = 0;
Chris@172 179 if (m_rectY + m_rectHeight > 1.0) m_rectY = 1.0 - m_rectHeight;
Chris@172 180 if (m_rectY < 0) m_rectY = 0;
Chris@173 181
Chris@173 182 if (!m_defaultsSet) {
Chris@173 183 m_defaultCentreX = centreX();
Chris@173 184 m_defaultCentreY = centreY();
Chris@173 185 m_defaultsSet = true;
Chris@173 186 }
Chris@172 187 }
Chris@172 188
Chris@172 189 void
Chris@172 190 Panner::emitAndUpdate()
Chris@172 191 {
Chris@172 192 emit rectExtentsChanged(m_rectX, m_rectY, m_rectWidth, m_rectHeight);
Chris@173 193 emit rectCentreMoved(centreX(), centreY());
Chris@172 194 update();
Chris@172 195 }
Chris@172 196
Chris@172 197 void
Chris@188 198 Panner::getRectExtents(float &x0, float &y0, float &width, float &height)
Chris@188 199 {
Chris@188 200 x0 = m_rectX;
Chris@188 201 y0 = m_rectY;
Chris@188 202 width = m_rectWidth;
Chris@188 203 height = m_rectHeight;
Chris@188 204 }
Chris@188 205
Chris@188 206 void
Chris@172 207 Panner::setRectExtents(float x0, float y0, float width, float height)
Chris@172 208 {
Chris@249 209 // std::cerr << "Panner::setRectExtents(" << x0 << ", " << y0 << ", "
Chris@249 210 // << width << ", " << height << ")" << std::endl;
Chris@174 211
Chris@172 212 if (m_rectX == x0 &&
Chris@172 213 m_rectY == y0 &&
Chris@172 214 m_rectWidth == width &&
Chris@172 215 m_rectHeight == height) {
Chris@172 216 return;
Chris@172 217 }
Chris@173 218
Chris@172 219 m_rectX = x0;
Chris@172 220 m_rectY = y0;
Chris@172 221 m_rectWidth = width;
Chris@172 222 m_rectHeight = height;
Chris@173 223
Chris@172 224 normalise();
Chris@172 225 emitAndUpdate();
Chris@172 226 }
Chris@172 227
Chris@172 228 void
Chris@172 229 Panner::setRectWidth(float width)
Chris@172 230 {
Chris@172 231 if (m_rectWidth == width) return;
Chris@172 232 m_rectWidth = width;
Chris@172 233 normalise();
Chris@172 234 emitAndUpdate();
Chris@172 235 }
Chris@172 236
Chris@172 237 void
Chris@172 238 Panner::setRectHeight(float height)
Chris@172 239 {
Chris@172 240 if (m_rectHeight == height) return;
Chris@172 241 m_rectHeight = height;
Chris@172 242 normalise();
Chris@172 243 emitAndUpdate();
Chris@172 244 }
Chris@172 245
Chris@172 246 void
Chris@172 247 Panner::setRectCentreX(float x)
Chris@172 248 {
Chris@172 249 float x0 = x - m_rectWidth/2;
Chris@172 250 if (x0 == m_rectX) return;
Chris@172 251 m_rectX = x0;
Chris@172 252 normalise();
Chris@172 253 emitAndUpdate();
Chris@172 254 }
Chris@172 255
Chris@172 256 void
Chris@172 257 Panner::setRectCentreY(float y)
Chris@172 258 {
Chris@173 259 float y0 = y - m_rectHeight/2;
Chris@172 260 if (y0 == m_rectY) return;
Chris@172 261 m_rectY = y0;
Chris@172 262 normalise();
Chris@172 263 emitAndUpdate();
Chris@172 264 }
Chris@172 265
Chris@172 266 QSize
Chris@172 267 Panner::sizeHint() const
Chris@172 268 {
Chris@172 269 return QSize(30, 30);
Chris@172 270 }
Chris@172 271
Chris@173 272 void
Chris@173 273 Panner::setDefaultRectCentre(float cx, float cy)
Chris@173 274 {
Chris@173 275 m_defaultCentreX = cx;
Chris@173 276 m_defaultCentreY = cy;
Chris@173 277 m_defaultsSet = true;
Chris@173 278 }
Chris@172 279
Chris@173 280 void
Chris@173 281 Panner::resetToDefault()
Chris@173 282 {
Chris@173 283 float x0 = m_defaultCentreX - m_rectWidth/2;
Chris@173 284 float y0 = m_defaultCentreY - m_rectHeight/2;
Chris@173 285 if (x0 == m_rectX && y0 == m_rectY) return;
Chris@173 286 m_rectX = x0;
Chris@173 287 m_rectY = y0;
Chris@173 288 normalise();
Chris@173 289 emitAndUpdate();
Chris@173 290 }
Chris@172 291
Chris@173 292