Mercurial > hg > svgui
comparison widgets/LevelPanWidget.cpp @ 923:2a9f1eb6e0ed tonioni
Try adding a combined simple level/pan widget
author | Chris Cannam |
---|---|
date | Tue, 24 Mar 2015 14:40:31 +0000 |
parents | |
children | cfcdec324712 |
comparison
equal
deleted
inserted
replaced
922:26da827e8fb5 | 923:2a9f1eb6e0ed |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 | |
8 This program is free software; you can redistribute it and/or | |
9 modify it under the terms of the GNU General Public License as | |
10 published by the Free Software Foundation; either version 2 of the | |
11 License, or (at your option) any later version. See the file | |
12 COPYING included with this distribution for more information. | |
13 */ | |
14 | |
15 #include "LevelPanWidget.h" | |
16 | |
17 #include <QPainter> | |
18 #include <QMouseEvent> | |
19 #include <QWheelEvent> | |
20 | |
21 #include "layer/ColourMapper.h" | |
22 | |
23 #include <iostream> | |
24 | |
25 using std::cerr; | |
26 using std::endl; | |
27 | |
28 static const int maxLevel = 5; | |
29 static const int maxPan = 2; // range is -maxPan to maxPan | |
30 | |
31 LevelPanWidget::LevelPanWidget(QWidget *parent) : | |
32 QWidget(parent), | |
33 m_level(maxLevel), | |
34 m_pan(0), | |
35 m_editable(true) | |
36 { | |
37 } | |
38 | |
39 LevelPanWidget::~LevelPanWidget() | |
40 { | |
41 } | |
42 | |
43 void | |
44 LevelPanWidget::setLevel(float level) | |
45 { | |
46 m_level = int(round(level * maxLevel)); | |
47 if (m_level < 0) m_level = 0; | |
48 if (m_level > maxLevel) m_level = maxLevel; | |
49 update(); | |
50 } | |
51 | |
52 void | |
53 LevelPanWidget::setPan(float pan) | |
54 { | |
55 m_pan = int(round(pan * maxPan)); | |
56 if (m_pan < -maxPan) m_pan = -maxPan; | |
57 if (m_pan > maxPan) m_pan = maxPan; | |
58 update(); | |
59 } | |
60 | |
61 void | |
62 LevelPanWidget::setEditable(bool editable) | |
63 { | |
64 m_editable = editable; | |
65 update(); | |
66 } | |
67 | |
68 float | |
69 LevelPanWidget::getLevel() const | |
70 { | |
71 return float(m_level) / float(maxLevel); | |
72 } | |
73 | |
74 float | |
75 LevelPanWidget::getPan() const | |
76 { | |
77 return float(m_pan) / float(maxPan); | |
78 } | |
79 | |
80 void | |
81 LevelPanWidget::emitLevelChanged() | |
82 { | |
83 cerr << "emitting levelChanged(" << getLevel() << ")" << endl; | |
84 emit levelChanged(getLevel()); | |
85 } | |
86 | |
87 void | |
88 LevelPanWidget::emitPanChanged() | |
89 { | |
90 cerr << "emitting panChanged(" << getPan() << ")" << endl; | |
91 emit panChanged(getPan()); | |
92 } | |
93 | |
94 void | |
95 LevelPanWidget::mousePressEvent(QMouseEvent *e) | |
96 { | |
97 mouseMoveEvent(e); | |
98 } | |
99 | |
100 void | |
101 LevelPanWidget::mouseMoveEvent(QMouseEvent *e) | |
102 { | |
103 if (!m_editable) return; | |
104 | |
105 int level, pan; | |
106 toCell(e->pos(), level, pan); | |
107 if (level == m_level && pan == m_pan) { | |
108 return; | |
109 } | |
110 if (level != m_level) { | |
111 m_level = level; | |
112 emitLevelChanged(); | |
113 } | |
114 if (pan != m_pan) { | |
115 m_pan = pan; | |
116 emitPanChanged(); | |
117 } | |
118 update(); | |
119 } | |
120 | |
121 void | |
122 LevelPanWidget::mouseReleaseEvent(QMouseEvent *e) | |
123 { | |
124 mouseMoveEvent(e); | |
125 } | |
126 | |
127 void | |
128 LevelPanWidget::wheelEvent(QWheelEvent *e) | |
129 { | |
130 if (e->modifiers() & Qt::ControlModifier) { | |
131 if (e->delta() > 0) { | |
132 if (m_pan < maxPan) { | |
133 ++m_pan; | |
134 emitPanChanged(); | |
135 update(); | |
136 } | |
137 } else { | |
138 if (m_pan > -maxPan) { | |
139 --m_pan; | |
140 emitPanChanged(); | |
141 update(); | |
142 } | |
143 } | |
144 } else { | |
145 if (e->delta() > 0) { | |
146 if (m_level < maxLevel) { | |
147 ++m_level; | |
148 emitLevelChanged(); | |
149 update(); | |
150 } | |
151 } else { | |
152 if (m_level > 0) { | |
153 --m_level; | |
154 emitLevelChanged(); | |
155 update(); | |
156 } | |
157 } | |
158 } | |
159 } | |
160 | |
161 void | |
162 LevelPanWidget::toCell(QPointF loc, int &level, int &pan) const | |
163 { | |
164 double w = width(), h = height(); | |
165 int npan = maxPan * 2 + 1; | |
166 double wcell = w / npan, hcell = h / maxLevel; | |
167 level = int((h - loc.y()) / hcell) + 1; | |
168 if (level < 1) level = 1; | |
169 if (level > maxLevel) level = maxLevel; | |
170 pan = int(loc.x() / wcell) - maxPan; | |
171 if (pan < -maxPan) pan = -maxPan; | |
172 if (pan > maxPan) pan = maxPan; | |
173 } | |
174 | |
175 QSizeF | |
176 LevelPanWidget::cellSize() const | |
177 { | |
178 double w = width(), h = height(); | |
179 int npan = maxPan * 2 + 1; | |
180 double wcell = w / npan, hcell = h / maxLevel; | |
181 return QSizeF(wcell, hcell); | |
182 } | |
183 | |
184 QPointF | |
185 LevelPanWidget::cellCentre(int level, int pan) const | |
186 { | |
187 QSizeF cs = cellSize(); | |
188 return QPointF(cs.width() * (pan + maxPan) + cs.width() / 2., | |
189 height() - cs.height() * level + cs.height() / 2.); | |
190 } | |
191 | |
192 QSizeF | |
193 LevelPanWidget::cellLightSize() const | |
194 { | |
195 double extent = 3. / 4.; | |
196 QSizeF cs = cellSize(); | |
197 double m = std::min(cs.width(), cs.height()); | |
198 return QSizeF(m * extent, m * extent); | |
199 } | |
200 | |
201 QRectF | |
202 LevelPanWidget::cellLightRect(int level, int pan) const | |
203 { | |
204 QSizeF cls = cellLightSize(); | |
205 QPointF cc = cellCentre(level, pan); | |
206 return QRectF(cc.x() - cls.width() / 2., | |
207 cc.y() - cls.height() / 2., | |
208 cls.width(), | |
209 cls.height()); | |
210 } | |
211 | |
212 double | |
213 LevelPanWidget::thinLineWidth() const | |
214 { | |
215 double tw = ceil(width() / (maxPan * 2. * 10.)); | |
216 double th = ceil(height() / (maxLevel * 10.)); | |
217 return std::min(th, tw); | |
218 } | |
219 | |
220 void | |
221 LevelPanWidget::paintEvent(QPaintEvent *) | |
222 { | |
223 QPainter paint(this); | |
224 ColourMapper mapper(ColourMapper::Sunset, 0, maxLevel); | |
225 | |
226 paint.setRenderHint(QPainter::Antialiasing, true); | |
227 | |
228 QPen pen; | |
229 | |
230 double thin = thinLineWidth(); | |
231 | |
232 pen.setColor(QColor(127, 127, 127, 127)); | |
233 pen.setWidthF(cellLightSize().width() + thin); | |
234 pen.setCapStyle(Qt::RoundCap); | |
235 paint.setPen(pen); | |
236 | |
237 for (int pan = -maxPan; pan <= maxPan; ++pan) { | |
238 paint.drawLine(cellCentre(1, pan), cellCentre(maxLevel, pan)); | |
239 } | |
240 | |
241 pen.setColor(Qt::black); | |
242 pen.setWidthF(thin); | |
243 pen.setCapStyle(Qt::FlatCap); | |
244 paint.setPen(pen); | |
245 | |
246 for (int level = 1; level <= m_level; ++level) { | |
247 // level starts at 1 because we handle mute separately | |
248 paint.setBrush(mapper.map(level)); | |
249 paint.drawEllipse(cellLightRect(level, m_pan)); | |
250 } | |
251 } | |
252 | |
253 |