Main Page | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members | Related Pages

qwt_knob.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
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     // draw button face
00105     //
00106     p->setBrush(colorGroup().brush(QColorGroup::Button));
00107     p->drawEllipse(aRect);
00108 
00109     //
00110     // draw button shades
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     // draw marker
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)) // point is inside the knob
00187     {
00188         scrollMode = ScrMouse;
00189         direction = 0;
00190     }
00191     else                                // point lies outside
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 //  the current rect and fonts.
00231 //  \param update_geometry  notify the layout system and call update
00232 //         to redraw the scale
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 ) ) // event from valueChange()
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     // calculate the angle corresponding to the value
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     // Add the scale radial thickness to the knobWidth
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 }

Generated on Fri Nov 7 14:11:45 2003 for Qwt Developer's Guide by doxygen 1.3.2