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

# qwt_knob.cpp

    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 <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     // draw button face
    00108     //
    00109     p->setBrush(colorGroup().brush(QColorGroup::Button));
    00110     p->drawEllipse(aRect);
    00111
    00112     //
    00113     // draw button shades
    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     // draw marker
    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)) // point is inside the knob
    00191     {
    00192         scrollMode = ScrMouse;
    00193         direction = 0;
    00194     }
    00195     else                                // point lies outside
    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 //  the current rect and fonts.
    00235 //  \param update_geometry  notify the layout system and call update
    00236 //         to redraw the scale
    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 ) ) // event from valueChange()
    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     // calculate the angle corresponding to the value
    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     // Add the scale radial thickness to the knobWidth
    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 // Local Variables:
    00434 // mode: C++
    00435 // c-file-style: "stroustrup"
    00436 // indent-tabs-mode: nil
    00437 // End: