annotate widgets/Thumbwheel.cpp @ 162:f32212631b9c

* Handle generator transforms (plugins whose channel count isn't dependent on number of audio inputs, as they have none) * Be less keen to suspend writing FFT data in spectrogram repaint -- only do it if we find we actually need to query the FFT data (i.e. we aren't repainting an area that hasn't been generated at all yet)
author Chris Cannam
date Tue, 10 Oct 2006 19:04:57 +0000
parents 9e6b3e239b9d
children 793df5f0c6cb
rev   line source
Chris@132 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@132 2
Chris@132 3 /*
Chris@132 4 Sonic Visualiser
Chris@132 5 An audio file viewer and annotation editor.
Chris@132 6 Centre for Digital Music, Queen Mary, University of London.
Chris@132 7 This file copyright 2006 Chris Cannam.
Chris@132 8
Chris@132 9 This program is free software; you can redistribute it and/or
Chris@132 10 modify it under the terms of the GNU General Public License as
Chris@132 11 published by the Free Software Foundation; either version 2 of the
Chris@132 12 License, or (at your option) any later version. See the file
Chris@132 13 COPYING included with this distribution for more information.
Chris@132 14 */
Chris@132 15
Chris@132 16 #include "Thumbwheel.h"
Chris@132 17
Chris@132 18 #include <QMouseEvent>
Chris@132 19 #include <QPaintEvent>
Chris@132 20 #include <QWheelEvent>
Chris@132 21 #include <QPainter>
Chris@132 22
Chris@132 23 #include <cmath>
Chris@132 24 #include <iostream>
Chris@132 25
Chris@133 26 Thumbwheel::Thumbwheel(Qt::Orientation orientation,
Chris@132 27 QWidget *parent) :
Chris@132 28 QWidget(parent),
Chris@133 29 m_min(0),
Chris@133 30 m_max(100),
Chris@133 31 m_default(50),
Chris@133 32 m_value(50),
Chris@132 33 m_orientation(orientation),
Chris@133 34 m_speed(0.25),
Chris@132 35 m_tracking(true),
Chris@132 36 m_showScale(true),
Chris@132 37 m_clicked(false),
Chris@133 38 m_atDefault(true),
Chris@132 39 m_clickValue(m_value)
Chris@132 40 {
Chris@132 41 }
Chris@132 42
Chris@132 43 Thumbwheel::~Thumbwheel()
Chris@132 44 {
Chris@132 45 }
Chris@132 46
Chris@132 47 void
Chris@133 48 Thumbwheel::setMinimumValue(int min)
Chris@133 49 {
Chris@133 50 if (m_min == min) return;
Chris@133 51
Chris@133 52 m_min = min;
Chris@133 53 if (m_max <= m_min) m_max = m_min + 1;
Chris@133 54 if (m_value < m_min) m_value = m_min;
Chris@133 55 if (m_value > m_max) m_value = m_max;
Chris@133 56 }
Chris@133 57
Chris@133 58 int
Chris@133 59 Thumbwheel::getMinimumValue() const
Chris@133 60 {
Chris@133 61 return m_min;
Chris@133 62 }
Chris@133 63
Chris@133 64 void
Chris@133 65 Thumbwheel::setMaximumValue(int max)
Chris@133 66 {
Chris@133 67 if (m_max == max) return;
Chris@133 68
Chris@133 69 m_max = max;
Chris@133 70 if (m_min >= m_max) m_min = m_max - 1;
Chris@133 71 if (m_value < m_min) m_value = m_min;
Chris@133 72 if (m_value > m_max) m_value = m_max;
Chris@133 73 }
Chris@133 74
Chris@133 75 int
Chris@133 76 Thumbwheel::getMaximumValue() const
Chris@133 77 {
Chris@133 78 return m_max;
Chris@133 79 }
Chris@133 80
Chris@133 81 void
Chris@133 82 Thumbwheel::setDefaultValue(int deft)
Chris@133 83 {
Chris@133 84 if (m_default == deft) return;
Chris@133 85
Chris@133 86 m_default = deft;
Chris@133 87 if (m_atDefault) {
Chris@133 88 setValue(m_default);
Chris@133 89 emit valueChanged(getValue());
Chris@133 90 }
Chris@133 91 }
Chris@133 92
Chris@133 93 int
Chris@133 94 Thumbwheel::getDefaultValue() const
Chris@133 95 {
Chris@133 96 return m_default;
Chris@133 97 }
Chris@133 98
Chris@133 99 void
Chris@132 100 Thumbwheel::setValue(int value)
Chris@132 101 {
Chris@133 102 if (m_value == value) return;
Chris@133 103 m_atDefault = false;
Chris@133 104
Chris@132 105 if (value < m_min) value = m_min;
Chris@132 106 if (value > m_max) value = m_max;
Chris@132 107 m_value = value;
Chris@132 108 update();
Chris@132 109 }
Chris@132 110
Chris@133 111 void
Chris@133 112 Thumbwheel::resetToDefault()
Chris@133 113 {
Chris@133 114 if (m_default == m_value) return;
Chris@133 115 setValue(m_default);
Chris@133 116 m_atDefault = true;
Chris@133 117 emit valueChanged(getValue());
Chris@133 118 }
Chris@133 119
Chris@132 120 int
Chris@132 121 Thumbwheel::getValue() const
Chris@132 122 {
Chris@132 123 return m_value;
Chris@132 124 }
Chris@132 125
Chris@132 126 void
Chris@132 127 Thumbwheel::setSpeed(float speed)
Chris@132 128 {
Chris@132 129 m_speed = speed;
Chris@132 130 }
Chris@132 131
Chris@132 132 float
Chris@132 133 Thumbwheel::getSpeed() const
Chris@132 134 {
Chris@132 135 return m_speed;
Chris@132 136 }
Chris@132 137
Chris@132 138 void
Chris@132 139 Thumbwheel::setTracking(bool tracking)
Chris@132 140 {
Chris@132 141 m_tracking = tracking;
Chris@132 142 }
Chris@132 143
Chris@132 144 bool
Chris@132 145 Thumbwheel::getTracking() const
Chris@132 146 {
Chris@132 147 return m_tracking;
Chris@132 148 }
Chris@132 149
Chris@132 150 void
Chris@132 151 Thumbwheel::setShowScale(bool showScale)
Chris@132 152 {
Chris@132 153 m_showScale = showScale;
Chris@132 154 }
Chris@132 155
Chris@132 156 bool
Chris@132 157 Thumbwheel::getShowScale() const
Chris@132 158 {
Chris@132 159 return m_showScale;
Chris@132 160 }
Chris@132 161
Chris@132 162 void
Chris@132 163 Thumbwheel::mousePressEvent(QMouseEvent *e)
Chris@132 164 {
Chris@133 165 if (e->button() == Qt::LeftButton) {
Chris@133 166 m_clicked = true;
Chris@133 167 m_clickPos = e->pos();
Chris@133 168 m_clickValue = m_value;
Chris@133 169 } else if (e->button() == Qt::MidButton) {
Chris@133 170 resetToDefault();
Chris@133 171 }
Chris@132 172 }
Chris@132 173
Chris@132 174 void
Chris@132 175 Thumbwheel::mouseDoubleClickEvent(QMouseEvent *)
Chris@132 176 {
Chris@133 177 resetToDefault();
Chris@132 178 }
Chris@132 179
Chris@132 180 void
Chris@132 181 Thumbwheel::mouseMoveEvent(QMouseEvent *e)
Chris@132 182 {
Chris@133 183 if (!m_clicked) return;
Chris@132 184 int dist = 0;
Chris@132 185 if (m_orientation == Qt::Horizontal) {
Chris@132 186 dist = e->x() - m_clickPos.x();
Chris@132 187 } else {
Chris@132 188 dist = e->y() - m_clickPos.y();
Chris@132 189 }
Chris@132 190 int value = m_clickValue + lrintf(m_speed * dist);
Chris@132 191 if (value < m_min) value = m_min;
Chris@132 192 if (value > m_max) value = m_max;
Chris@132 193 if (value != m_value) {
Chris@132 194 setValue(value);
Chris@132 195 if (m_tracking) emit valueChanged(getValue());
Chris@132 196 }
Chris@132 197 }
Chris@132 198
Chris@132 199 void
Chris@132 200 Thumbwheel::mouseReleaseEvent(QMouseEvent *e)
Chris@132 201 {
Chris@133 202 if (!m_clicked) return;
Chris@132 203 bool reallyTracking = m_tracking;
Chris@132 204 m_tracking = true;
Chris@132 205 mouseMoveEvent(e);
Chris@132 206 m_tracking = reallyTracking;
Chris@133 207 m_clicked = false;
Chris@132 208 }
Chris@132 209
Chris@132 210 void
Chris@132 211 Thumbwheel::wheelEvent(QWheelEvent *e)
Chris@132 212 {
Chris@132 213 int step = lrintf(m_speed);
Chris@132 214 if (step == 0) step = 1;
Chris@132 215
Chris@132 216 if (e->delta() > 0) {
Chris@132 217 setValue(m_value + step);
Chris@132 218 } else {
Chris@132 219 setValue(m_value - step);
Chris@132 220 }
Chris@132 221
Chris@132 222 emit valueChanged(getValue());
Chris@132 223 }
Chris@132 224
Chris@132 225 void
Chris@132 226 Thumbwheel::paintEvent(QPaintEvent *)
Chris@132 227 {
Chris@133 228 QPainter paint(this);
Chris@133 229 paint.fillRect(rect(), palette().background().color());
Chris@133 230 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@133 231
Chris@133 232 int bw = 3;
Chris@133 233
Chris@133 234 for (int i = 0; i < bw; ++i) {
Chris@133 235 int grey = (i + 1) * (256 / (bw + 1));
Chris@133 236 QColor fc = QColor(grey, grey, grey);
Chris@133 237 paint.setPen(fc);
Chris@133 238 paint.drawRect(i, i, width() - i*2 - 1, height() - i*2 - 1);
Chris@133 239 }
Chris@133 240
Chris@133 241 paint.setClipRect(QRect(bw, bw, width() - bw*2, height() - bw*2));
Chris@133 242
Chris@132 243 float distance = float(m_value - m_min) / float(m_max - m_min);
Chris@132 244 float rotation = distance * 1.5f * M_PI;
Chris@132 245
Chris@132 246 // std::cerr << "value = " << m_value << ", min = " << m_min << ", max = " << m_max << ", rotation = " << rotation << std::endl;
Chris@132 247
Chris@133 248 int w = (m_orientation == Qt::Horizontal ? width() : height()) - bw*2;
Chris@132 249
Chris@132 250 // total number of notches on the entire wheel
Chris@132 251 int notches = 25;
Chris@132 252
Chris@132 253 // radius of the wheel including invisible part
Chris@132 254 int radius = w / 2 + 2;
Chris@132 255
Chris@132 256 paint.setRenderHint(QPainter::Antialiasing, true);
Chris@132 257
Chris@132 258 for (int i = 0; i < notches; ++i) {
Chris@132 259
Chris@132 260 float a0 = (2.f * M_PI * i) / notches + rotation;
Chris@132 261 float a1 = a0 + M_PI / (notches * 2);
Chris@132 262 float a2 = (2.f * M_PI * (i + 1)) / notches + rotation;
Chris@132 263
Chris@132 264 float depth = cosf((a0 + a2) / 2);
Chris@132 265 if (depth < 0) continue;
Chris@132 266
Chris@132 267 float x0 = radius * sinf(a0) + w/2;
Chris@132 268 float x1 = radius * sinf(a1) + w/2;
Chris@132 269 float x2 = radius * sinf(a2) + w/2;
Chris@132 270 if (x2 < 0 || x0 > w) continue;
Chris@132 271
Chris@132 272 if (x0 < 0) x0 = 0;
Chris@132 273 if (x2 > w) x2 = w;
Chris@132 274
Chris@133 275 x0 += bw;
Chris@133 276 x1 += bw;
Chris@133 277 x2 += bw;
Chris@133 278
Chris@132 279 int grey = lrintf(255 * depth);
Chris@132 280 QColor fc = QColor(grey, grey, grey);
Chris@132 281 QColor oc = palette().dark().color();
Chris@132 282
Chris@132 283 paint.setPen(oc);
Chris@132 284 paint.setBrush(fc);
Chris@132 285
Chris@132 286 if (m_orientation == Qt::Horizontal) {
Chris@133 287 paint.drawRect(QRectF(x1, bw, x2 - x1, height() - bw*2));
Chris@132 288 } else {
Chris@133 289 paint.drawRect(QRectF(bw, x1, width() - bw*2, x2 - x1));
Chris@132 290 }
Chris@132 291
Chris@132 292 if (m_showScale) {
Chris@132 293
Chris@132 294 paint.setBrush(oc);
Chris@132 295
Chris@132 296 float prop;
Chris@132 297 if (i >= notches / 4) {
Chris@132 298 prop = float(notches - (((i - float(notches) / 4.f) * 4.f) / 3.f))
Chris@132 299 / notches;
Chris@132 300 } else {
Chris@132 301 prop = 0.f;
Chris@132 302 }
Chris@132 303
Chris@132 304 if (m_orientation == Qt::Horizontal) {
Chris@133 305 paint.drawRect(QRectF(x1, height() - (height() - bw*2) * prop - bw,
Chris@132 306 x2 - x1, height() * prop));
Chris@132 307 } else {
Chris@133 308 paint.drawRect(QRectF(bw, x1, (width() - bw*2) * prop, x2 - x1));
Chris@132 309 }
Chris@132 310 }
Chris@132 311
Chris@132 312 paint.setPen(oc);
Chris@132 313 paint.setBrush(palette().background().color());
Chris@132 314
Chris@132 315 if (m_orientation == Qt::Horizontal) {
Chris@133 316 paint.drawRect(QRectF(x0, bw, x1 - x0, height() - bw*2));
Chris@132 317 } else {
Chris@133 318 paint.drawRect(QRectF(bw, x0, width() - bw*2, x1 - x0));
Chris@132 319 }
Chris@132 320 }
Chris@132 321 }
Chris@132 322
Chris@132 323 QSize
Chris@132 324 Thumbwheel::sizeHint() const
Chris@132 325 {
Chris@132 326 if (m_orientation == Qt::Horizontal) {
Chris@132 327 return QSize(80, 12);
Chris@132 328 } else {
Chris@132 329 return QSize(12, 80);
Chris@132 330 }
Chris@132 331 }
Chris@132 332