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