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@1313
|
80 m_rectY += unit * float(count);
|
Chris@256
|
81 } else {
|
Chris@1313
|
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@173
|
165 QColor bg(palette().background().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
|