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 <qbitmap.h>
00014 #include <qpalette.h>
00015 #endif
00016 #include <qpixmap.h>
00017 #include <qevent.h>
00018 #include "qwt_math.h"
00019 #include "qwt_scale_engine.h"
00020 #include "qwt_scale_map.h"
00021 #include "qwt_paint_buffer.h"
00022 #include "qwt_painter.h"
00023 #include "qwt_dial_needle.h"
00024 #include "qwt_dial.h"
00025 
00026 class QwtDial::PrivateData
00027 {
00028 public:
00029     PrivateData():
00030         visibleBackground(true),
00031         frameShadow(Sunken),
00032         lineWidth(0),
00033         mode(RotateNeedle),
00034         origin(90.0),
00035         minScaleArc(0.0),
00036         maxScaleArc(0.0),
00037         scaleDraw(0),
00038         maxMajIntv(36),
00039         maxMinIntv(10),
00040         scaleStep(0.0),
00041         needle(0)
00042     {
00043     }
00044 
00045     ~PrivateData()
00046     {
00047         delete scaleDraw;
00048         delete needle;
00049     }
00050     bool visibleBackground;
00051     Shadow frameShadow;
00052     int lineWidth;
00053 
00054     QwtDial::Mode mode;
00055 
00056     double origin;
00057     double minScaleArc;
00058     double maxScaleArc;
00059 
00060     QwtDialScaleDraw *scaleDraw;
00061     int maxMajIntv;
00062     int maxMinIntv;
00063     double scaleStep;
00064 
00065     QwtDialNeedle *needle;
00066 
00067     static double previousDir;
00068 };
00069 
00070 double QwtDial::PrivateData::previousDir = -1.0;
00071 
00077 QwtDialScaleDraw::QwtDialScaleDraw(QwtDial *parent):
00078     d_parent(parent),
00079     d_penWidth(1)
00080 {
00081 }
00082 
00090 void QwtDialScaleDraw::setPenWidth(uint penWidth)
00091 {
00092     d_penWidth = penWidth;
00093 }
00094 
00099 uint QwtDialScaleDraw::penWidth() const
00100 {
00101     return d_penWidth;
00102 }
00103 
00111 QwtText QwtDialScaleDraw::label(double value) const
00112 {
00113     if ( d_parent == NULL )
00114         return QwtRoundScaleDraw::label(value);
00115 
00116     return d_parent->scaleLabel(value);
00117 }
00118 
00129 QwtDial::QwtDial(QWidget* parent):
00130     QwtAbstractSlider(Qt::Horizontal, parent)
00131 {
00132     initDial();
00133 }
00134 
00135 #if QT_VERSION < 0x040000
00136 
00146 QwtDial::QwtDial(QWidget* parent, const char *name):
00147     QwtAbstractSlider(Qt::Horizontal, parent)
00148 {
00149     setName(name);
00150     initDial();
00151 }
00152 #endif
00153 
00154 void QwtDial::initDial()
00155 {
00156     d_data = new PrivateData;
00157 
00158 #if QT_VERSION < 0x040000
00159     setWFlags(Qt::WNoAutoErase);
00160 #endif 
00161 
00162 #if QT_VERSION >= 0x040000
00163     using namespace Qt;
00164 #endif
00165     setFocusPolicy(TabFocus);
00166 
00167     QPalette p = palette();
00168     for ( int i = 0; i < QPalette::NColorGroups; i++ )
00169     {
00170         const QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
00171 
00172         // Base: background color of the circle inside the frame.
00173         // Foreground: background color of the circle inside the scale
00174 
00175 #if QT_VERSION < 0x040000
00176         p.setColor(cg, QColorGroup::Foreground, 
00177             p.color(cg, QColorGroup::Base));
00178 #else
00179         p.setColor(cg, QPalette::Foreground, 
00180             p.color(cg, QPalette::Base));
00181 #endif
00182     }
00183     setPalette(p);
00184 
00185     d_data->scaleDraw = new QwtDialScaleDraw(this);
00186     d_data->scaleDraw->setRadius(0);
00187 
00188     setScaleArc(0.0, 360.0); // scale as a full circle
00189     setRange(0.0, 360.0, 1.0, 10); // degrees as deafult
00190 }
00191 
00193 QwtDial::~QwtDial() 
00194 {
00195     delete d_data;
00196 }
00197 
00206 void QwtDial::showBackground(bool show)
00207 {
00208     if ( d_data->visibleBackground != show )
00209     {
00210         d_data->visibleBackground = show;
00211         updateMask();
00212     }
00213 }
00214 
00220 bool QwtDial::hasVisibleBackground() const 
00221 { 
00222     return d_data->visibleBackground; 
00223 }
00224 
00230 void QwtDial::setFrameShadow(Shadow shadow)
00231 {
00232     if ( shadow != d_data->frameShadow )
00233     {
00234         d_data->frameShadow = shadow;
00235         if ( lineWidth() > 0 )
00236             update();
00237     }
00238 }
00239 
00244 QwtDial::Shadow QwtDial::frameShadow() const 
00245 { 
00246     return d_data->frameShadow; 
00247 }
00248 
00255 void QwtDial::setLineWidth(int lineWidth)
00256 {
00257     if ( lineWidth < 0 )
00258         lineWidth = 0;
00259 
00260     if ( d_data->lineWidth != lineWidth )
00261     {
00262         d_data->lineWidth = lineWidth;
00263         update();
00264     }
00265 }
00266 
00271 int QwtDial::lineWidth() const 
00272 { 
00273     return d_data->lineWidth; 
00274 }
00275 
00280 QRect QwtDial::contentsRect() const
00281 {
00282     const int lw = lineWidth();
00283 
00284     QRect r = boundingRect();
00285     if ( lw > 0 )
00286     {
00287         r.setRect(r.x() + lw, r.y() + lw, 
00288             r.width() - 2 * lw, r.height() - 2 * lw);
00289     }
00290     return r;
00291 }
00292 
00297 QRect QwtDial::boundingRect() const
00298 {
00299     const int radius = qwtMin(width(), height()) / 2;
00300 
00301     QRect r(0, 0, 2 * radius, 2 * radius);
00302     r.moveCenter(rect().center());
00303     return r;
00304 }
00305 
00310 QRect QwtDial::scaleContentsRect() const
00311 {
00312 #if QT_VERSION < 0x040000
00313     const QPen scalePen(colorGroup().text(), 0, Qt::NoPen);
00314 #else
00315     const QPen scalePen(palette().text(), 0, Qt::NoPen);
00316 #endif
00317 
00318     int scaleDist = 0;
00319     if ( d_data->scaleDraw )
00320     {
00321         scaleDist = d_data->scaleDraw->extent(scalePen, font());
00322         scaleDist++; // margin
00323     }
00324 
00325     const QRect rect = contentsRect();
00326     return QRect(rect.x() + scaleDist, rect.y() + scaleDist,
00327         rect.width() - 2 * scaleDist, rect.height() - 2 * scaleDist);
00328 }
00329 
00345 void QwtDial::setMode(Mode mode)
00346 {   
00347     if ( mode != d_data->mode )
00348     {
00349         d_data->mode = mode;
00350         update(); 
00351     }
00352 }       
00353 
00368 QwtDial::Mode QwtDial::mode() const
00369 {
00370     return d_data->mode;
00371 }
00372 
00383 void QwtDial::setWrapping(bool wrapping)
00384 {
00385     setPeriodic(wrapping);
00386 } 
00387 
00396 bool QwtDial::wrapping() const
00397 {
00398     return periodic();
00399 }
00400 
00405 void QwtDial::resizeEvent(QResizeEvent *e)
00406 {
00407     QWidget::resizeEvent(e);
00408 
00409     if ( !hasVisibleBackground() )
00410         updateMask();
00411 }
00412 
00417 void QwtDial::paintEvent(QPaintEvent *e)
00418 {
00419     const QRect &ur = e->rect();
00420     if ( ur.isValid() )
00421     {
00422 #if QT_VERSION < 0x040000
00423         QwtPaintBuffer paintBuffer(this, ur);
00424         QPainter &painter = *paintBuffer.painter();
00425 #else
00426         QPainter painter(this);
00427         painter.setRenderHint(QPainter::Antialiasing, true);
00428 #endif
00429 
00430         painter.save();
00431         drawContents(&painter);
00432         painter.restore();
00433 
00434         painter.save();
00435         drawFrame(&painter);
00436         painter.restore();
00437 
00438         if ( hasFocus() )
00439             drawFocusIndicator(&painter);
00440     }
00441 }
00442 
00448 void QwtDial::drawFocusIndicator(QPainter *painter) const
00449 {
00450     if ( !isReadOnly() )
00451     {
00452         QRect focusRect = contentsRect();
00453 
00454         const int margin = 2;
00455         focusRect.setRect( 
00456             focusRect.x() + margin,
00457             focusRect.y() + margin,
00458             focusRect.width() - 2 * margin,
00459             focusRect.height() - 2 * margin);
00460 
00461 #if QT_VERSION < 0x040000
00462         QColor color = colorGroup().color(QColorGroup::Base);
00463 #else
00464         QColor color = palette().color(QPalette::Base);
00465 #endif
00466         if (color.isValid())
00467         {
00468             const QColor gray(Qt::gray);
00469 
00470             int h, s, v;
00471 #if QT_VERSION < 0x040000
00472             color.hsv(&h, &s, &v);
00473 #else
00474             color.getHsv(&h, &s, &v);
00475 #endif
00476             color = (v > 128) ? gray.dark(120) : gray.light(120);
00477         }
00478         else
00479             color = Qt::darkGray;
00480 
00481         painter->save();
00482         painter->setBrush(Qt::NoBrush);
00483         painter->setPen(QPen(color, 0, Qt::DotLine));
00484         painter->drawEllipse(focusRect);
00485         painter->restore();
00486     }
00487 }
00488 
00495 void QwtDial::drawFrame(QPainter *painter)
00496 {
00497     const int lw = lineWidth();
00498     const int off = (lw + 1) % 2;
00499 
00500     QRect r = boundingRect();
00501     r.setRect(r.x() + lw / 2 - off, r.y() + lw / 2 - off,
00502         r.width() - lw + off + 1, r.height() - lw + off + 1);
00503 #if QT_VERSION >= 0x040000
00504 #ifdef __GNUC__
00505 #endif
00506     r.setX(r.x() + 1);
00507     r.setY(r.y() + 1);
00508     r.setWidth(r.width() - 2);
00509     r.setHeight(r.height() - 2);
00510 #endif
00511 
00512     if ( lw > 0 )
00513     {
00514         switch(d_data->frameShadow)
00515         {
00516             case QwtDial::Raised:
00517 #if QT_VERSION < 0x040000
00518                 QwtPainter::drawRoundFrame(painter, r, 
00519                     lw, colorGroup(), false);
00520 #else
00521                 QwtPainter::drawRoundFrame(painter, r, 
00522                     lw, palette(), false);
00523 #endif
00524                 break;
00525             case QwtDial::Sunken:
00526 #if QT_VERSION < 0x040000
00527                 QwtPainter::drawRoundFrame(painter, r, 
00528                     lw, colorGroup(), true);
00529 #else
00530                 QwtPainter::drawRoundFrame(painter, r, 
00531                     lw, palette(), true);
00532 #endif
00533                 break;
00534             default: // Plain
00535             {
00536                 painter->save();
00537                 painter->setPen(QPen(Qt::black, lw));
00538                 painter->setBrush(Qt::NoBrush);
00539                 painter->drawEllipse(r);
00540                 painter->restore();
00541             }
00542         }
00543     }
00544 }
00545 
00557 void QwtDial::drawContents(QPainter *painter) const
00558 {
00559 #if QT_VERSION < 0x040000
00560     if ( backgroundMode() == Qt::NoBackground || 
00561         colorGroup().brush(QColorGroup::Base) != 
00562             colorGroup().brush(QColorGroup::Background) )
00563 #else
00564     if ( testAttribute(Qt::WA_NoSystemBackground) ||
00565         palette().brush(QPalette::Base) != 
00566             palette().brush(QPalette::Background) )
00567 #endif
00568     {
00569 
00570         const QRect br = boundingRect();
00571 
00572         painter->save();
00573         painter->setPen(Qt::NoPen);
00574 
00575 #if QT_VERSION < 0x040000
00576         painter->setBrush(colorGroup().brush(QColorGroup::Base));
00577 #else
00578         painter->setBrush(palette().brush(QPalette::Base));
00579 #endif
00580 
00581         painter->drawEllipse(br);
00582         painter->restore();
00583     }
00584 
00585 
00586     const QRect insideScaleRect = scaleContentsRect();
00587 #if QT_VERSION < 0x040000
00588     if ( colorGroup().brush(QColorGroup::Foreground) !=
00589         colorGroup().brush(QColorGroup::Base) )
00590 #else
00591     if ( palette().brush(QPalette::Foreground) !=
00592         palette().brush(QPalette::Base) )
00593 #endif
00594     {
00595         painter->save();
00596         painter->setPen(Qt::NoPen);
00597 
00598 #if QT_VERSION < 0x040000
00599         painter->setBrush(colorGroup().brush(QColorGroup::Foreground));
00600 #else
00601         painter->setBrush(palette().brush(QPalette::Foreground));
00602 #endif
00603 
00604         painter->drawEllipse(insideScaleRect.x() - 1, insideScaleRect.y() - 1,
00605             insideScaleRect.width(), insideScaleRect.height() );
00606 
00607         painter->restore();
00608     }
00609 
00610     const QPoint center = insideScaleRect.center();
00611     const int radius = insideScaleRect.width() / 2;
00612 
00613     painter->save();
00614     drawScaleContents(painter, center, radius);
00615     painter->restore();
00616 
00617     double direction = d_data->origin;
00618 
00619     if (isValid())
00620     {
00621         direction = d_data->origin + d_data->minScaleArc;
00622         if ( maxValue() > minValue() && d_data->maxScaleArc > d_data->minScaleArc )
00623         {
00624             const double ratio = 
00625                 (value() - minValue()) / (maxValue() - minValue());
00626             direction += ratio * (d_data->maxScaleArc - d_data->minScaleArc);
00627         }
00628 
00629         if ( direction >= 360.0 )
00630             direction -= 360.0;
00631     }
00632 
00633     double origin = d_data->origin;
00634     if ( mode() == RotateScale )
00635     {
00636         origin -= direction - d_data->origin;
00637         direction = d_data->origin;
00638     }
00639 
00640     painter->save();
00641     drawScale(painter, center, radius, origin, d_data->minScaleArc, d_data->maxScaleArc);
00642     painter->restore();
00643 
00644     if ( isValid() )
00645     {
00646         QPalette::ColorGroup cg;
00647         if ( isEnabled() )
00648             cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
00649         else
00650             cg = QPalette::Disabled;
00651 
00652         painter->save();
00653         drawNeedle(painter, center, radius, direction, cg);
00654         painter->restore();
00655     }
00656 }
00657 
00667 void QwtDial::drawNeedle(QPainter *painter, const QPoint &center, 
00668     int radius, double direction, QPalette::ColorGroup cg) const
00669 {
00670     if ( d_data->needle )
00671     {
00672         direction = 360.0 - direction; // counter clockwise
00673         d_data->needle->draw(painter, center, radius, direction, cg);
00674     }
00675 }
00676 
00689 void QwtDial::drawScale(QPainter *painter, const QPoint &center,
00690     int radius, double origin, double minArc, double maxArc) const
00691 {
00692     if ( d_data->scaleDraw == NULL )
00693         return;
00694 
00695     origin -= 270.0; // hardcoded origin of QwtScaleDraw
00696 
00697     double angle = maxArc - minArc;
00698     if ( angle > 360.0 )
00699         angle = fmod(angle, 360.0);
00700 
00701     minArc += origin;
00702     if ( minArc < -360.0 )
00703         minArc = fmod(minArc, 360.0);
00704     
00705     maxArc = minArc + angle;
00706     if ( maxArc > 360.0 )
00707     {
00708         // QwtAbstractScaleDraw::setAngleRange accepts only values
00709         // in the range [-360.0..360.0]
00710         minArc -= 360.0;
00711         maxArc -= 360.0;
00712     }
00713     
00714     painter->setFont(font());
00715 
00716     d_data->scaleDraw->setAngleRange(minArc, maxArc);
00717     d_data->scaleDraw->setRadius(radius);
00718     d_data->scaleDraw->moveCenter(center);
00719 
00720 #if QT_VERSION < 0x040000
00721     QColorGroup cg = colorGroup();
00722 
00723     const QColor textColor = cg.color(QColorGroup::Text);
00724     cg.setColor(QColorGroup::Foreground, textColor);
00725     painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth()));
00726     
00727     d_data->scaleDraw->draw(painter, cg);
00728 #else
00729     QPalette pal = palette();
00730 
00731     const QColor textColor = pal.color(QPalette::Text);
00732     pal.setColor(QPalette::Foreground, textColor); //ticks, backbone
00733     
00734     painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth()));
00735 
00736     d_data->scaleDraw->draw(painter, pal);
00737 #endif
00738 }
00739 
00740 void QwtDial::drawScaleContents(QPainter *, 
00741     const QPoint &, int) const
00742 {
00743     // empty default implementation
00744 }
00745 
00756 void QwtDial::setNeedle(QwtDialNeedle *needle)
00757 {
00758     if ( needle != d_data->needle )
00759     {
00760         if ( d_data->needle )
00761             delete d_data->needle;
00762 
00763         d_data->needle = needle;
00764         update();
00765     }
00766 }
00767 
00772 const QwtDialNeedle *QwtDial::needle() const 
00773 { 
00774     return d_data->needle; 
00775 }
00776 
00781 QwtDialNeedle *QwtDial::needle() 
00782 { 
00783     return d_data->needle; 
00784 }
00785 
00787 void QwtDial::rangeChange()
00788 {
00789     updateScale();
00790 }
00791 
00796 void QwtDial::updateScale()
00797 {
00798     if ( d_data->scaleDraw )
00799     {
00800         QwtLinearScaleEngine scaleEngine;
00801 
00802         const QwtScaleDiv scaleDiv = scaleEngine.divideScale(
00803             minValue(), maxValue(), 
00804             d_data->maxMajIntv, d_data->maxMinIntv, d_data->scaleStep);
00805 
00806         d_data->scaleDraw->setTransformation(scaleEngine.transformation());
00807         d_data->scaleDraw->setScaleDiv(scaleDiv);
00808     }
00809 }
00810 
00812 QwtDialScaleDraw *QwtDial::scaleDraw() 
00813 { 
00814     return d_data->scaleDraw; 
00815 }
00816 
00818 const QwtDialScaleDraw *QwtDial::scaleDraw() const 
00819 { 
00820     return d_data->scaleDraw; 
00821 }
00822 
00829 void QwtDial::setScaleDraw(QwtDialScaleDraw *scaleDraw)
00830 {
00831     if ( scaleDraw != d_data->scaleDraw )
00832     {
00833         if ( d_data->scaleDraw )
00834             delete d_data->scaleDraw;
00835     
00836         d_data->scaleDraw = scaleDraw;
00837         updateScale();
00838         update();
00839     }
00840 }
00841 
00846 void QwtDial::setScale(int maxMajIntv, int maxMinIntv, double step)
00847 {
00848     d_data->maxMajIntv = maxMajIntv;
00849     d_data->maxMinIntv = maxMinIntv;
00850     d_data->scaleStep = step;
00851 
00852     updateScale();
00853 }
00854 
00869 void QwtDial::setScaleOptions(int options)
00870 {
00871     if ( options == 0 )
00872         setScaleDraw(NULL);
00873 
00874     QwtDialScaleDraw *sd = d_data->scaleDraw;
00875     if ( sd == NULL )
00876         return;
00877 
00878     sd->enableComponent(QwtAbstractScaleDraw::Backbone, 
00879         options & ScaleBackbone);
00880 
00881     sd->enableComponent(QwtAbstractScaleDraw::Ticks, 
00882         options & ScaleTicks);
00883     
00884     sd->enableComponent(QwtAbstractScaleDraw::Labels, 
00885         options & ScaleLabel);
00886 }
00887 
00889 void QwtDial::setScaleTicks(int minLen, int medLen, 
00890     int majLen, int penWidth)
00891 {
00892     QwtDialScaleDraw *sd = d_data->scaleDraw;
00893     if ( sd )
00894     {
00895         sd->setTickLength(QwtScaleDiv::MinorTick, minLen);
00896         sd->setTickLength(QwtScaleDiv::MediumTick, medLen);
00897         sd->setTickLength(QwtScaleDiv::MajorTick, majLen);
00898         sd->setPenWidth(penWidth);
00899     }
00900 }
00901 
00908 QwtText QwtDial::scaleLabel(double value) const
00909 {
00910 #if 1
00911     if ( value == -0 )
00912         value = 0;
00913 #endif
00914 
00915     return QString::number(value);
00916 }
00917 
00919 double QwtDial::minScaleArc() const 
00920 { 
00921     return d_data->minScaleArc; 
00922 }
00923 
00925 double QwtDial::maxScaleArc() const 
00926 { 
00927     return d_data->maxScaleArc; 
00928 }
00929 
00938 void QwtDial::setOrigin(double origin)
00939 {
00940     d_data->origin = origin;
00941     update();
00942 }
00943 
00950 double QwtDial::origin() const
00951 {
00952     return d_data->origin;
00953 }
00954 
00961 void QwtDial::setScaleArc(double minArc, double maxArc)
00962 {
00963     if ( minArc != 360.0 && minArc != -360.0 )
00964         minArc = fmod(minArc, 360.0);
00965     if ( maxArc != 360.0 && maxArc != -360.0 )
00966         maxArc = fmod(maxArc, 360.0);
00967 
00968     d_data->minScaleArc = qwtMin(minArc, maxArc);
00969     d_data->maxScaleArc = qwtMax(minArc, maxArc);
00970     if ( d_data->maxScaleArc - d_data->minScaleArc > 360.0 )
00971         d_data->maxScaleArc = d_data->minScaleArc + 360.0;
00972     
00973     update();
00974 }
00975 
00977 void QwtDial::valueChange()
00978 {
00979     update();
00980     QwtAbstractSlider::valueChange();
00981 }
00982 
00986 QSize QwtDial::sizeHint() const
00987 {
00988     int sh = 0;
00989     if ( d_data->scaleDraw )
00990         sh = d_data->scaleDraw->extent( QPen(), font() );
00991 
00992     const int d = 6 * sh + 2 * lineWidth();
00993     
00994     return QSize( d, d );
00995 }
00996 
01002 QSize QwtDial::minimumSizeHint() const
01003 {   
01004     int sh = 0;
01005     if ( d_data->scaleDraw )
01006         sh = d_data->scaleDraw->extent(QPen(), font() );
01007 
01008     const int d = 3 * sh + 2 * lineWidth();
01009     
01010     return QSize( d, d );
01011 }
01012 
01013 static double line2Radians(const QPoint &p1, const QPoint &p2)
01014 {
01015     const QPoint p = p2 - p1;
01016 
01017     double angle;
01018     if ( p.x() == 0 )
01019         angle = ( p.y() <= 0 ) ? M_PI_2 : 3 * M_PI_2;
01020     else
01021     {
01022         angle = atan(double(-p.y()) / double(p.x()));
01023         if ( p.x() < 0 )
01024             angle += M_PI;
01025         if ( angle < 0.0 )
01026             angle += 2 * M_PI;
01027     }
01028     return 360.0 - angle * 180.0 / M_PI;
01029 }
01030 
01037 double QwtDial::getValue(const QPoint &pos)
01038 {
01039     if ( d_data->maxScaleArc == d_data->minScaleArc || maxValue() == minValue() )
01040         return minValue();
01041 
01042     double dir = line2Radians(rect().center(), pos) - d_data->origin;
01043     if ( dir < 0.0 )
01044         dir += 360.0;
01045 
01046     if ( mode() == RotateScale )
01047         dir = 360.0 - dir;
01048 
01049     // The position might be in the area that is outside the scale arc.
01050     // We need the range of the scale if it was a complete circle.
01051 
01052     const double completeCircle = 360.0 / (d_data->maxScaleArc - d_data->minScaleArc) 
01053         * (maxValue() - minValue());
01054 
01055     double posValue = minValue() + completeCircle * dir / 360.0;
01056 
01057     if ( scrollMode() == ScrMouse )
01058     {
01059         if ( d_data->previousDir >= 0.0 ) // valid direction
01060         {
01061             // We have to find out whether the mouse is moving
01062             // clock or counter clockwise
01063 
01064             bool clockWise = false;
01065 
01066             const double angle = dir - d_data->previousDir;
01067             if ( (angle >= 0.0 && angle <= 180.0) || angle < -180.0 )
01068                 clockWise = true;
01069 
01070             if ( clockWise )
01071             {
01072                 if ( dir < d_data->previousDir && mouseOffset() > 0.0 )
01073                 {
01074                     // We passed 360 -> 0
01075                     setMouseOffset(mouseOffset() - completeCircle);
01076                 }
01077 
01078                 if ( wrapping() )
01079                 {
01080                     if ( posValue - mouseOffset() > maxValue() )
01081                     {
01082                         // We passed maxValue and the value will be set
01083                         // to minValue. We have to adjust the mouseOffset.
01084 
01085                         setMouseOffset(posValue - minValue());
01086                     }
01087                 }
01088                 else
01089                 {
01090                     if ( posValue - mouseOffset() > maxValue() ||
01091                         value() == maxValue() )
01092                     {
01093                         // We fix the value at maxValue by adjusting
01094                         // the mouse offset.
01095 
01096                         setMouseOffset(posValue - maxValue());
01097                     }
01098                 }
01099             }
01100             else
01101             {
01102                 if ( dir > d_data->previousDir && mouseOffset() < 0.0 )
01103                 {
01104                     // We passed 0 -> 360 
01105                     setMouseOffset(mouseOffset() + completeCircle);    
01106                 }
01107 
01108                 if ( wrapping() )
01109                 {
01110                     if ( posValue - mouseOffset() < minValue() )
01111                     {
01112                         // We passed minValue and the value will be set
01113                         // to maxValue. We have to adjust the mouseOffset.
01114 
01115                         setMouseOffset(posValue - maxValue());
01116                     }
01117                 }
01118                 else
01119                 {
01120                     if ( posValue - mouseOffset() < minValue() ||
01121                         value() == minValue() )
01122                     {
01123                         // We fix the value at minValue by adjusting
01124                         // the mouse offset.
01125 
01126                         setMouseOffset(posValue - minValue());
01127                     }
01128                 }
01129             }
01130         }
01131         d_data->previousDir = dir;
01132     }
01133 
01134     return posValue;
01135 }
01136 
01140 void QwtDial::getScrollMode(const QPoint &p, int &scrollMode, int &direction)
01141 {
01142     direction = 0;
01143     scrollMode = ScrNone;
01144 
01145     const QRegion region(contentsRect(), QRegion::Ellipse);
01146     if ( region.contains(p) && p != rect().center() )
01147     {
01148         scrollMode = ScrMouse;
01149         d_data->previousDir = -1.0;
01150     }
01151 }
01152 
01172 void QwtDial::keyPressEvent(QKeyEvent *e)
01173 {
01174     if ( isReadOnly() )
01175     {
01176         e->ignore();
01177         return;
01178     }
01179 
01180     if ( !isValid() )
01181         return;
01182 
01183     double previous = prevValue();
01184     switch ( e->key() )
01185     {
01186         case Qt::Key_Down:
01187         case Qt::Key_Left:
01188             QwtDoubleRange::incValue(-1);
01189             break;
01190 #if QT_VERSION < 0x040000
01191         case Qt::Key_Prior:
01192 #else
01193         case Qt::Key_PageUp:
01194 #endif
01195             QwtDoubleRange::incValue(-pageSize());
01196             break;
01197         case Qt::Key_Home:
01198             setValue(minValue());
01199             break;
01200 
01201         case Qt::Key_Up:
01202         case Qt::Key_Right:
01203             QwtDoubleRange::incValue(1);
01204             break;
01205 #if QT_VERSION < 0x040000
01206         case Qt::Key_Next:
01207 #else
01208         case Qt::Key_PageDown:
01209 #endif
01210             QwtDoubleRange::incValue(pageSize());
01211             break;
01212         case Qt::Key_End:
01213             setValue(maxValue());
01214             break;
01215         default:;
01216             e->ignore();
01217     }
01218 
01219     if (value() != previous)
01220         emit sliderMoved(value());
01221 }
01222 
01231 void QwtDial::updateMask()
01232 {
01233     if ( d_data->visibleBackground )
01234         clearMask();
01235     else
01236         setMask(QRegion(boundingRect(), QRegion::Ellipse));
01237 }

Generated on Sun Mar 22 16:54:06 2009 for Qwt User's Guide by  doxygen 1.5.0