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     initDial();
00147 }
00148 
00149 #if QT_VERSION < 0x040000
00150 
00160 QwtDial::QwtDial(QWidget* parent, const char *name):
00161     QwtAbstractSlider(Qt::Horizontal, parent)
00162 {
00163     setName(name);
00164     initDial();
00165 }
00166 #endif
00167 
00168 void QwtDial::initDial()
00169 {
00170     d_data = new PrivateData;
00171 
00172 #if QT_VERSION < 0x040000
00173     setWFlags(Qt::WNoAutoErase);
00174 #endif 
00175 
00176 #if QT_VERSION >= 0x040000
00177     using namespace Qt;
00178 #endif
00179     setFocusPolicy(TabFocus);
00180 
00181     QPalette p = palette();
00182     for ( int i = 0; i < QPalette::NColorGroups; i++ )
00183     {
00184         const QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
00185 
00186         // Base: background color of the circle inside the frame.
00187         // Foreground: background color of the circle inside the scale
00188 
00189 #if QT_VERSION < 0x040000
00190         p.setColor(cg, QColorGroup::Foreground, 
00191             p.color(cg, QColorGroup::Base));
00192 #else
00193         p.setColor(cg, QPalette::Foreground, 
00194             p.color(cg, QPalette::Base));
00195 #endif
00196     }
00197     setPalette(p);
00198 
00199     d_data->scaleDraw = new QwtDialScaleDraw(this);
00200     d_data->scaleDraw->setRadius(0);
00201 
00202     setScaleArc(0.0, 360.0); // scale as a full circle
00203     setRange(0.0, 360.0, 1.0, 10); // degrees as deafult
00204 }
00205 
00207 QwtDial::~QwtDial() 
00208 {
00209     delete d_data;
00210 }
00211 
00220 void QwtDial::showBackground(bool show)
00221 {
00222     if ( d_data->visibleBackground != show )
00223     {
00224         d_data->visibleBackground = show;
00225         updateMask();
00226     }
00227 }
00228 
00234 bool QwtDial::hasVisibleBackground() const 
00235 { 
00236     return d_data->visibleBackground; 
00237 }
00238 
00244 void QwtDial::setFrameShadow(Shadow shadow)
00245 {
00246     if ( shadow != d_data->frameShadow )
00247     {
00248         d_data->frameShadow = shadow;
00249         if ( lineWidth() > 0 )
00250             update();
00251     }
00252 }
00253 
00258 QwtDial::Shadow QwtDial::frameShadow() const 
00259 { 
00260     return d_data->frameShadow; 
00261 }
00262 
00269 void QwtDial::setLineWidth(int lineWidth)
00270 {
00271     if ( lineWidth < 0 )
00272         lineWidth = 0;
00273 
00274     if ( d_data->lineWidth != lineWidth )
00275     {
00276         d_data->lineWidth = lineWidth;
00277         update();
00278     }
00279 }
00280 
00285 int QwtDial::lineWidth() const 
00286 { 
00287     return d_data->lineWidth; 
00288 }
00289 
00294 QRect QwtDial::contentsRect() const
00295 {
00296     const int lw = lineWidth();
00297 
00298     QRect r = boundingRect();
00299     if ( lw > 0 )
00300     {
00301         r.setRect(r.x() + lw, r.y() + lw, 
00302             r.width() - 2 * lw, r.height() - 2 * lw);
00303     }
00304     return r;
00305 }
00306 
00311 QRect QwtDial::boundingRect() const
00312 {
00313     const int radius = qwtMin(width(), height()) / 2;
00314 
00315     QRect r(0, 0, 2 * radius, 2 * radius);
00316     r.moveCenter(rect().center());
00317     return r;
00318 }
00319 
00324 QRect QwtDial::scaleContentsRect() const
00325 {
00326 #if QT_VERSION < 0x040000
00327     const QPen scalePen(colorGroup().text(), 0, Qt::NoPen);
00328 #else
00329     const QPen scalePen(palette().text(), 0, Qt::NoPen);
00330 #endif
00331 
00332     int scaleDist = 0;
00333     if ( d_data->scaleDraw )
00334     {
00335         scaleDist = d_data->scaleDraw->extent(scalePen, font());
00336         scaleDist++; // margin
00337     }
00338 
00339     const QRect rect = contentsRect();
00340     return QRect(rect.x() + scaleDist, rect.y() + scaleDist,
00341         rect.width() - 2 * scaleDist, rect.height() - 2 * scaleDist);
00342 }
00343 
00359 void QwtDial::setMode(Mode mode)
00360 {   
00361     if ( mode != d_data->mode )
00362     {
00363         d_data->mode = mode;
00364         update(); 
00365     }
00366 }       
00367 
00382 QwtDial::Mode QwtDial::mode() const
00383 {
00384     return d_data->mode;
00385 }
00386 
00397 void QwtDial::setWrapping(bool wrapping)
00398 {
00399     setPeriodic(wrapping);
00400 } 
00401 
00410 bool QwtDial::wrapping() const
00411 {
00412     return periodic();
00413 }
00414 
00419 void QwtDial::resizeEvent(QResizeEvent *e)
00420 {
00421     QWidget::resizeEvent(e);
00422 
00423     if ( !hasVisibleBackground() )
00424         updateMask();
00425 }
00426 
00431 void QwtDial::paintEvent(QPaintEvent *e)
00432 {
00433     const QRect &ur = e->rect();
00434     if ( ur.isValid() )
00435     {
00436 #if QT_VERSION < 0x040000
00437         QwtPaintBuffer paintBuffer(this, ur);
00438         QPainter &painter = *paintBuffer.painter();
00439 #else
00440         QPainter painter(this);
00441 #endif
00442 
00443         setAntialiasing(&painter, true);
00444 
00445         painter.save();
00446         drawContents(&painter);
00447         painter.restore();
00448 
00449         painter.save();
00450         drawFrame(&painter);
00451         painter.restore();
00452 
00453         if ( hasFocus() )
00454             drawFocusIndicator(&painter);
00455     }
00456 }
00457 
00463 void QwtDial::drawFocusIndicator(QPainter *painter) const
00464 {
00465     if ( !isReadOnly() )
00466     {
00467         QRect focusRect = contentsRect();
00468 
00469         const int margin = 2;
00470         focusRect.setRect( 
00471             focusRect.x() + margin,
00472             focusRect.y() + margin,
00473             focusRect.width() - 2 * margin,
00474             focusRect.height() - 2 * margin);
00475 
00476 #if QT_VERSION < 0x040000
00477         QColor color = colorGroup().color(QColorGroup::Base);
00478 #else
00479         QColor color = palette().color(QPalette::Base);
00480 #endif
00481         if (color.isValid())
00482         {
00483             const QColor gray(Qt::gray);
00484 
00485             int h, s, v;
00486 #if QT_VERSION < 0x040000
00487             color.hsv(&h, &s, &v);
00488 #else
00489             color.getHsv(&h, &s, &v);
00490 #endif
00491             color = (v > 128) ? gray.dark(120) : gray.light(120);
00492         }
00493         else
00494             color = Qt::darkGray;
00495 
00496         painter->save();
00497         painter->setBrush(Qt::NoBrush);
00498         painter->setPen(QPen(color, 0, Qt::DotLine));
00499         painter->drawEllipse(focusRect);
00500         painter->restore();
00501     }
00502 }
00503 
00510 void QwtDial::drawFrame(QPainter *painter)
00511 {
00512     const int lw = lineWidth();
00513     const int off = (lw + 1) % 2;
00514 
00515     QRect r = boundingRect();
00516     r.setRect(r.x() + lw / 2 - off, r.y() + lw / 2 - off,
00517         r.width() - lw + off + 1, r.height() - lw + off + 1);
00518 #if QT_VERSION >= 0x040000
00519 #ifdef __GNUC__
00520 #endif
00521     r.setX(r.x() + 1);
00522     r.setY(r.y() + 1);
00523     r.setWidth(r.width() - 2);
00524     r.setHeight(r.height() - 2);
00525 #endif
00526 
00527     if ( lw > 0 )
00528     {
00529         switch(d_data->frameShadow)
00530         {
00531             case QwtDial::Raised:
00532 #if QT_VERSION < 0x040000
00533                 QwtPainter::drawRoundFrame(painter, r, 
00534                     lw, colorGroup(), false);
00535 #else
00536                 QwtPainter::drawRoundFrame(painter, r, 
00537                     lw, palette(), false);
00538 #endif
00539                 break;
00540             case QwtDial::Sunken:
00541 #if QT_VERSION < 0x040000
00542                 QwtPainter::drawRoundFrame(painter, r, 
00543                     lw, colorGroup(), true);
00544 #else
00545                 QwtPainter::drawRoundFrame(painter, r, 
00546                     lw, palette(), true);
00547 #endif
00548                 break;
00549             default: // Plain
00550             {
00551                 painter->save();
00552                 painter->setPen(QPen(Qt::black, lw));
00553                 painter->setBrush(Qt::NoBrush);
00554                 painter->drawEllipse(r);
00555                 painter->restore();
00556             }
00557         }
00558     }
00559 }
00560 
00572 void QwtDial::drawContents(QPainter *painter) const
00573 {
00574 #if QT_VERSION < 0x040000
00575     if ( backgroundMode() == Qt::NoBackground || 
00576         colorGroup().brush(QColorGroup::Base) != 
00577             colorGroup().brush(QColorGroup::Background) )
00578 #else
00579     if ( testAttribute(Qt::WA_NoSystemBackground) ||
00580         palette().brush(QPalette::Base) != 
00581             palette().brush(QPalette::Background) )
00582 #endif
00583     {
00584 
00585         const QRect br = boundingRect();
00586 
00587         painter->save();
00588         painter->setPen(Qt::NoPen);
00589 
00590 #if QT_VERSION < 0x040000
00591         painter->setBrush(colorGroup().brush(QColorGroup::Base));
00592 #else
00593         painter->setBrush(palette().brush(QPalette::Base));
00594 #endif
00595 
00596         painter->drawEllipse(br);
00597         painter->restore();
00598     }
00599 
00600 
00601     const QRect insideScaleRect = scaleContentsRect();
00602 #if QT_VERSION < 0x040000
00603     if ( colorGroup().brush(QColorGroup::Foreground) !=
00604         colorGroup().brush(QColorGroup::Base) )
00605 #else
00606     if ( palette().brush(QPalette::Foreground) !=
00607         palette().brush(QPalette::Base) )
00608 #endif
00609     {
00610         painter->save();
00611         painter->setPen(Qt::NoPen);
00612 
00613 #if QT_VERSION < 0x040000
00614         painter->setBrush(colorGroup().brush(QColorGroup::Foreground));
00615 #else
00616         painter->setBrush(palette().brush(QPalette::Foreground));
00617 #endif
00618 
00619         painter->drawEllipse(insideScaleRect.x() - 1, insideScaleRect.y() - 1,
00620             insideScaleRect.width(), insideScaleRect.height() );
00621 
00622         painter->restore();
00623     }
00624 
00625     const QPoint center = insideScaleRect.center();
00626     const int radius = insideScaleRect.width() / 2;
00627 
00628     painter->save();
00629     drawScaleContents(painter, center, radius);
00630     painter->restore();
00631 
00632     double direction = d_data->origin;
00633 
00634     if (isValid())
00635     {
00636         direction = d_data->origin + d_data->minScaleArc;
00637         if ( maxValue() > minValue() && d_data->maxScaleArc > d_data->minScaleArc )
00638         {
00639             const double ratio = 
00640                 (value() - minValue()) / (maxValue() - minValue());
00641             direction += ratio * (d_data->maxScaleArc - d_data->minScaleArc);
00642         }
00643 
00644         if ( direction >= 360.0 )
00645             direction -= 360.0;
00646     }
00647 
00648     double origin = d_data->origin;
00649     if ( mode() == RotateScale )
00650     {
00651         origin -= direction - d_data->origin;
00652         direction = d_data->origin;
00653     }
00654 
00655     painter->save();
00656     drawScale(painter, center, radius, origin, d_data->minScaleArc, d_data->maxScaleArc);
00657     painter->restore();
00658 
00659     if ( isValid() )
00660     {
00661         QPalette::ColorGroup cg;
00662         if ( isEnabled() )
00663             cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
00664         else
00665             cg = QPalette::Disabled;
00666 
00667         painter->save();
00668         drawNeedle(painter, center, radius, direction, cg);
00669         painter->restore();
00670     }
00671 }
00672 
00682 void QwtDial::drawNeedle(QPainter *painter, const QPoint &center, 
00683     int radius, double direction, QPalette::ColorGroup cg) const
00684 {
00685     if ( d_data->needle )
00686     {
00687         direction = 360.0 - direction; // counter clockwise
00688         d_data->needle->draw(painter, center, radius, direction, cg);
00689     }
00690 }
00691 
00704 void QwtDial::drawScale(QPainter *painter, const QPoint &center,
00705     int radius, double origin, double minArc, double maxArc) const
00706 {
00707     if ( d_data->scaleDraw == NULL )
00708         return;
00709 
00710     origin -= 270.0; // hardcoded origin of QwtScaleDraw
00711 
00712     double angle = maxArc - minArc;
00713     if ( angle > 360.0 )
00714         angle = fmod(angle, 360.0);
00715 
00716     minArc += origin;
00717     if ( minArc < -360.0 )
00718         minArc = fmod(minArc, 360.0);
00719     
00720     maxArc = minArc + angle;
00721     if ( maxArc > 360.0 )
00722     {
00723         // QwtAbstractScaleDraw::setAngleRange accepts only values
00724         // in the range [-360.0..360.0]
00725         minArc -= 360.0;
00726         maxArc -= 360.0;
00727     }
00728     
00729     painter->setFont(font());
00730 
00731     d_data->scaleDraw->setAngleRange(minArc, maxArc);
00732     d_data->scaleDraw->setRadius(radius);
00733     d_data->scaleDraw->moveCenter(center);
00734 
00735 #if QT_VERSION < 0x040000
00736     QColorGroup cg = colorGroup();
00737 
00738     const QColor textColor = cg.color(QColorGroup::Text);
00739     cg.setColor(QColorGroup::Foreground, textColor);
00740     painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth()));
00741     
00742     d_data->scaleDraw->draw(painter, cg);
00743 #else
00744     QPalette pal = palette();
00745 
00746     const QColor textColor = pal.color(QPalette::Text);
00747     pal.setColor(QPalette::Foreground, textColor); //ticks, backbone
00748     
00749     painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth()));
00750 
00751     d_data->scaleDraw->draw(painter, pal);
00752 #endif
00753 }
00754 
00755 void QwtDial::drawScaleContents(QPainter *, 
00756     const QPoint &, int) const
00757 {
00758     // empty default implementation
00759 }
00760 
00771 void QwtDial::setNeedle(QwtDialNeedle *needle)
00772 {
00773     if ( needle != d_data->needle )
00774     {
00775         if ( d_data->needle )
00776             delete d_data->needle;
00777 
00778         d_data->needle = needle;
00779         update();
00780     }
00781 }
00782 
00787 const QwtDialNeedle *QwtDial::needle() const 
00788 { 
00789     return d_data->needle; 
00790 }
00791 
00796 QwtDialNeedle *QwtDial::needle() 
00797 { 
00798     return d_data->needle; 
00799 }
00800 
00802 void QwtDial::rangeChange()
00803 {
00804     updateScale();
00805 }
00806 
00811 void QwtDial::updateScale()
00812 {
00813     if ( d_data->scaleDraw )
00814     {
00815         QwtLinearScaleEngine scaleEngine;
00816 
00817         const QwtScaleDiv scaleDiv = scaleEngine.divideScale(
00818             minValue(), maxValue(), 
00819             d_data->maxMajIntv, d_data->maxMinIntv, d_data->scaleStep);
00820 
00821         d_data->scaleDraw->setTransformation(scaleEngine.transformation());
00822         d_data->scaleDraw->setScaleDiv(scaleDiv);
00823     }
00824 }
00825 
00827 QwtDialScaleDraw *QwtDial::scaleDraw() 
00828 { 
00829     return d_data->scaleDraw; 
00830 }
00831 
00833 const QwtDialScaleDraw *QwtDial::scaleDraw() const 
00834 { 
00835     return d_data->scaleDraw; 
00836 }
00837 
00844 void QwtDial::setScaleDraw(QwtDialScaleDraw *scaleDraw)
00845 {
00846     if ( scaleDraw != d_data->scaleDraw )
00847     {
00848         if ( d_data->scaleDraw )
00849             delete d_data->scaleDraw;
00850     
00851         d_data->scaleDraw = scaleDraw;
00852         updateScale();
00853         update();
00854     }
00855 }
00856 
00861 void QwtDial::setScale(int maxMajIntv, int maxMinIntv, double step)
00862 {
00863     d_data->maxMajIntv = maxMajIntv;
00864     d_data->maxMinIntv = maxMinIntv;
00865     d_data->scaleStep = step;
00866 
00867     updateScale();
00868 }
00869 
00884 void QwtDial::setScaleOptions(int options)
00885 {
00886     if ( options == 0 )
00887         setScaleDraw(NULL);
00888 
00889     QwtDialScaleDraw *sd = d_data->scaleDraw;
00890     if ( sd == NULL )
00891         return;
00892 
00893     sd->enableComponent(QwtAbstractScaleDraw::Backbone, 
00894         options & ScaleBackbone);
00895 
00896     sd->enableComponent(QwtAbstractScaleDraw::Ticks, 
00897         options & ScaleTicks);
00898     
00899     sd->enableComponent(QwtAbstractScaleDraw::Labels, 
00900         options & ScaleLabel);
00901 }
00902 
00904 void QwtDial::setScaleTicks(int minLen, int medLen, 
00905     int majLen, int penWidth)
00906 {
00907     QwtDialScaleDraw *sd = d_data->scaleDraw;
00908     if ( sd )
00909     {
00910         sd->setTickLength(QwtScaleDiv::MinorTick, minLen);
00911         sd->setTickLength(QwtScaleDiv::MediumTick, medLen);
00912         sd->setTickLength(QwtScaleDiv::MajorTick, majLen);
00913         sd->setPenWidth(penWidth);
00914     }
00915 }
00916 
00923 QwtText QwtDial::scaleLabel(double value) const
00924 {
00925 #if 1
00926     if ( value == -0 )
00927         value = 0;
00928 #endif
00929 
00930     return QString::number(value);
00931 }
00932 
00934 double QwtDial::minScaleArc() const 
00935 { 
00936     return d_data->minScaleArc; 
00937 }
00938 
00940 double QwtDial::maxScaleArc() const 
00941 { 
00942     return d_data->maxScaleArc; 
00943 }
00944 
00953 void QwtDial::setOrigin(double origin)
00954 {
00955     d_data->origin = origin;
00956     update();
00957 }
00958 
00965 double QwtDial::origin() const
00966 {
00967     return d_data->origin;
00968 }
00969 
00976 void QwtDial::setScaleArc(double minArc, double maxArc)
00977 {
00978     if ( minArc != 360.0 && minArc != -360.0 )
00979         minArc = fmod(minArc, 360.0);
00980     if ( maxArc != 360.0 && maxArc != -360.0 )
00981         maxArc = fmod(maxArc, 360.0);
00982 
00983     d_data->minScaleArc = qwtMin(minArc, maxArc);
00984     d_data->maxScaleArc = qwtMax(minArc, maxArc);
00985     if ( d_data->maxScaleArc - d_data->minScaleArc > 360.0 )
00986         d_data->maxScaleArc = d_data->minScaleArc + 360.0;
00987     
00988     update();
00989 }
00990 
00992 void QwtDial::valueChange()
00993 {
00994     update();
00995     QwtAbstractSlider::valueChange();
00996 }
00997 
01001 QSize QwtDial::sizeHint() const
01002 {
01003     int sh = 0;
01004     if ( d_data->scaleDraw )
01005         sh = d_data->scaleDraw->extent( QPen(), font() );
01006 
01007     const int d = 6 * sh + 2 * lineWidth();
01008     
01009     return QSize( d, d );
01010 }
01011 
01017 QSize QwtDial::minimumSizeHint() const
01018 {   
01019     int sh = 0;
01020     if ( d_data->scaleDraw )
01021         sh = d_data->scaleDraw->extent(QPen(), font() );
01022 
01023     const int d = 3 * sh + 2 * lineWidth();
01024     
01025     return QSize( d, d );
01026 }
01027 
01028 static double line2Radians(const QPoint &p1, const QPoint &p2)
01029 {
01030     const QPoint p = p2 - p1;
01031 
01032     double angle;
01033     if ( p.x() == 0 )
01034         angle = ( p.y() <= 0 ) ? M_PI_2 : 3 * M_PI_2;
01035     else
01036     {
01037         angle = atan(double(-p.y()) / double(p.x()));
01038         if ( p.x() < 0 )
01039             angle += M_PI;
01040         if ( angle < 0.0 )
01041             angle += 2 * M_PI;
01042     }
01043     return 360.0 - angle * 180.0 / M_PI;
01044 }
01045 
01052 double QwtDial::getValue(const QPoint &pos)
01053 {
01054     if ( d_data->maxScaleArc == d_data->minScaleArc || maxValue() == minValue() )
01055         return minValue();
01056 
01057     double dir = line2Radians(rect().center(), pos) - d_data->origin;
01058     if ( dir < 0.0 )
01059         dir += 360.0;
01060 
01061     if ( mode() == RotateScale )
01062         dir = 360.0 - dir;
01063 
01064     // The position might be in the area that is outside the scale arc.
01065     // We need the range of the scale if it was a complete circle.
01066 
01067     const double completeCircle = 360.0 / (d_data->maxScaleArc - d_data->minScaleArc) 
01068         * (maxValue() - minValue());
01069 
01070     double posValue = minValue() + completeCircle * dir / 360.0;
01071 
01072     if ( scrollMode() == ScrMouse )
01073     {
01074         if ( d_data->previousDir >= 0.0 ) // valid direction
01075         {
01076             // We have to find out whether the mouse is moving
01077             // clock or counter clockwise
01078 
01079             bool clockWise = false;
01080 
01081             const double angle = dir - d_data->previousDir;
01082             if ( (angle >= 0.0 && angle <= 180.0) || angle < -180.0 )
01083                 clockWise = true;
01084 
01085             if ( clockWise )
01086             {
01087                 if ( dir < d_data->previousDir && mouseOffset() > 0.0 )
01088                 {
01089                     // We passed 360 -> 0
01090                     setMouseOffset(mouseOffset() - completeCircle);
01091                 }
01092 
01093                 if ( wrapping() )
01094                 {
01095                     if ( posValue - mouseOffset() > maxValue() )
01096                     {
01097                         // We passed maxValue and the value will be set
01098                         // to minValue. We have to adjust the mouseOffset.
01099 
01100                         setMouseOffset(posValue - minValue());
01101                     }
01102                 }
01103                 else
01104                 {
01105                     if ( posValue - mouseOffset() > maxValue() ||
01106                         value() == maxValue() )
01107                     {
01108                         // We fix the value at maxValue by adjusting
01109                         // the mouse offset.
01110 
01111                         setMouseOffset(posValue - maxValue());
01112                     }
01113                 }
01114             }
01115             else
01116             {
01117                 if ( dir > d_data->previousDir && mouseOffset() < 0.0 )
01118                 {
01119                     // We passed 0 -> 360 
01120                     setMouseOffset(mouseOffset() + completeCircle);    
01121                 }
01122 
01123                 if ( wrapping() )
01124                 {
01125                     if ( posValue - mouseOffset() < minValue() )
01126                     {
01127                         // We passed minValue and the value will be set
01128                         // to maxValue. We have to adjust the mouseOffset.
01129 
01130                         setMouseOffset(posValue - maxValue());
01131                     }
01132                 }
01133                 else
01134                 {
01135                     if ( posValue - mouseOffset() < minValue() ||
01136                         value() == minValue() )
01137                     {
01138                         // We fix the value at minValue by adjusting
01139                         // the mouse offset.
01140 
01141                         setMouseOffset(posValue - minValue());
01142                     }
01143                 }
01144             }
01145         }
01146         d_data->previousDir = dir;
01147     }
01148 
01149     return posValue;
01150 }
01151 
01155 void QwtDial::getScrollMode(const QPoint &p, int &scrollMode, int &direction)
01156 {
01157     direction = 0;
01158     scrollMode = ScrNone;
01159 
01160     const QRegion region(contentsRect(), QRegion::Ellipse);
01161     if ( region.contains(p) && p != rect().center() )
01162     {
01163         scrollMode = ScrMouse;
01164         d_data->previousDir = -1.0;
01165     }
01166 }
01167 
01187 void QwtDial::keyPressEvent(QKeyEvent *e)
01188 {
01189     if ( isReadOnly() )
01190     {
01191         e->ignore();
01192         return;
01193     }
01194 
01195     if ( !isValid() )
01196         return;
01197 
01198     double previous = prevValue();
01199     switch ( e->key() )
01200     {
01201         case Qt::Key_Down:
01202         case Qt::Key_Left:
01203             QwtDoubleRange::incValue(-1);
01204             break;
01205 #if QT_VERSION < 0x040000
01206         case Qt::Key_Prior:
01207 #else
01208         case Qt::Key_PageUp:
01209 #endif
01210             QwtDoubleRange::incValue(-pageSize());
01211             break;
01212         case Qt::Key_Home:
01213             setValue(minValue());
01214             break;
01215 
01216         case Qt::Key_Up:
01217         case Qt::Key_Right:
01218             QwtDoubleRange::incValue(1);
01219             break;
01220 #if QT_VERSION < 0x040000
01221         case Qt::Key_Next:
01222 #else
01223         case Qt::Key_PageDown:
01224 #endif
01225             QwtDoubleRange::incValue(pageSize());
01226             break;
01227         case Qt::Key_End:
01228             setValue(maxValue());
01229             break;
01230         default:;
01231             e->ignore();
01232     }
01233 
01234     if (value() != previous)
01235         emit sliderMoved(value());
01236 }
01237 
01246 void QwtDial::updateMask()
01247 {
01248     if ( d_data->visibleBackground )
01249         clearMask();
01250     else
01251         setMask(QRegion(boundingRect(), QRegion::Ellipse));
01252 }

Generated on Mon Feb 26 21:22:36 2007 for Qwt User's Guide by  doxygen 1.4.6