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

qwt_dial.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 <math.h>
00011 #include <qpainter.h>
00012 #if QT_VERSION >= 0x040000
00013 #include <qpaintengine.h>
00014 #include <qbitmap.h>
00015 #include <qpalette.h>
00016 #endif
00017 #include <qpixmap.h>
00018 #include <qevent.h>
00019 #include "qwt_math.h"
00020 #include "qwt_scale_engine.h"
00021 #include "qwt_scale_map.h"
00022 #include "qwt_paint_buffer.h"
00023 #include "qwt_painter.h"
00024 #include "qwt_dial_needle.h"
00025 #include "qwt_dial.h"
00026 
00027 #if QT_VERSION >= 0x040000
00028 static void setAntialiasing(QPainter *painter, bool on)
00029 {
00030     QPaintEngine *engine = painter->paintEngine();
00031     if ( engine && engine->hasFeature(QPaintEngine::Antialiasing) )
00032         painter->setRenderHint(QPainter::Antialiasing, on);
00033 }
00034 #else
00035 static void setAntialiasing(QPainter *, bool)
00036 {
00037 }
00038 #endif
00039 
00040 class QwtDial::PrivateData
00041 {
00042 public:
00043     PrivateData():
00044         visibleBackground(true),
00045         frameShadow(Sunken),
00046         lineWidth(0),
00047         mode(RotateNeedle),
00048         origin(90.0),
00049         minScaleArc(0.0),
00050         maxScaleArc(0.0),
00051         scaleDraw(0),
00052         maxMajIntv(36),
00053         maxMinIntv(10),
00054         scaleStep(0.0),
00055         needle(0)
00056     {
00057     }
00058 
00059     ~PrivateData()
00060     {
00061         delete scaleDraw;
00062         delete needle;
00063     }
00064     bool visibleBackground;
00065     Shadow frameShadow;
00066     int lineWidth;
00067 
00068     QwtDial::Mode mode;
00069 
00070     double origin;
00071     double minScaleArc;
00072     double maxScaleArc;
00073 
00074     QwtDialScaleDraw *scaleDraw;
00075     int maxMajIntv;
00076     int maxMinIntv;
00077     double scaleStep;
00078 
00079     QwtDialNeedle *needle;
00080 
00081     static double previousDir;
00082 };
00083 
00084 double QwtDial::PrivateData::previousDir = -1.0;
00085 
00091 QwtDialScaleDraw::QwtDialScaleDraw(QwtDial *parent):
00092     d_parent(parent),
00093     d_penWidth(1)
00094 {
00095 }
00096 
00104 void QwtDialScaleDraw::setPenWidth(uint penWidth)
00105 {
00106     d_penWidth = penWidth;
00107 }
00108 
00113 uint QwtDialScaleDraw::penWidth() const
00114 {
00115     return d_penWidth;
00116 }
00117 
00125 QwtText QwtDialScaleDraw::label(double value) const
00126 {
00127     if ( d_parent == NULL )
00128         return QwtRoundScaleDraw::label(value);
00129 
00130     return d_parent->scaleLabel(value);
00131 }
00132 
00143 QwtDial::QwtDial(QWidget* parent):
00144     QwtAbstractSlider(Qt::Horizontal, parent)
00145 {
00146     d_data = new PrivateData;
00147 
00148 #if QT_VERSION < 0x040000
00149     setWFlags(Qt::WNoAutoErase);
00150 #endif 
00151 
00152 #if QT_VERSION >= 0x040000
00153     using namespace Qt;
00154 #endif
00155     setFocusPolicy(TabFocus);
00156 
00157     QPalette p = palette();
00158     for ( int i = 0; i < QPalette::NColorGroups; i++ )
00159     {
00160         const QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
00161 
00162         // Base: background color of the circle inside the frame.
00163         // Foreground: background color of the circle inside the scale
00164 
00165 #if QT_VERSION < 0x040000
00166         p.setColor(cg, QColorGroup::Foreground, 
00167             p.color(cg, QColorGroup::Base));
00168 #else
00169         p.setColor(cg, QPalette::Foreground, 
00170             p.color(cg, QPalette::Base));
00171 #endif
00172     }
00173     setPalette(p);
00174 
00175     d_data->scaleDraw = new QwtDialScaleDraw(this);
00176     d_data->scaleDraw->setRadius(0);
00177 
00178     setScaleArc(0.0, 360.0); // scale as a full circle
00179     setRange(0.0, 360.0, 1.0, 10); // degrees as deafult
00180 }
00181 
00183 QwtDial::~QwtDial() 
00184 {
00185     delete d_data;
00186 }
00187 
00196 void QwtDial::showBackground(bool show)
00197 {
00198     if ( d_data->visibleBackground != show )
00199     {
00200         d_data->visibleBackground = show;
00201         updateMask();
00202     }
00203 }
00204 
00210 bool QwtDial::hasVisibleBackground() const 
00211 { 
00212     return d_data->visibleBackground; 
00213 }
00214 
00220 void QwtDial::setFrameShadow(Shadow shadow)
00221 {
00222     if ( shadow != d_data->frameShadow )
00223     {
00224         d_data->frameShadow = shadow;
00225         if ( lineWidth() > 0 )
00226             update();
00227     }
00228 }
00229 
00235 QwtDial::Shadow QwtDial::frameShadow() const 
00236 { 
00237     return d_data->frameShadow; 
00238 }
00239 
00246 void QwtDial::setLineWidth(int lineWidth)
00247 {
00248     if ( lineWidth < 0 )
00249         lineWidth = 0;
00250 
00251     if ( d_data->lineWidth != lineWidth )
00252     {
00253         d_data->lineWidth = lineWidth;
00254         update();
00255     }
00256 }
00257 
00263 int QwtDial::lineWidth() const 
00264 { 
00265     return d_data->lineWidth; 
00266 }
00267 
00272 QRect QwtDial::contentsRect() const
00273 {
00274     const int lw = lineWidth();
00275 
00276     QRect r = boundingRect();
00277     if ( lw > 0 )
00278     {
00279         r.setRect(r.x() + lw, r.y() + lw, 
00280             r.width() - 2 * lw, r.height() - 2 * lw);
00281     }
00282     return r;
00283 }
00284 
00289 QRect QwtDial::boundingRect() const
00290 {
00291     const int radius = qwtMin(width(), height()) / 2;
00292 
00293     QRect r(0, 0, 2 * radius, 2 * radius);
00294     r.moveCenter(rect().center());
00295     return r;
00296 }
00297 
00302 QRect QwtDial::scaleContentsRect() const
00303 {
00304 #if QT_VERSION < 0x040000
00305     const QPen scalePen(colorGroup().text(), 0, Qt::NoPen);
00306 #else
00307     const QPen scalePen(palette().text(), 0, Qt::NoPen);
00308 #endif
00309 
00310     int scaleDist = 0;
00311     if ( d_data->scaleDraw )
00312     {
00313         scaleDist = d_data->scaleDraw->extent(scalePen, font());
00314         scaleDist++; // margin
00315     }
00316 
00317     const QRect rect = contentsRect();
00318     return QRect(rect.x() + scaleDist, rect.y() + scaleDist,
00319         rect.width() - 2 * scaleDist, rect.height() - 2 * scaleDist);
00320 }
00321 
00337 void QwtDial::setMode(Mode mode)
00338 {   
00339     if ( mode != d_data->mode )
00340     {
00341         d_data->mode = mode;
00342         update(); 
00343     }
00344 }       
00345 
00360 QwtDial::Mode QwtDial::mode() const
00361 {
00362     return d_data->mode;
00363 }
00364 
00375 void QwtDial::setWrapping(bool wrapping)
00376 {
00377     setPeriodic(wrapping);
00378 } 
00379 
00388 bool QwtDial::wrapping() const
00389 {
00390     return periodic();
00391 }
00392 
00394 void QwtDial::resizeEvent(QResizeEvent *e)
00395 {
00396     QWidget::resizeEvent(e);
00397 
00398     if ( !hasVisibleBackground() )
00399         updateMask();
00400 }
00401 
00403 void QwtDial::paintEvent(QPaintEvent *e)
00404 {
00405     const QRect &ur = e->rect();
00406     if ( ur.isValid() )
00407     {
00408 #if QT_VERSION < 0x040000
00409         QwtPaintBuffer paintBuffer(this, ur);
00410         QPainter &painter = *paintBuffer.painter();
00411 #else
00412         QPainter painter(this);
00413 #endif
00414 
00415         setAntialiasing(&painter, true);
00416 
00417         painter.save();
00418         drawContents(&painter);
00419         painter.restore();
00420 
00421         painter.save();
00422         drawFrame(&painter);
00423         painter.restore();
00424 
00425         if ( hasFocus() )
00426             drawFocusIndicator(&painter);
00427     }
00428 }
00429 
00435 void QwtDial::drawFocusIndicator(QPainter *painter) const
00436 {
00437     if ( !isReadOnly() )
00438     {
00439         QRect focusRect = contentsRect();
00440 
00441         const int margin = 2;
00442         focusRect.setRect( 
00443             focusRect.x() + margin,
00444             focusRect.y() + margin,
00445             focusRect.width() - 2 * margin,
00446             focusRect.height() - 2 * margin);
00447 
00448 #if QT_VERSION < 0x040000
00449         QColor color = colorGroup().color(QColorGroup::Base);
00450 #else
00451         QColor color = palette().color(QPalette::Base);
00452 #endif
00453         if (color.isValid())
00454         {
00455             const QColor gray(Qt::gray);
00456 
00457             int h, s, v;
00458 #if QT_VERSION < 0x040000
00459             color.hsv(&h, &s, &v);
00460 #else
00461             color.getHsv(&h, &s, &v);
00462 #endif
00463             color = (v > 128) ? gray.dark(120) : gray.light(120);
00464         }
00465         else
00466             color = Qt::darkGray;
00467 
00468         painter->save();
00469         painter->setBrush(Qt::NoBrush);
00470         painter->setPen(QPen(color, 0, Qt::DotLine));
00471         painter->drawEllipse(focusRect);
00472         painter->restore();
00473     }
00474 }
00475 
00482 void QwtDial::drawFrame(QPainter *painter)
00483 {
00484     const int lw = lineWidth();
00485     const int off = (lw + 1) % 2;
00486 
00487     QRect r = boundingRect();
00488     r.setRect(r.x() + lw / 2 - off, r.y() + lw / 2 - off,
00489         r.width() - lw + off + 1, r.height() - lw + off + 1);
00490 #if QT_VERSION >= 0x040000
00491 #ifdef __GNUC__
00492 #warning QwtPainter::drawRoundFrame 
00493 #endif
00494     r.setX(r.x() + 1);
00495     r.setY(r.y() + 1);
00496     r.setWidth(r.width() - 2);
00497     r.setHeight(r.height() - 2);
00498 #endif
00499 
00500     if ( lw > 0 )
00501     {
00502         switch(d_data->frameShadow)
00503         {
00504             case QwtDial::Raised:
00505 #if QT_VERSION < 0x040000
00506                 QwtPainter::drawRoundFrame(painter, r, 
00507                     lw, colorGroup(), false);
00508 #else
00509                 QwtPainter::drawRoundFrame(painter, r, 
00510                     lw, palette(), false);
00511 #endif
00512                 break;
00513             case QwtDial::Sunken:
00514 #if QT_VERSION < 0x040000
00515                 QwtPainter::drawRoundFrame(painter, r, 
00516                     lw, colorGroup(), true);
00517 #else
00518                 QwtPainter::drawRoundFrame(painter, r, 
00519                     lw, palette(), true);
00520 #endif
00521                 break;
00522             default: // Plain
00523             {
00524                 painter->save();
00525                 painter->setPen(QPen(Qt::black, lw));
00526                 painter->setBrush(Qt::NoBrush);
00527                 painter->drawEllipse(r);
00528                 painter->restore();
00529             }
00530         }
00531     }
00532 }
00533 
00545 void QwtDial::drawContents(QPainter *painter) const
00546 {
00547 #if QT_VERSION < 0x040000
00548     if ( backgroundMode() == Qt::NoBackground || 
00549         colorGroup().brush(QColorGroup::Base) != 
00550             colorGroup().brush(QColorGroup::Background) )
00551 #else
00552     if ( testAttribute(Qt::WA_NoSystemBackground) ||
00553         palette().brush(QPalette::Base) != 
00554             palette().brush(QPalette::Background) )
00555 #endif
00556     {
00557 
00558         const QRect br = boundingRect();
00559 
00560         painter->save();
00561         painter->setPen(Qt::NoPen);
00562 
00563 #if QT_VERSION < 0x040000
00564         painter->setBrush(colorGroup().brush(QColorGroup::Base));
00565 #else
00566         painter->setBrush(palette().brush(QPalette::Base));
00567 #endif
00568 
00569         painter->drawEllipse(br);
00570         painter->restore();
00571     }
00572 
00573 
00574     const QRect insideScaleRect = scaleContentsRect();
00575 #if QT_VERSION < 0x040000
00576     if ( colorGroup().brush(QColorGroup::Foreground) !=
00577         colorGroup().brush(QColorGroup::Base) )
00578 #else
00579     if ( palette().brush(QPalette::Foreground) !=
00580         palette().brush(QPalette::Base) )
00581 #endif
00582     {
00583         painter->save();
00584         painter->setPen(Qt::NoPen);
00585 
00586 #if QT_VERSION < 0x040000
00587         painter->setBrush(colorGroup().brush(QColorGroup::Foreground));
00588 #else
00589         painter->setBrush(palette().brush(QPalette::Foreground));
00590 #endif
00591 
00592         painter->drawEllipse(insideScaleRect.x() - 1, insideScaleRect.y() - 1,
00593             insideScaleRect.width(), insideScaleRect.height() );
00594 
00595         painter->restore();
00596     }
00597 
00598     const QPoint center = insideScaleRect.center();
00599     const int radius = insideScaleRect.width() / 2;
00600 
00601     painter->save();
00602     drawScaleContents(painter, center, radius);
00603     painter->restore();
00604 
00605     double direction = d_data->origin;
00606 
00607     if (isValid())
00608     {
00609         direction = d_data->origin + d_data->minScaleArc;
00610         if ( maxValue() > minValue() && d_data->maxScaleArc > d_data->minScaleArc )
00611         {
00612             const double ratio = 
00613                 (value() - minValue()) / (maxValue() - minValue());
00614             direction += ratio * (d_data->maxScaleArc - d_data->minScaleArc);
00615         }
00616 
00617         if ( direction >= 360.0 )
00618             direction -= 360.0;
00619     }
00620 
00621     double origin = d_data->origin;
00622     if ( mode() == RotateScale )
00623     {
00624         origin -= direction - d_data->origin;
00625         direction = d_data->origin;
00626     }
00627 
00628     painter->save();
00629     drawScale(painter, center, radius, origin, d_data->minScaleArc, d_data->maxScaleArc);
00630     painter->restore();
00631 
00632     if ( isValid() )
00633     {
00634         QPalette::ColorGroup cg;
00635         if ( isEnabled() )
00636             cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
00637         else
00638             cg = QPalette::Disabled;
00639 
00640         painter->save();
00641         drawNeedle(painter, center, radius, direction, cg);
00642         painter->restore();
00643     }
00644 }
00645 
00658 void QwtDial::drawNeedle(QPainter *painter, const QPoint &center, 
00659     int radius, double direction, QPalette::ColorGroup cg) const
00660 {
00661     if ( d_data->needle )
00662     {
00663         direction = 360.0 - direction; // counter clockwise
00664         d_data->needle->draw(painter, center, radius, direction, cg);
00665     }
00666 }
00667 
00680 void QwtDial::drawScale(QPainter *painter, const QPoint &center,
00681     int radius, double origin, double minArc, double maxArc) const
00682 {
00683     if ( d_data->scaleDraw == NULL )
00684         return;
00685 
00686     origin -= 270.0; // hardcoded origin of QwtScaleDraw
00687 
00688     double angle = maxArc - minArc;
00689     if ( angle > 360.0 )
00690         angle = fmod(angle, 360.0);
00691 
00692     minArc += origin;
00693     if ( minArc < -360.0 )
00694         minArc = fmod(minArc, 360.0);
00695     
00696     maxArc = minArc + angle;
00697     if ( maxArc > 360.0 )
00698     {
00699         // QwtAbstractScaleDraw::setAngleRange accepts only values
00700         // in the range [-360.0..360.0]
00701         minArc -= 360.0;
00702         maxArc -= 360.0;
00703     }
00704     
00705     painter->setFont(font());
00706 
00707     d_data->scaleDraw->setAngleRange(minArc, maxArc);
00708     d_data->scaleDraw->setRadius(radius);
00709     d_data->scaleDraw->moveCenter(center);
00710 
00711 #if QT_VERSION < 0x040000
00712     QColorGroup cg = colorGroup();
00713 
00714     const QColor textColor = cg.color(QColorGroup::Text);
00715     cg.setColor(QColorGroup::Foreground, textColor);
00716     painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth()));
00717     
00718     d_data->scaleDraw->draw(painter, cg);
00719 #else
00720     QPalette pal = palette();
00721 
00722     const QColor textColor = pal.color(QPalette::Text);
00723     pal.setColor(QPalette::Foreground, textColor); //ticks, backbone
00724     
00725     painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth()));
00726 
00727     d_data->scaleDraw->draw(painter, pal);
00728 #endif
00729 }
00730 
00731 void QwtDial::drawScaleContents(QPainter *, 
00732     const QPoint &, int) const
00733 {
00734     // empty default implementation
00735 }
00736 
00747 void QwtDial::setNeedle(QwtDialNeedle *needle)
00748 {
00749     if ( needle != d_data->needle )
00750     {
00751         if ( d_data->needle )
00752             delete d_data->needle;
00753 
00754         d_data->needle = needle;
00755         update();
00756     }
00757 }
00758 
00763 const QwtDialNeedle *QwtDial::needle() const 
00764 { 
00765     return d_data->needle; 
00766 }
00767 
00772 QwtDialNeedle *QwtDial::needle() 
00773 { 
00774     return d_data->needle; 
00775 }
00776 
00778 void QwtDial::rangeChange()
00779 {
00780     updateScale();
00781 }
00782 
00787 void QwtDial::updateScale()
00788 {
00789     if ( d_data->scaleDraw )
00790     {
00791         QwtLinearScaleEngine scaleEngine;
00792 
00793         const QwtScaleDiv scaleDiv = scaleEngine.divideScale(
00794             minValue(), maxValue(), 
00795             d_data->maxMajIntv, d_data->maxMinIntv, d_data->scaleStep);
00796 
00797         d_data->scaleDraw->setTransformation(scaleEngine.transformation());
00798         d_data->scaleDraw->setScaleDiv(scaleDiv);
00799     }
00800 }
00801 
00803 QwtDialScaleDraw *QwtDial::scaleDraw() 
00804 { 
00805     return d_data->scaleDraw; 
00806 }
00807 
00809 const QwtDialScaleDraw *QwtDial::scaleDraw() const 
00810 { 
00811     return d_data->scaleDraw; 
00812 }
00813 
00819 void QwtDial::setScaleDraw(QwtDialScaleDraw *scaleDraw)
00820 {
00821     if ( scaleDraw != d_data->scaleDraw )
00822     {
00823         if ( d_data->scaleDraw )
00824             delete d_data->scaleDraw;
00825     
00826         d_data->scaleDraw = scaleDraw;
00827         updateScale();
00828         update();
00829     }
00830 }
00831 
00836 void QwtDial::setScale(int maxMajIntv, int maxMinIntv, double step)
00837 {
00838     d_data->maxMajIntv = maxMajIntv;
00839     d_data->maxMinIntv = maxMinIntv;
00840     d_data->scaleStep = step;
00841 
00842     updateScale();
00843 }
00844 
00859 void QwtDial::setScaleOptions(int options)
00860 {
00861     if ( options == 0 )
00862         setScaleDraw(NULL);
00863 
00864     QwtDialScaleDraw *sd = d_data->scaleDraw;
00865     if ( sd == NULL )
00866         return;
00867 
00868     sd->enableComponent(QwtAbstractScaleDraw::Backbone, 
00869         options & ScaleBackbone);
00870 
00871     sd->enableComponent(QwtAbstractScaleDraw::Ticks, 
00872         options & ScaleTicks);
00873     
00874     sd->enableComponent(QwtAbstractScaleDraw::Labels, 
00875         options & ScaleLabel);
00876 }
00877 
00879 void QwtDial::setScaleTicks(int minLen, int medLen, 
00880     int majLen, int penWidth)
00881 {
00882     QwtDialScaleDraw *sd = d_data->scaleDraw;
00883     if ( sd )
00884     {
00885         sd->setTickLength(QwtScaleDiv::MinorTick, minLen);
00886         sd->setTickLength(QwtScaleDiv::MediumTick, medLen);
00887         sd->setTickLength(QwtScaleDiv::MajorTick, majLen);
00888         sd->setPenWidth(penWidth);
00889     }
00890 }
00891 
00895 QwtText QwtDial::scaleLabel(double value) const
00896 {
00897 #if 1
00898     if ( value == -0 )
00899         value = 0;
00900 #endif
00901 
00902     return QString::number(value);
00903 }
00904 
00906 double QwtDial::minScaleArc() const 
00907 { 
00908     return d_data->minScaleArc; 
00909 }
00910 
00912 double QwtDial::maxScaleArc() const 
00913 { 
00914     return d_data->maxScaleArc; 
00915 }
00916 
00925 void QwtDial::setOrigin(double origin)
00926 {
00927     d_data->origin = origin;
00928     update();
00929 }
00930 
00937 double QwtDial::origin() const
00938 {
00939     return d_data->origin;
00940 }
00941 
00948 void QwtDial::setScaleArc(double minArc, double maxArc)
00949 {
00950     if ( minArc != 360.0 && minArc != -360.0 )
00951         minArc = fmod(minArc, 360.0);
00952     if ( maxArc != 360.0 && maxArc != -360.0 )
00953         maxArc = fmod(maxArc, 360.0);
00954 
00955     d_data->minScaleArc = qwtMin(minArc, maxArc);
00956     d_data->maxScaleArc = qwtMax(minArc, maxArc);
00957     if ( d_data->maxScaleArc - d_data->minScaleArc > 360.0 )
00958         d_data->maxScaleArc = d_data->minScaleArc + 360.0;
00959     
00960     update();
00961 }
00962 
00964 void QwtDial::valueChange()
00965 {
00966     update();
00967     QwtAbstractSlider::valueChange();
00968 }
00969 
00973 QSize QwtDial::sizeHint() const
00974 {
00975     int sh = 0;
00976     if ( d_data->scaleDraw )
00977         sh = d_data->scaleDraw->extent( QPen(), font() );
00978 
00979     const int d = 6 * sh + 2 * lineWidth();
00980     
00981     return QSize( d, d );
00982 }
00983 
00989 QSize QwtDial::minimumSizeHint() const
00990 {   
00991     int sh = 0;
00992     if ( d_data->scaleDraw )
00993         sh = d_data->scaleDraw->extent(QPen(), font() );
00994 
00995     const int d = 3 * sh + 2 * lineWidth();
00996     
00997     return QSize( d, d );
00998 }
00999 
01000 static double line2Radians(const QPoint &p1, const QPoint &p2)
01001 {
01002     const QPoint p = p2 - p1;
01003 
01004     double angle;
01005     if ( p.x() == 0 )
01006         angle = ( p.y() <= 0 ) ? M_PI_2 : 3 * M_PI_2;
01007     else
01008     {
01009         angle = atan(double(-p.y()) / double(p.x()));
01010         if ( p.x() < 0 )
01011             angle += M_PI;
01012         if ( angle < 0.0 )
01013             angle += 2 * M_PI;
01014     }
01015     return 360.0 - angle * 180.0 / M_PI;
01016 }
01017 
01024 double QwtDial::getValue(const QPoint &pos)
01025 {
01026     if ( d_data->maxScaleArc == d_data->minScaleArc || maxValue() == minValue() )
01027         return minValue();
01028 
01029     double dir = line2Radians(rect().center(), pos) - d_data->origin;
01030     if ( dir < 0.0 )
01031         dir += 360.0;
01032 
01033     if ( mode() == RotateScale )
01034         dir = 360.0 - dir;
01035 
01036     // The position might be in the area that is outside the scale arc.
01037     // We need the range of the scale if it was a complete circle.
01038 
01039     const double completeCircle = 360.0 / (d_data->maxScaleArc - d_data->minScaleArc) 
01040         * (maxValue() - minValue());
01041 
01042     double posValue = minValue() + completeCircle * dir / 360.0;
01043 
01044     if ( scrollMode() == ScrMouse )
01045     {
01046         if ( d_data->previousDir >= 0.0 ) // valid direction
01047         {
01048             // We have to find out whether the mouse is moving
01049             // clock or counter clockwise
01050 
01051             bool clockWise = false;
01052 
01053             const double angle = dir - d_data->previousDir;
01054             if ( (angle >= 0.0 && angle <= 180.0) || angle < -180.0 )
01055                 clockWise = true;
01056 
01057             if ( clockWise )
01058             {
01059                 if ( dir < d_data->previousDir && mouseOffset() > 0.0 )
01060                 {
01061                     // We passed 360 -> 0
01062                     setMouseOffset(mouseOffset() - completeCircle);
01063                 }
01064 
01065                 if ( wrapping() )
01066                 {
01067                     if ( posValue - mouseOffset() > maxValue() )
01068                     {
01069                         // We passed maxValue and the value will be set
01070                         // to minValue. We have to adjust the mouseOffset.
01071 
01072                         setMouseOffset(posValue - minValue());
01073                     }
01074                 }
01075                 else
01076                 {
01077                     if ( posValue - mouseOffset() > maxValue() ||
01078                         value() == maxValue() )
01079                     {
01080                         // We fix the value at maxValue by adjusting
01081                         // the mouse offset.
01082 
01083                         setMouseOffset(posValue - maxValue());
01084                     }
01085                 }
01086             }
01087             else
01088             {
01089                 if ( dir > d_data->previousDir && mouseOffset() < 0.0 )
01090                 {
01091                     // We passed 0 -> 360 
01092                     setMouseOffset(mouseOffset() + completeCircle);    
01093                 }
01094 
01095                 if ( wrapping() )
01096                 {
01097                     if ( posValue - mouseOffset() < minValue() )
01098                     {
01099                         // We passed minValue and the value will be set
01100                         // to maxValue. We have to adjust the mouseOffset.
01101 
01102                         setMouseOffset(posValue - maxValue());
01103                     }
01104                 }
01105                 else
01106                 {
01107                     if ( posValue - mouseOffset() < minValue() ||
01108                         value() == minValue() )
01109                     {
01110                         // We fix the value at minValue by adjusting
01111                         // the mouse offset.
01112 
01113                         setMouseOffset(posValue - minValue());
01114                     }
01115                 }
01116             }
01117         }
01118         d_data->previousDir = dir;
01119     }
01120 
01121     return posValue;
01122 }
01123 
01127 void QwtDial::getScrollMode(const QPoint &p, int &scrollMode, int &direction)
01128 {
01129     direction = 0;
01130     scrollMode = ScrNone;
01131 
01132     const QRegion region(contentsRect(), QRegion::Ellipse);
01133     if ( region.contains(p) && p != rect().center() )
01134     {
01135         scrollMode = ScrMouse;
01136         d_data->previousDir = -1.0;
01137     }
01138 }
01139 
01159 void QwtDial::keyPressEvent(QKeyEvent *e)
01160 {
01161     if ( isReadOnly() )
01162     {
01163         e->ignore();
01164         return;
01165     }
01166 
01167     if ( !isValid() )
01168         return;
01169 
01170     double previous = prevValue();
01171     switch ( e->key() )
01172     {
01173         case Qt::Key_Down:
01174         case Qt::Key_Left:
01175             QwtDoubleRange::incValue(-1);
01176             break;
01177 #if QT_VERSION < 0x040000
01178         case Qt::Key_Prior:
01179 #else
01180         case Qt::Key_PageUp:
01181 #endif
01182             QwtDoubleRange::incValue(-pageSize());
01183             break;
01184         case Qt::Key_Home:
01185             setValue(minValue());
01186             break;
01187 
01188         case Qt::Key_Up:
01189         case Qt::Key_Right:
01190             QwtDoubleRange::incValue(1);
01191             break;
01192 #if QT_VERSION < 0x040000
01193         case Qt::Key_Next:
01194 #else
01195         case Qt::Key_PageDown:
01196 #endif
01197             QwtDoubleRange::incValue(pageSize());
01198             break;
01199         case Qt::Key_End:
01200             setValue(maxValue());
01201             break;
01202         default:;
01203             e->ignore();
01204     }
01205 
01206     if (value() != previous)
01207         emit sliderMoved(value());
01208 }
01209 
01210 void QwtDial::updateMask()
01211 {
01212     if ( d_data->visibleBackground )
01213         clearMask();
01214     else
01215         setMask(QRegion(boundingRect(), QRegion::Ellipse));
01216 }

Generated on Mon Jan 30 22:16:25 2006 for Qwt User's Guide by  doxygen 1.4.4