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 #warning QwtPainter::drawRoundFrame 
00521 #endif
00522     r.setX(r.x() + 1);
00523     r.setY(r.y() + 1);
00524     r.setWidth(r.width() - 2);
00525     r.setHeight(r.height() - 2);
00526 #endif
00527 
00528     if ( lw > 0 )
00529     {
00530         switch(d_data->frameShadow)
00531         {
00532             case QwtDial::Raised:
00533 #if QT_VERSION < 0x040000
00534                 QwtPainter::drawRoundFrame(painter, r, 
00535                     lw, colorGroup(), false);
00536 #else
00537                 QwtPainter::drawRoundFrame(painter, r, 
00538                     lw, palette(), false);
00539 #endif
00540                 break;
00541             case QwtDial::Sunken:
00542 #if QT_VERSION < 0x040000
00543                 QwtPainter::drawRoundFrame(painter, r, 
00544                     lw, colorGroup(), true);
00545 #else
00546                 QwtPainter::drawRoundFrame(painter, r, 
00547                     lw, palette(), true);
00548 #endif
00549                 break;
00550             default: // Plain
00551             {
00552                 painter->save();
00553                 painter->setPen(QPen(Qt::black, lw));
00554                 painter->setBrush(Qt::NoBrush);
00555                 painter->drawEllipse(r);
00556                 painter->restore();
00557             }
00558         }
00559     }
00560 }
00561 
00573 void QwtDial::drawContents(QPainter *painter) const
00574 {
00575 #if QT_VERSION < 0x040000
00576     if ( backgroundMode() == Qt::NoBackground || 
00577         colorGroup().brush(QColorGroup::Base) != 
00578             colorGroup().brush(QColorGroup::Background) )
00579 #else
00580     if ( testAttribute(Qt::WA_NoSystemBackground) ||
00581         palette().brush(QPalette::Base) != 
00582             palette().brush(QPalette::Background) )
00583 #endif
00584     {
00585 
00586         const QRect br = boundingRect();
00587 
00588         painter->save();
00589         painter->setPen(Qt::NoPen);
00590 
00591 #if QT_VERSION < 0x040000
00592         painter->setBrush(colorGroup().brush(QColorGroup::Base));
00593 #else
00594         painter->setBrush(palette().brush(QPalette::Base));
00595 #endif
00596 
00597         painter->drawEllipse(br);
00598         painter->restore();
00599     }
00600 
00601 
00602     const QRect insideScaleRect = scaleContentsRect();
00603 #if QT_VERSION < 0x040000
00604     if ( colorGroup().brush(QColorGroup::Foreground) !=
00605         colorGroup().brush(QColorGroup::Base) )
00606 #else
00607     if ( palette().brush(QPalette::Foreground) !=
00608         palette().brush(QPalette::Base) )
00609 #endif
00610     {
00611         painter->save();
00612         painter->setPen(Qt::NoPen);
00613 
00614 #if QT_VERSION < 0x040000
00615         painter->setBrush(colorGroup().brush(QColorGroup::Foreground));
00616 #else
00617         painter->setBrush(palette().brush(QPalette::Foreground));
00618 #endif
00619 
00620         painter->drawEllipse(insideScaleRect.x() - 1, insideScaleRect.y() - 1,
00621             insideScaleRect.width(), insideScaleRect.height() );
00622 
00623         painter->restore();
00624     }
00625 
00626     const QPoint center = insideScaleRect.center();
00627     const int radius = insideScaleRect.width() / 2;
00628 
00629     painter->save();
00630     drawScaleContents(painter, center, radius);
00631     painter->restore();
00632 
00633     double direction = d_data->origin;
00634 
00635     if (isValid())
00636     {
00637         direction = d_data->origin + d_data->minScaleArc;
00638         if ( maxValue() > minValue() && d_data->maxScaleArc > d_data->minScaleArc )
00639         {
00640             const double ratio = 
00641                 (value() - minValue()) / (maxValue() - minValue());
00642             direction += ratio * (d_data->maxScaleArc - d_data->minScaleArc);
00643         }
00644 
00645         if ( direction >= 360.0 )
00646             direction -= 360.0;
00647     }
00648 
00649     double origin = d_data->origin;
00650     if ( mode() == RotateScale )
00651     {
00652         origin -= direction - d_data->origin;
00653         direction = d_data->origin;
00654     }
00655 
00656     painter->save();
00657     drawScale(painter, center, radius, origin, d_data->minScaleArc, d_data->maxScaleArc);
00658     painter->restore();
00659 
00660     if ( isValid() )
00661     {
00662         QPalette::ColorGroup cg;
00663         if ( isEnabled() )
00664             cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
00665         else
00666             cg = QPalette::Disabled;
00667 
00668         painter->save();
00669         drawNeedle(painter, center, radius, direction, cg);
00670         painter->restore();
00671     }
00672 }
00673 
00683 void QwtDial::drawNeedle(QPainter *painter, const QPoint &center, 
00684     int radius, double direction, QPalette::ColorGroup cg) const
00685 {
00686     if ( d_data->needle )
00687     {
00688         direction = 360.0 - direction; // counter clockwise
00689         d_data->needle->draw(painter, center, radius, direction, cg);
00690     }
00691 }
00692 
00705 void QwtDial::drawScale(QPainter *painter, const QPoint &center,
00706     int radius, double origin, double minArc, double maxArc) const
00707 {
00708     if ( d_data->scaleDraw == NULL )
00709         return;
00710 
00711     origin -= 270.0; // hardcoded origin of QwtScaleDraw
00712 
00713     double angle = maxArc - minArc;
00714     if ( angle > 360.0 )
00715         angle = fmod(angle, 360.0);
00716 
00717     minArc += origin;
00718     if ( minArc < -360.0 )
00719         minArc = fmod(minArc, 360.0);
00720     
00721     maxArc = minArc + angle;
00722     if ( maxArc > 360.0 )
00723     {
00724         // QwtAbstractScaleDraw::setAngleRange accepts only values
00725         // in the range [-360.0..360.0]
00726         minArc -= 360.0;
00727         maxArc -= 360.0;
00728     }
00729     
00730     painter->setFont(font());
00731 
00732     d_data->scaleDraw->setAngleRange(minArc, maxArc);
00733     d_data->scaleDraw->setRadius(radius);
00734     d_data->scaleDraw->moveCenter(center);
00735 
00736 #if QT_VERSION < 0x040000
00737     QColorGroup cg = colorGroup();
00738 
00739     const QColor textColor = cg.color(QColorGroup::Text);
00740     cg.setColor(QColorGroup::Foreground, textColor);
00741     painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth()));
00742     
00743     d_data->scaleDraw->draw(painter, cg);
00744 #else
00745     QPalette pal = palette();
00746 
00747     const QColor textColor = pal.color(QPalette::Text);
00748     pal.setColor(QPalette::Foreground, textColor); //ticks, backbone
00749     
00750     painter->setPen(QPen(textColor, d_data->scaleDraw->penWidth()));
00751 
00752     d_data->scaleDraw->draw(painter, pal);
00753 #endif
00754 }
00755 
00756 void QwtDial::drawScaleContents(QPainter *, 
00757     const QPoint &, int) const
00758 {
00759     // empty default implementation
00760 }
00761 
00772 void QwtDial::setNeedle(QwtDialNeedle *needle)
00773 {
00774     if ( needle != d_data->needle )
00775     {
00776         if ( d_data->needle )
00777             delete d_data->needle;
00778 
00779         d_data->needle = needle;
00780         update();
00781     }
00782 }
00783 
00788 const QwtDialNeedle *QwtDial::needle() const 
00789 { 
00790     return d_data->needle; 
00791 }
00792 
00797 QwtDialNeedle *QwtDial::needle() 
00798 { 
00799     return d_data->needle; 
00800 }
00801 
00803 void QwtDial::rangeChange()
00804 {
00805     updateScale();
00806 }
00807 
00812 void QwtDial::updateScale()
00813 {
00814     if ( d_data->scaleDraw )
00815     {
00816         QwtLinearScaleEngine scaleEngine;
00817 
00818         const QwtScaleDiv scaleDiv = scaleEngine.divideScale(
00819             minValue(), maxValue(), 
00820             d_data->maxMajIntv, d_data->maxMinIntv, d_data->scaleStep);
00821 
00822         d_data->scaleDraw->setTransformation(scaleEngine.transformation());
00823         d_data->scaleDraw->setScaleDiv(scaleDiv);
00824     }
00825 }
00826 
00828 QwtDialScaleDraw *QwtDial::scaleDraw() 
00829 { 
00830     return d_data->scaleDraw; 
00831 }
00832 
00834 const QwtDialScaleDraw *QwtDial::scaleDraw() const 
00835 { 
00836     return d_data->scaleDraw; 
00837 }
00838 
00845 void QwtDial::setScaleDraw(QwtDialScaleDraw *scaleDraw)
00846 {
00847     if ( scaleDraw != d_data->scaleDraw )
00848     {
00849         if ( d_data->scaleDraw )
00850             delete d_data->scaleDraw;
00851     
00852         d_data->scaleDraw = scaleDraw;
00853         updateScale();
00854         update();
00855     }
00856 }
00857 
00862 void QwtDial::setScale(int maxMajIntv, int maxMinIntv, double step)
00863 {
00864     d_data->maxMajIntv = maxMajIntv;
00865     d_data->maxMinIntv = maxMinIntv;
00866     d_data->scaleStep = step;
00867 
00868     updateScale();
00869 }
00870 
00885 void QwtDial::setScaleOptions(int options)
00886 {
00887     if ( options == 0 )
00888         setScaleDraw(NULL);
00889 
00890     QwtDialScaleDraw *sd = d_data->scaleDraw;
00891     if ( sd == NULL )
00892         return;
00893 
00894     sd->enableComponent(QwtAbstractScaleDraw::Backbone, 
00895         options & ScaleBackbone);
00896 
00897     sd->enableComponent(QwtAbstractScaleDraw::Ticks, 
00898         options & ScaleTicks);
00899     
00900     sd->enableComponent(QwtAbstractScaleDraw::Labels, 
00901         options & ScaleLabel);
00902 }
00903 
00905 void QwtDial::setScaleTicks(int minLen, int medLen, 
00906     int majLen, int penWidth)
00907 {
00908     QwtDialScaleDraw *sd = d_data->scaleDraw;
00909     if ( sd )
00910     {
00911         sd->setTickLength(QwtScaleDiv::MinorTick, minLen);
00912         sd->setTickLength(QwtScaleDiv::MediumTick, medLen);
00913         sd->setTickLength(QwtScaleDiv::MajorTick, majLen);
00914         sd->setPenWidth(penWidth);
00915     }
00916 }
00917 
00924 QwtText QwtDial::scaleLabel(double value) const
00925 {
00926 #if 1
00927     if ( value == -0 )
00928         value = 0;
00929 #endif
00930 
00931     return QString::number(value);
00932 }
00933 
00935 double QwtDial::minScaleArc() const 
00936 { 
00937     return d_data->minScaleArc; 
00938 }
00939 
00941 double QwtDial::maxScaleArc() const 
00942 { 
00943     return d_data->maxScaleArc; 
00944 }
00945 
00954 void QwtDial::setOrigin(double origin)
00955 {
00956     d_data->origin = origin;
00957     update();
00958 }
00959 
00966 double QwtDial::origin() const
00967 {
00968     return d_data->origin;
00969 }
00970 
00977 void QwtDial::setScaleArc(double minArc, double maxArc)
00978 {
00979     if ( minArc != 360.0 && minArc != -360.0 )
00980         minArc = fmod(minArc, 360.0);
00981     if ( maxArc != 360.0 && maxArc != -360.0 )
00982         maxArc = fmod(maxArc, 360.0);
00983 
00984     d_data->minScaleArc = qwtMin(minArc, maxArc);
00985     d_data->maxScaleArc = qwtMax(minArc, maxArc);
00986     if ( d_data->maxScaleArc - d_data->minScaleArc > 360.0 )
00987         d_data->maxScaleArc = d_data->minScaleArc + 360.0;
00988     
00989     update();
00990 }
00991 
00993 void QwtDial::valueChange()
00994 {
00995     update();
00996     QwtAbstractSlider::valueChange();
00997 }
00998 
01002 QSize QwtDial::sizeHint() const
01003 {
01004     int sh = 0;
01005     if ( d_data->scaleDraw )
01006         sh = d_data->scaleDraw->extent( QPen(), font() );
01007 
01008     const int d = 6 * sh + 2 * lineWidth();
01009     
01010     return QSize( d, d );
01011 }
01012 
01018 QSize QwtDial::minimumSizeHint() const
01019 {   
01020     int sh = 0;
01021     if ( d_data->scaleDraw )
01022         sh = d_data->scaleDraw->extent(QPen(), font() );
01023 
01024     const int d = 3 * sh + 2 * lineWidth();
01025     
01026     return QSize( d, d );
01027 }
01028 
01029 static double line2Radians(const QPoint &p1, const QPoint &p2)
01030 {
01031     const QPoint p = p2 - p1;
01032 
01033     double angle;
01034     if ( p.x() == 0 )
01035         angle = ( p.y() <= 0 ) ? M_PI_2 : 3 * M_PI_2;
01036     else
01037     {
01038         angle = atan(double(-p.y()) / double(p.x()));
01039         if ( p.x() < 0 )
01040             angle += M_PI;
01041         if ( angle < 0.0 )
01042             angle += 2 * M_PI;
01043     }
01044     return 360.0 - angle * 180.0 / M_PI;
01045 }
01046 
01053 double QwtDial::getValue(const QPoint &pos)
01054 {
01055     if ( d_data->maxScaleArc == d_data->minScaleArc || maxValue() == minValue() )
01056         return minValue();
01057 
01058     double dir = line2Radians(rect().center(), pos) - d_data->origin;
01059     if ( dir < 0.0 )
01060         dir += 360.0;
01061 
01062     if ( mode() == RotateScale )
01063         dir = 360.0 - dir;
01064 
01065     // The position might be in the area that is outside the scale arc.
01066     // We need the range of the scale if it was a complete circle.
01067 
01068     const double completeCircle = 360.0 / (d_data->maxScaleArc - d_data->minScaleArc) 
01069         * (maxValue() - minValue());
01070 
01071     double posValue = minValue() + completeCircle * dir / 360.0;
01072 
01073     if ( scrollMode() == ScrMouse )
01074     {
01075         if ( d_data->previousDir >= 0.0 ) // valid direction
01076         {
01077             // We have to find out whether the mouse is moving
01078             // clock or counter clockwise
01079 
01080             bool clockWise = false;
01081 
01082             const double angle = dir - d_data->previousDir;
01083             if ( (angle >= 0.0 && angle <= 180.0) || angle < -180.0 )
01084                 clockWise = true;
01085 
01086             if ( clockWise )
01087             {
01088                 if ( dir < d_data->previousDir && mouseOffset() > 0.0 )
01089                 {
01090                     // We passed 360 -> 0
01091                     setMouseOffset(mouseOffset() - completeCircle);
01092                 }
01093 
01094                 if ( wrapping() )
01095                 {
01096                     if ( posValue - mouseOffset() > maxValue() )
01097                     {
01098                         // We passed maxValue and the value will be set
01099                         // to minValue. We have to adjust the mouseOffset.
01100 
01101                         setMouseOffset(posValue - minValue());
01102                     }
01103                 }
01104                 else
01105                 {
01106                     if ( posValue - mouseOffset() > maxValue() ||
01107                         value() == maxValue() )
01108                     {
01109                         // We fix the value at maxValue by adjusting
01110                         // the mouse offset.
01111 
01112                         setMouseOffset(posValue - maxValue());
01113                     }
01114                 }
01115             }
01116             else
01117             {
01118                 if ( dir > d_data->previousDir && mouseOffset() < 0.0 )
01119                 {
01120                     // We passed 0 -> 360 
01121                     setMouseOffset(mouseOffset() + completeCircle);    
01122                 }
01123 
01124                 if ( wrapping() )
01125                 {
01126                     if ( posValue - mouseOffset() < minValue() )
01127                     {
01128                         // We passed minValue and the value will be set
01129                         // to maxValue. We have to adjust the mouseOffset.
01130 
01131                         setMouseOffset(posValue - maxValue());
01132                     }
01133                 }
01134                 else
01135                 {
01136                     if ( posValue - mouseOffset() < minValue() ||
01137                         value() == minValue() )
01138                     {
01139                         // We fix the value at minValue by adjusting
01140                         // the mouse offset.
01141 
01142                         setMouseOffset(posValue - minValue());
01143                     }
01144                 }
01145             }
01146         }
01147         d_data->previousDir = dir;
01148     }
01149 
01150     return posValue;
01151 }
01152 
01156 void QwtDial::getScrollMode(const QPoint &p, int &scrollMode, int &direction)
01157 {
01158     direction = 0;
01159     scrollMode = ScrNone;
01160 
01161     const QRegion region(contentsRect(), QRegion::Ellipse);
01162     if ( region.contains(p) && p != rect().center() )
01163     {
01164         scrollMode = ScrMouse;
01165         d_data->previousDir = -1.0;
01166     }
01167 }
01168 
01188 void QwtDial::keyPressEvent(QKeyEvent *e)
01189 {
01190     if ( isReadOnly() )
01191     {
01192         e->ignore();
01193         return;
01194     }
01195 
01196     if ( !isValid() )
01197         return;
01198 
01199     double previous = prevValue();
01200     switch ( e->key() )
01201     {
01202         case Qt::Key_Down:
01203         case Qt::Key_Left:
01204             QwtDoubleRange::incValue(-1);
01205             break;
01206 #if QT_VERSION < 0x040000
01207         case Qt::Key_Prior:
01208 #else
01209         case Qt::Key_PageUp:
01210 #endif
01211             QwtDoubleRange::incValue(-pageSize());
01212             break;
01213         case Qt::Key_Home:
01214             setValue(minValue());
01215             break;
01216 
01217         case Qt::Key_Up:
01218         case Qt::Key_Right:
01219             QwtDoubleRange::incValue(1);
01220             break;
01221 #if QT_VERSION < 0x040000
01222         case Qt::Key_Next:
01223 #else
01224         case Qt::Key_PageDown:
01225 #endif
01226             QwtDoubleRange::incValue(pageSize());
01227             break;
01228         case Qt::Key_End:
01229             setValue(maxValue());
01230             break;
01231         default:;
01232             e->ignore();
01233     }
01234 
01235     if (value() != previous)
01236         emit sliderMoved(value());
01237 }
01238 
01247 void QwtDial::updateMask()
01248 {
01249     if ( d_data->visibleBackground )
01250         clearMask();
01251     else
01252         setMask(QRegion(boundingRect(), QRegion::Ellipse));
01253 }

Generated on Sun Jul 22 11:26:54 2007 for Qwt User's Guide by  doxygen 1.5.2