00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qpainter.h>
00011 #include <qpalette.h>
00012 #include <qstyle.h>
00013 #include <qevent.h>
00014 #include "qwt_knob.h"
00015 #include "qwt_math.h"
00016 #include "qwt_paint_buffer.h"
00017
00023 QwtKnob::QwtKnob(QWidget* parent, const char *name):
00024 QwtSliderBase(Qt::Horizontal, parent, name,
00025 Qt::WRepaintNoErase|Qt::WResizeNoErase)
00026 {
00027 d_angle = 0.0;
00028 d_oldAngle = 0.0;
00029 d_nTurns = 0.0;
00030 d_borderWidth = 2;
00031 d_borderDist = 4;
00032 d_totalAngle = 270.0;
00033 d_scaleDist = 4;
00034 d_hasScale = 0;
00035 d_symbol = Line;
00036 d_maxScaleTicks = 11;
00037 d_knobWidth = 50;
00038 d_dotWidth = 8;
00039
00040 scaleDraw()->setGeometry(
00041 0, 0, d_knobWidth + 2 * d_scaleDist, QwtScaleDraw::Round );
00042 setUpdateTime(50);
00043 setTotalAngle( 270.0 );
00044 recalcAngle();
00045 setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
00046 }
00047
00049 QwtKnob::~QwtKnob()
00050 {
00051 }
00052
00057 void QwtKnob::setSymbol(QwtKnob::Symbol s)
00058 {
00059 if ( d_symbol != s )
00060 {
00061 d_symbol = s;
00062 update();
00063 }
00064 }
00065
00070 QwtKnob::Symbol QwtKnob::symbol() const
00071 {
00072 return d_symbol;
00073 }
00074
00083 void QwtKnob::setTotalAngle (double angle)
00084 {
00085 if (angle < 10.0)
00086 d_totalAngle = 10.0;
00087 else
00088 d_totalAngle = angle;
00089 scaleDraw()->setAngleRange( -0.5 * d_totalAngle, 0.5 * d_totalAngle);
00090 layoutKnob();
00091 }
00092
00093
00099 void QwtKnob::drawKnob(QPainter *p, const QRect &r)
00100 {
00101 const int bw2 = d_borderWidth / 2;
00102
00103 QRect aRect(r.x() + bw2, r.y() + bw2,
00104 r.width() - 2 * bw2, r.height() - 2 * bw2);
00105
00106
00107
00108
00109 p->setBrush(colorGroup().brush(QColorGroup::Button));
00110 p->drawEllipse(aRect);
00111
00112
00113
00114
00115 QPen pn;
00116 pn.setWidth(d_borderWidth);
00117
00118 pn.setColor(colorGroup().light());
00119 p->setPen(pn);
00120 p->drawArc(aRect, 45*16,180*16);
00121
00122 pn.setColor(colorGroup().dark());
00123 p->setPen(pn);
00124 p->drawArc(aRect, 225*16,180*16);
00125
00126
00127
00128
00129 if ( isValid() )
00130 drawMarker(p, d_angle, colorGroup().buttonText());
00131 }
00132
00139 void QwtKnob::valueChange()
00140 {
00141 recalcAngle();
00142 update();
00143 QwtSliderBase::valueChange();
00144 }
00145
00152 double QwtKnob::getValue(const QPoint &p)
00153 {
00154 const double dx = double((rect().x() + rect().width() / 2) - p.x() );
00155 const double dy = double((rect().y() + rect().height() / 2) - p.y() );
00156
00157 const double arc = atan2(-dx,dy) * 180.0 / M_PI;
00158
00159 double newValue = 0.5 * (minValue() + maxValue())
00160 + (arc + d_nTurns * 360.0) * (maxValue() - minValue())
00161 / d_totalAngle;
00162
00163 const double oneTurn = fabs(maxValue() - minValue()) * 360.0 / d_totalAngle;
00164 const double eqValue = value() + d_mouseOffset;
00165
00166 if (fabs(newValue - eqValue) > 0.5 * oneTurn)
00167 {
00168 if (newValue < eqValue)
00169 newValue += oneTurn;
00170 else
00171 newValue -= oneTurn;
00172 }
00173
00174 return newValue;
00175 }
00176
00183 void QwtKnob::getScrollMode(const QPoint &p, int &scrollMode, int &direction)
00184 {
00185 const int r = d_kRect.width() / 2;
00186
00187 const int dx = d_kRect.x() + r - p.x();
00188 const int dy = d_kRect.y() + r - p.y();
00189
00190 if ( (dx * dx) + (dy * dy) <= (r * r))
00191 {
00192 scrollMode = ScrMouse;
00193 direction = 0;
00194 }
00195 else
00196 {
00197 scrollMode = ScrTimer;
00198 double arc = atan2(double(-dx),double(dy)) * 180.0 / M_PI;
00199 if ( arc < d_angle)
00200 direction = -1;
00201 else if (arc > d_angle)
00202 direction = 1;
00203 else
00204 direction = 0;
00205 }
00206 }
00207
00208
00214 void QwtKnob::rangeChange()
00215 {
00216 if (!hasUserScale())
00217 {
00218 scaleDraw()->setScale(minValue(), maxValue(),
00219 scaleMaxMajor(), scaleMaxMinor());
00220 }
00221 layoutKnob();
00222 recalcAngle();
00223 }
00224
00228 void QwtKnob::resizeEvent(QResizeEvent *)
00229 {
00230 layoutKnob( FALSE );
00231 }
00232
00234
00235
00236
00237 void QwtKnob::layoutKnob( bool update_geometry )
00238 {
00239 const QRect &r = rect();
00240
00241 const int width = qwtMin(qwtMin(r.height(), r.width()), d_knobWidth);
00242 const int width_2 = width / 2;
00243
00244 d_kRect.setRect(r.x() + r.width() / 2 - width_2,
00245 r.y() + r.height() / 2 - width_2,
00246 width, width);
00247
00248 scaleDraw()->setGeometry(d_kRect.x() - d_scaleDist,
00249 d_kRect.y() - d_scaleDist,
00250 width + 2 * d_scaleDist, QwtScaleDraw::Round );
00251
00252 if ( update_geometry )
00253 {
00254 updateGeometry();
00255 update();
00256 }
00257 }
00258
00262 void QwtKnob::paintEvent(QPaintEvent *e)
00263 {
00264 const QRect &ur = e->rect();
00265 if ( ur.isValid() )
00266 {
00267 QwtPaintBuffer paintBuffer(this, ur);
00268 draw(paintBuffer.painter(), ur);
00269 }
00270 }
00271
00275 void QwtKnob::draw(QPainter *painter, const QRect& ur)
00276 {
00277 if ( !d_kRect.contains( ur ) )
00278 scaleDraw()->draw( painter );
00279 drawKnob( painter, d_kRect );
00280
00281 if ( hasFocus() )
00282 {
00283 QRect r = rect();
00284
00285 #if QT_VERSION < 300
00286 style().drawFocusRect(painter, r, colorGroup());
00287 #else
00288 style().drawPrimitive(QStyle::PE_FocusRect, painter,
00289 r, colorGroup());
00290 #endif
00291 }
00292
00293 }
00294
00301 void QwtKnob::drawMarker(QPainter *p, double arc, const QColor &c)
00302 {
00303 const double rarc = arc * M_PI / 180.0;
00304 const double ca = cos(rarc);
00305 const double sa = - sin(rarc);
00306
00307 int radius = d_kRect.width() / 2 - d_borderWidth;
00308 if (radius < 3)
00309 radius = 3;
00310
00311 const int ym = d_kRect.y() + radius + d_borderWidth;
00312 const int xm = d_kRect.x() + radius + d_borderWidth;
00313
00314 switch (d_symbol)
00315 {
00316 case Dot:
00317 {
00318 p->setBrush(c);
00319 p->setPen(Qt::NoPen);
00320
00321 const double rb = double(qwtMax(radius - 4 - d_dotWidth / 2, 0));
00322 p->drawEllipse(xm - int(floor (sa * rb + 0.5)) - d_dotWidth / 2,
00323 ym - int(floor (ca * rb + 0.5)) - d_dotWidth / 2,
00324 d_dotWidth, d_dotWidth);
00325 break;
00326 }
00327 case Line:
00328 {
00329 p->setPen(QPen(c, 2));
00330
00331 const double rb = qwtMax(double((radius - 4) / 3.0), 0.0);
00332 const double re = qwtMax(double(radius - 4), 0.0);
00333
00334 p->drawLine (xm - int (floor (sa * rb + 0.5)),
00335 ym - int (floor (ca * rb + 0.5)),
00336 xm - int (floor (sa * re + 0.5)),
00337 ym - int (floor (ca * re + 0.5)));
00338
00339 break;
00340 }
00341 }
00342 }
00343
00350 void QwtKnob::setKnobWidth(int w)
00351 {
00352 d_knobWidth = qwtMax(w,5);
00353 layoutKnob();
00354 }
00355
00360 void QwtKnob::setBorderWidth(int bw)
00361 {
00362 d_borderWidth = qwtMax(bw, 0);
00363 layoutKnob();
00364 }
00365
00370 void QwtKnob::recalcAngle()
00371 {
00372 d_oldAngle = d_angle;
00373
00374
00375
00376
00377 if (maxValue() == minValue())
00378 {
00379 d_angle = 0;
00380 d_nTurns = 0;
00381 }
00382 else
00383 {
00384 d_angle = (value() - 0.5 * (minValue() + maxValue()))
00385 / (maxValue() - minValue()) * d_totalAngle;
00386 d_nTurns = floor((d_angle + 180.0) / 360.0);
00387 d_angle = d_angle - d_nTurns * 360.0;
00388 }
00389 }
00390
00391
00396 void QwtKnob::scaleChange()
00397 {
00398 layoutKnob();
00399 }
00400
00405 void QwtKnob::fontChange(const QFont &f)
00406 {
00407 QwtSliderBase::fontChange( f );
00408 layoutKnob();
00409 }
00410
00414 QSize QwtKnob::sizeHint() const
00415 {
00416 return minimumSizeHint();
00417 }
00418
00424 QSize QwtKnob::minimumSizeHint() const
00425 {
00426
00427 const int sh = scaleDraw()->minHeight( QPen(), fontMetrics() );
00428 const int d = 2 * sh + 2 * d_scaleDist + d_knobWidth;
00429
00430 return QSize( d, d );
00431 }
00432
00433
00434
00435
00436
00437