1 //=============================================================================
2 // Awl
3 // Audio Widget Library
4 //
5 // Copyright (C) 2002-2006 by Werner Schweer and others
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "knob.h"
21
22 namespace Awl {
23
24 //---------------------------------------------------------
25 // Knob
26 /// this is the AwlKnob constructor
27 //---------------------------------------------------------
28
Knob(QWidget * parent)29 Knob::Knob(QWidget* parent)
30 : AbstractSlider(parent)
31 {
32 _spanDegrees = 270;
33 _markSize = 6;
34 _border = 2;
35 points = 0;
36 startY = 0;
37 }
38
39 //---------------------------------------------------------
40 // Knob
41 //---------------------------------------------------------
42
~Knob()43 Knob::~Knob()
44 {
45 if (points)
46 delete points;
47 }
48
49 //---------------------------------------------------------
50 // setText
51 //---------------------------------------------------------
52
setText(const QString & s)53 void Knob::setText(const QString& s)
54 {
55 if (s != _text) {
56 _text = s;
57 update();
58 }
59 }
60
61 //---------------------------------------------------------
62 // setScaleSize
63 //! set the scale size in degrees
64 //
65 //! the scale size is the max moving angle measured
66 //! in degrees
67 //---------------------------------------------------------
68
setSpanDegrees(double val)69 void Knob::setSpanDegrees(double val)
70 {
71 if (val != _spanDegrees) {
72 _spanDegrees = val;
73 update();
74 }
75 }
76
77 //---------------------------------------------------------
78 // setMarkSize
79 //! set size of the center marker
80 //---------------------------------------------------------
81
setMarkSize(int val)82 void Knob::setMarkSize(int val)
83 {
84 if (val != _markSize) {
85 _markSize = val;
86 update();
87 }
88 }
89
90 //---------------------------------------------------------
91 // setBorder
92 //! set border size
93 //---------------------------------------------------------
94
setBorder(int val)95 void Knob::setBorder(int val)
96 {
97 if (val != _border) {
98 _border = val;
99 update();
100 }
101 }
102
103 //---------------------------------------------------------
104 // setKnobIcon
105 //---------------------------------------------------------
106
setKnobIcon(const QIcon & icon)107 void Knob::setKnobIcon(const QIcon& icon)
108 {
109 _knobIcon = icon;
110 update();
111 }
112
113 //---------------------------------------------------------
114 // mousePressEvent
115 //---------------------------------------------------------
116
mousePressEvent(QMouseEvent * ev)117 void Knob::mousePressEvent(QMouseEvent* ev)
118 {
119 startY = ev->y();
120 emit sliderPressed(__id);
121 if (_center) {
122 QRect r(points->boundingRect().toRect());
123 if (r.contains(ev->pos())) {
124 auto centerVal = (maxValue() - minValue()) / 2 + 0.5;
125 setValue(centerVal);
126 valueChange();
127 }
128 }
129 }
130
131 //---------------------------------------------------------
132 // mouseReleaseEvent
133 //---------------------------------------------------------
134
mouseReleaseEvent(QMouseEvent *)135 void Knob::mouseReleaseEvent(QMouseEvent*)
136 {
137 emit sliderReleased(__id);
138 }
139
140 //---------------------------------------------------------
141 // mouseMoveEvent
142 //---------------------------------------------------------
143
mouseMoveEvent(QMouseEvent * ev)144 void Knob::mouseMoveEvent(QMouseEvent* ev)
145 {
146 int y = ev->y();
147 double delta = (maxValue() - minValue()) / 100.0f;
148 if (delta == 0)
149 delta = 1;
150 _value += (startY - y) * delta;
151 if (_value < minValue())
152 _value = _minValue;
153 else if (_value > maxValue())
154 _value = _maxValue;
155 startY = y;
156 valueChange();
157 }
158
159 //---------------------------------------------------------
160 // paintEvent
161 // r - phys coord system
162 //---------------------------------------------------------
163
paintEvent(QPaintEvent *)164 void Knob::paintEvent(QPaintEvent* /*ev*/)
165 {
166 #if 0 // yet(?) unused
167 QRect rr(ev->rect());
168 #endif
169 QPainter p(this);
170 p.setRenderHint(QPainter::Antialiasing, true);
171
172 int markSize2 = _markSize/2;
173 int emptyDegrees = 360 - _spanDegrees;
174 int w = width() - _scaleWidth - 2 * _border;
175 int h = height() - _scaleWidth/2 - 2 * _border;
176
177 int xoffset, yoffset;
178 if (_center)
179 h -= _markSize;
180 if (w > h) {
181 yoffset = 0;
182 xoffset = (w - h) / 2;
183 w = h;
184 }
185 else {
186 xoffset = 0;
187 yoffset = h - w; // top align
188 h = w;
189 }
190
191 int x = xoffset + _scaleWidth / 2 + _border;
192 int y = yoffset + _scaleWidth / 2 + _border + (_center ? _markSize+_scaleWidth/2 : 0);
193 QRectF dialArea(x, y, w, h);
194
195 QColor dialBgCol(isEnabled() ? _scaleColor : Qt::gray);
196 QColor dialCol(isEnabled() ? _scaleValueColor : Qt::lightGray);
197
198 //-----------------------------------------
199 // draw arc
200 //-----------------------------------------
201
202 double maxVal = maxValue();
203 double minVal = minValue();
204 double val = value();
205
206 double span = maxVal - minVal;
207
208 p.setPen(QPen(dialBgCol, _scaleWidth));
209 p.drawArc(dialArea, (90 + (_spanDegrees / 2)) * 16, -_spanDegrees * 16);
210
211 if (_center) {
212 double frac = (val - minVal) / span - 0.5;
213
214 p.setPen(QPen(dialCol, _scaleWidth));
215 p.drawArc(dialArea, 90 * 16, -frac * _spanDegrees * 16);
216 }
217 else {
218 double frac = (val - minVal) / span;
219
220 p.setPen(QPen(dialBgCol, _scaleWidth));
221 p.drawArc(dialArea, (90 + (_spanDegrees / 2)) * 16, frac * -_spanDegrees * 16);
222 }
223
224 //-----------------------------------------
225 // draw pointer
226 //-----------------------------------------
227
228 //knob image
229 if (!_knobIcon.isNull()) {
230 QRect r((int)dialArea.x(), (int)dialArea.y(), (int)dialArea.width(), (int)dialArea.height());
231 _knobIcon.paint(&p, r);
232 }
233
234 //indicator line
235 p.setPen(QPen(dialCol, _scaleWidth));
236 double r1 = double(_spanDegrees) * (_value - _minValue) / span + 90.0
237 + double(emptyDegrees / 2);
238 r1 = r1 / 180.0 * M_PI; // convert to radians
239 int rd = w/2;
240 int x1 = x + rd;
241 int y1 = y + rd;
242 int x2 = x1 + lrint(cos(r1) * double(rd));
243 int y2 = y1 + lrint(sin(r1) * double(rd));
244 p.drawLine(x1, y1, x2, y2);
245
246
247 //-----------------------------------------
248 // draw center mark
249 //-----------------------------------------
250
251 p.setPen(QPen(dialCol, 0));
252 p.setBrush(dialCol);
253 if (_center) {
254 if (points)
255 delete points;
256 qreal x3 = dialArea.width() / 2 + dialArea.x();
257 qreal y3 = dialArea.y() - _markSize - _scaleWidth/2;
258 points = new QPainterPath(QPointF(x3 - markSize2, y3));
259 points->lineTo(x3 + markSize2, y3);
260 points->lineTo(x3, _markSize + y3);
261 points->closeSubpath();
262 p.drawPath(*points);
263 }
264
265 //-----------------------------------------
266 // draw text
267 //-----------------------------------------
268
269 if (!_text.isEmpty()) {
270 p.drawText(dialArea, Qt::AlignBottom | Qt::AlignHCenter, _text);
271 }
272 }
273 }
274
275