1
//======================================================================
4
// $Id: knob.cpp,v 1.1 2002/01/30 14:54:03 muse Exp $
5
// (C) Copyright 1999 Werner Schweer (ws@seh.de)
7
// Adapted from Qwt Lib:
8
// Copyright (C) 1997 Josef Wilgen
9
// This program is free software; you can redistribute it and/or modify
10
// it under the terms of the GNU General Public License, version 2,
11
// as published by the Free Software Foundation.
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with this program; if not, write to the Free Software
18
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
//=========================================================
29
//---------------------------------------------------------
30
// The QwtKnob widget imitates look and behaviour of a volume knob on a radio.
32
// a scale around the knob which is set up automatically or can
33
// be configured manually (see @^QwtScaleIf@).
34
// Automatic scrolling is enabled when the user presses a mouse
35
// button on the scale. For a description of signals, slots and other
36
// members, see QwtSliderBase@.
37
//---------------------------------------------------------
40
//---------------------------------------------------------
42
//---------------------------------------------------------
44
Knob::Knob(QWidget* parent, const char* name)
45
: SliderBase(parent, name)
56
d_faceColor = backgroundColor();
57
d_markerColor = foregroundColor();
60
setMinimumSize(30,30);
64
//------------------------------------------------------------
65
// QwtKnob::setTotalAngle
66
// Set the total angle by which the knob can be turned
69
// void QwtKnob::setTotalAngle(double angle)
72
// double angle -- angle in degrees.
75
// The default angle is 270 degrees. It is possible to specify
76
// an angle of more than 360 degrees so that the knob can be
77
// turned several times around its axis.
78
//------------------------------------------------------------
80
void Knob::setTotalAngle (double angle)
86
d_scale.setAngleRange( -0.5 * d_totalAngle, 0.5 * d_totalAngle);
89
//------------------------------------------------------------
91
// const QRect &r -- borders of the knob
92
//------------------------------------------------------------
94
void Knob::drawKnob(QPainter* p, const QRect& r)
98
QColorGroup g = colorGroup();
100
int bw2 = d_borderWidth / 2;
102
aRect.setRect(r.x() + bw2,
111
p->setBrush(d_faceColor);
112
p->drawEllipse(aRect);
115
// draw button shades
117
pn.setWidth(d_borderWidth);
120
pn.setColor(g.light());
122
p->drawArc(aRect, 45*16,180*16);
124
pn.setColor(g.dark());
126
p->drawArc(aRect, 225*16,180*16);
131
drawMarker(p, d_angle, d_markerColor);
134
//------------------------------------------------------------
135
//.F QwtSliderBase::valueChange
136
// Notify change of value
139
// double x -- new value
142
// Sets the slider's value to the nearest multiple
144
//------------------------------------------------------------
146
void Knob::valueChange()
150
repaint(kRect, FALSE);
151
SliderBase::valueChange();
154
//------------------------------------------------------------
155
//.F QwtKnob::getValue
156
// Determine the value corresponding to a specified position
159
// const QPoint &p -- point
162
// Called by QwtSliderBase
163
//------------------------------------------------------------
165
double Knob::getValue(const QPoint &p)
172
const QRect& r = rect();
174
double dx = double((r.x() + r.width() / 2) - p.x() );
175
double dy = double((r.y() + r.height() / 2) - p.y() );
177
arc = atan2(-dx,dy) * 180.0 / M_PI;
179
newValue = 0.5 * (minValue() + maxValue())
180
+ (arc + d_nTurns * 360.0) * (maxValue() - minValue())
183
oneTurn = fabs(maxValue() - minValue()) * 360.0 / d_totalAngle;
184
eqValue = value() + d_mouseOffset;
186
if (fabs(newValue - eqValue) > 0.5 * oneTurn)
188
if (newValue < eqValue)
200
//------------------------------------------------------------
202
//.F QwtKnob::setScrollMode
203
// Determine the scrolling mode and direction
204
// corresponding to a specified position
207
// const QPoint &p -- point in question
210
// Called by QwtSliderBase
211
//------------------------------------------------------------
212
void Knob::getScrollMode(const QPoint &p, int &scrollMode, int &direction)
217
r = kRect.width() / 2;
219
dx = kRect.x() + r - p.x();
220
dy = kRect.y() + r - p.y();
222
if ( (dx * dx) + (dy * dy) <= (r * r)) // point is inside the knob
224
scrollMode = ScrMouse;
227
else // point lies outside
229
scrollMode = ScrTimer;
230
arc = atan2(double(-dx),double(dy)) * 180.0 / M_PI;
233
else if (arc > d_angle)
243
//------------------------------------------------------------
244
//.F QwtKnob::rangeChange
245
// Notify a change of the range
248
// Called by QwtSliderBase
249
//------------------------------------------------------------
251
void Knob::rangeChange()
255
d_scale.setScale(minValue(), maxValue(),
256
d_maxMajor, d_maxMinor);
263
//---------------------------------------------------------
265
//---------------------------------------------------------
267
void Knob::resizeEvent(QResizeEvent *)
271
const QRect& r = rect();
273
// printf("resize %d %d %d\n", r.height(), r.width(), d_knobWidth);
275
// width = qwtMin(qwtMin(r.height(), r.width()), d_knobWidth);
276
width = qwtMin(r.height(), r.width());
279
int x = r.x() + r.width() / 2 - width_2;
280
int y = r.y() + r.height() / 2 - width_2;
282
kRect.setRect(x, y, width, width);
284
x = kRect.x() - d_scaleDist;
285
y = kRect.y() - d_scaleDist;
286
int w = width + 2 * d_scaleDist;
288
d_scale.setGeometry(x, y, w, ScaleDraw::Round);
291
//------------------------------------------------------------
293
//------------------------------------------------------------
295
void Knob::paintEvent(QPaintEvent* e)
298
const QRect &r = e->rect();
300
if ((r == kRect) && d_newVal ) { // event from valueChange()
301
if (d_newVal > 1) // lost paintEvents()?
304
drawMarker(&p, d_oldAngle, d_faceColor);
305
drawMarker(&p, d_angle, d_markerColor);
317
//------------------------------------------------------------
319
//.F QwtKnob::drawMarker
320
// Draw the marker at the knob's front
323
//.p QPainter *p -- painter
324
// double arc -- angle of the marker
325
// const QColor &c -- marker color
328
// void QwtKnob::drawMarker(QPainter *p)
330
//------------------------------------------------------------
331
void Knob::drawMarker(QPainter *p, double arc, const QColor &c)
339
rarc = arc * M_PI / 180.0;
340
double ca = cos(rarc);
341
double sa = - sin(rarc);
342
radius = kRect.width() / 2 - d_borderWidth;
343
if (radius < 3) radius = 3;
344
int ym = kRect.y() + radius + d_borderWidth;
345
int xm = kRect.x() + radius + d_borderWidth;
353
rb = double(qwtMax(radius - 4 - d_dotWidth / 2, 0));
354
p->drawEllipse(xm - int(rint(sa * rb)) - d_dotWidth / 2,
355
ym - int(rint(ca * rb)) - d_dotWidth / 2,
356
d_dotWidth, d_dotWidth);
366
rb = qwtMax(double((radius - 4) / 3.0), 0.0);
367
re = qwtMax(double(radius - 4), 0.0);
369
p->drawLine( xm - int(rint(sa * rb)),
370
ym - int(rint(ca * rb)),
371
xm - int(rint(sa * re)),
372
ym - int(rint(ca * re)));
380
//------------------------------------------------------------
382
//.F QwtKnob::setKnobWidth
383
// Change the knob's width.
386
//.f void QwtKnob::setKnobWidth(int w)
389
//.p int w -- new width
392
// The specified width must be >= 5, or it will be clipped.
394
//------------------------------------------------------------
395
void Knob::setKnobWidth(int w)
397
d_knobWidth = qwtMax(w,5);
402
//------------------------------------------------------------
404
//.F QwtKnob::setBorderWidth
405
// Set the knob's border width
408
//.f void QwtKnob::setBorderWidth(int bw)
411
//.p int bw -- new border width
413
//------------------------------------------------------------
414
void Knob::setBorderWidth(int bw)
416
d_borderWidth = qwtMax(bw, 0);
421
//------------------------------------------------------------
423
//.F QwtKnob::recalcAngle
424
// Recalculate the marker angle corresponding to the
428
//.f void QwtKnob::recalcAngle()
430
//------------------------------------------------------------
431
void Knob::recalcAngle()
433
d_oldAngle = d_angle;
436
// calculate the angle corresponding to the value
438
if (maxValue() == minValue())
445
d_angle = (value() - 0.5 * (minValue() + maxValue()))
446
/ (maxValue() - minValue()) * d_totalAngle;
447
d_nTurns = floor((d_angle + 180.0) / 360.0);
448
d_angle = d_angle - d_nTurns * 360.0;