00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qpainter.h>
00011 #include <qpalette.h>
00012 #include <qstyle.h>
00013 #include "qwt_knob.h"
00014 #include "qwt_math.h"
00015 #include "qwt_paint_buffer.h"
00016
00022 QwtKnob::QwtKnob(QWidget* parent, const char *name):
00023 QwtSliderBase(Qt::Horizontal, parent, name, WRepaintNoErase|WResizeNoErase)
00024 {
00025 d_angle = 0.0;
00026 d_oldAngle = 0.0;
00027 d_nTurns = 0.0;
00028 d_borderWidth = 2;
00029 d_borderDist = 4;
00030 d_totalAngle = 270.0;
00031 d_scaleDist = 4;
00032 d_hasScale = 0;
00033 d_symbol = Line;
00034 d_maxScaleTicks = 11;
00035 d_knobWidth = 50;
00036 d_dotWidth = 8;
00037
00038 d_scaleDraw->setGeometry( 0, 0, d_knobWidth + 2 * d_scaleDist,
00039 QwtScaleDraw::Round );
00040 setUpdateTime(50);
00041 setTotalAngle( 270.0 );
00042 recalcAngle();
00043 }
00044
00046 QwtKnob::~QwtKnob()
00047 {
00048 }
00049
00054 void QwtKnob::setSymbol(QwtKnob::Symbol s)
00055 {
00056 if ( d_symbol != s )
00057 {
00058 d_symbol = s;
00059 update();
00060 }
00061 }
00062
00067 QwtKnob::Symbol QwtKnob::symbol() const
00068 {
00069 return d_symbol;
00070 }
00071
00080 void QwtKnob::setTotalAngle (double angle)
00081 {
00082 if (angle < 10.0)
00083 d_totalAngle = 10.0;
00084 else
00085 d_totalAngle = angle;
00086 d_scaleDraw->setAngleRange( -0.5 * d_totalAngle, 0.5 * d_totalAngle);
00087 layoutKnob();
00088 }
00089
00090
00096 void QwtKnob::drawKnob(QPainter *p, const QRect &r)
00097 {
00098 const int bw2 = d_borderWidth / 2;
00099
00100 QRect aRect(r.x() + bw2, r.y() + bw2,
00101 r.width() - 2 * bw2, r.height() - 2 * bw2);
00102
00103
00104
00105
00106 p->setBrush(colorGroup().brush(QColorGroup::Button));
00107 p->drawEllipse(aRect);
00108
00109
00110
00111
00112 QPen pn;
00113 pn.setWidth(d_borderWidth);
00114
00115 pn.setColor(colorGroup().light());
00116 p->setPen(pn);
00117 p->drawArc(aRect, 45*16,180*16);
00118
00119 pn.setColor(colorGroup().dark());
00120 p->setPen(pn);
00121 p->drawArc(aRect, 225*16,180*16);
00122
00123
00124
00125
00126 drawMarker(p, d_angle, colorGroup().buttonText());
00127 }
00128
00135 void QwtKnob::valueChange()
00136 {
00137 recalcAngle();
00138 update();
00139 QwtSliderBase::valueChange();
00140 }
00141
00148 double QwtKnob::getValue(const QPoint &p)
00149 {
00150 const double dx = double((rect().x() + rect().width() / 2) - p.x() );
00151 const double dy = double((rect().y() + rect().height() / 2) - p.y() );
00152
00153 const double arc = atan2(-dx,dy) * 180.0 / M_PI;
00154
00155 double newValue = 0.5 * (minValue() + maxValue())
00156 + (arc + d_nTurns * 360.0) * (maxValue() - minValue())
00157 / d_totalAngle;
00158
00159 const double oneTurn = fabs(maxValue() - minValue()) * 360.0 / d_totalAngle;
00160 const double eqValue = value() + d_mouseOffset;
00161
00162 if (fabs(newValue - eqValue) > 0.5 * oneTurn)
00163 {
00164 if (newValue < eqValue)
00165 newValue += oneTurn;
00166 else
00167 newValue -= oneTurn;
00168 }
00169
00170 return newValue;
00171 }
00172
00179 void QwtKnob::getScrollMode(const QPoint &p, int &scrollMode, int &direction)
00180 {
00181 const int r = d_kRect.width() / 2;
00182
00183 const int dx = d_kRect.x() + r - p.x();
00184 const int dy = d_kRect.y() + r - p.y();
00185
00186 if ( (dx * dx) + (dy * dy) <= (r * r))
00187 {
00188 scrollMode = ScrMouse;
00189 direction = 0;
00190 }
00191 else
00192 {
00193 scrollMode = ScrTimer;
00194 double arc = atan2(double(-dx),double(dy)) * 180.0 / M_PI;
00195 if ( arc < d_angle)
00196 direction = -1;
00197 else if (arc > d_angle)
00198 direction = 1;
00199 else
00200 direction = 0;
00201 }
00202 }
00203
00204
00210 void QwtKnob::rangeChange()
00211 {
00212 if (!hasUserScale())
00213 {
00214 d_scaleDraw->setScale(minValue(), maxValue(),
00215 d_maxMajor, d_maxMinor);
00216 }
00217 layoutKnob();
00218 recalcAngle();
00219 }
00220
00224 void QwtKnob::resizeEvent(QResizeEvent *)
00225 {
00226 layoutKnob( FALSE );
00227 }
00228
00230
00231
00232
00233 void QwtKnob::layoutKnob( bool update_geometry )
00234 {
00235 const QRect &r = rect();
00236
00237 const int width = qwtMin(qwtMin(r.height(), r.width()), d_knobWidth);
00238 const int width_2 = width / 2;
00239
00240 d_kRect.setRect(r.x() + r.width() / 2 - width_2,
00241 r.y() + r.height() / 2 - width_2,
00242 width, width);
00243
00244 d_scaleDraw->setGeometry(d_kRect.x() - d_scaleDist,
00245 d_kRect.y() - d_scaleDist,
00246 width + 2 * d_scaleDist, QwtScaleDraw::Round );
00247
00248 if ( update_geometry )
00249 {
00250 updateGeometry();
00251 update();
00252 }
00253 }
00254
00258 void QwtKnob::paintEvent(QPaintEvent *e)
00259 {
00260 const QRect &ur = e->rect();
00261 if ( ur.isValid() )
00262 {
00263 QwtPaintBuffer paintBuffer(this, ur);
00264 draw(paintBuffer.painter(), ur);
00265 }
00266 }
00267
00271 void QwtKnob::draw(QPainter *painter, const QRect& ur)
00272 {
00273 if ( !d_kRect.contains( ur ) )
00274 d_scaleDraw->draw( painter );
00275 drawKnob( painter, d_kRect );
00276
00277 if ( hasFocus() )
00278 {
00279 QRect r = rect();
00280
00281 #if QT_VERSION < 300
00282 style().drawFocusRect(painter, r, colorGroup());
00283 #else
00284 style().drawPrimitive(QStyle::PE_FocusRect, painter,
00285 r, colorGroup());
00286 #endif
00287 }
00288
00289 }
00290
00297 void QwtKnob::drawMarker(QPainter *p, double arc, const QColor &c)
00298 {
00299 const double rarc = arc * M_PI / 180.0;
00300 const double ca = cos(rarc);
00301 const double sa = - sin(rarc);
00302
00303 int radius = d_kRect.width() / 2 - d_borderWidth;
00304 if (radius < 3)
00305 radius = 3;
00306
00307 const int ym = d_kRect.y() + radius + d_borderWidth;
00308 const int xm = d_kRect.x() + radius + d_borderWidth;
00309
00310 switch (d_symbol)
00311 {
00312 case Dot:
00313 {
00314 p->setBrush(c);
00315 p->setPen(NoPen);
00316
00317 const double rb = double(qwtMax(radius - 4 - d_dotWidth / 2, 0));
00318 p->drawEllipse(xm - int(floor (sa * rb + 0.5)) - d_dotWidth / 2,
00319 ym - int(floor (ca * rb + 0.5)) - d_dotWidth / 2,
00320 d_dotWidth, d_dotWidth);
00321 break;
00322 }
00323 case Line:
00324 {
00325 p->setPen(QPen(c, 2));
00326
00327 const double rb = qwtMax(double((radius - 4) / 3.0), 0.0);
00328 const double re = qwtMax(double(radius - 4), 0.0);
00329
00330 p->drawLine (xm - int (floor (sa * rb + 0.5)),
00331 ym - int (floor (ca * rb + 0.5)),
00332 xm - int (floor (sa * re + 0.5)),
00333 ym - int (floor (ca * re + 0.5)));
00334
00335 break;
00336 }
00337 }
00338 }
00339
00346 void QwtKnob::setKnobWidth(int w)
00347 {
00348 d_knobWidth = qwtMax(w,5);
00349 layoutKnob();
00350 }
00351
00356 void QwtKnob::setBorderWidth(int bw)
00357 {
00358 d_borderWidth = qwtMax(bw, 0);
00359 layoutKnob();
00360 }
00361
00366 void QwtKnob::recalcAngle()
00367 {
00368 d_oldAngle = d_angle;
00369
00370
00371
00372
00373 if (maxValue() == minValue())
00374 {
00375 d_angle = 0;
00376 d_nTurns = 0;
00377 }
00378 else
00379 {
00380 d_angle = (value() - 0.5 * (minValue() + maxValue()))
00381 / (maxValue() - minValue()) * d_totalAngle;
00382 d_nTurns = floor((d_angle + 180.0) / 360.0);
00383 d_angle = d_angle - d_nTurns * 360.0;
00384 }
00385 }
00386
00387
00392 void QwtKnob::scaleChange()
00393 {
00394 layoutKnob();
00395 }
00396
00401 void QwtKnob::fontChange(const QFont &f)
00402 {
00403 QwtSliderBase::fontChange( f );
00404 layoutKnob();
00405 }
00406
00408 QSizePolicy QwtKnob::sizePolicy() const
00409 {
00410 QSizePolicy sp;
00411 sp.setHorData( QSizePolicy::Fixed );
00412 sp.setVerData( QSizePolicy::Fixed );
00413 return sp;
00414 }
00415
00419 QSize QwtKnob::sizeHint() const
00420 {
00421 return minimumSizeHint();
00422 }
00423
00429 QSize QwtKnob::minimumSizeHint() const
00430 {
00431
00432 const int sh = d_scaleDraw->minHeight( QPen(), fontMetrics() );
00433 const int d = 2 * sh + 2 * d_scaleDist + d_knobWidth;
00434
00435 return QSize( d, d );
00436 }