qwt_wheel.cpp
Go to the documentation of this file.
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 "qwt_wheel.h"
00011 #include "qwt_math.h"
00012 #include "qwt_painter.h"
00013 #include <qevent.h>
00014 #include <qdrawutil.h>
00015 #include <qpainter.h>
00016 #include <qstyle.h>
00017 #include <qstyleoption.h>
00018 #include <qapplication.h>
00019 #include <qdatetime.h>
00020 
00021 #if QT_VERSION < 0x040601
00022 #define qFabs(x) ::fabs(x)
00023 #define qFastSin(x) ::sin(x)
00024 #define qExp(x) ::exp(x)
00025 #endif
00026 
00027 class QwtWheel::PrivateData
00028 {
00029 public:
00030     PrivateData():
00031         orientation( Qt::Horizontal ),
00032         viewAngle( 175.0 ),
00033         totalAngle( 360.0 ),
00034         tickCount( 10 ),
00035         wheelBorderWidth( 2 ),
00036         borderWidth( 2 ),
00037         wheelWidth( 20 ),
00038         isScrolling( false ),
00039         mouseOffset( 0.0 ),
00040         tracking( true ),
00041         pendingValueChanged( false ),
00042         updateInterval( 50 ),
00043         mass( 0.0 ),
00044         timerId( 0 ),
00045         speed( 0.0 ),
00046         mouseValue( 0.0 ),
00047         flyingValue( 0.0 ),
00048         minimum( 0.0 ),
00049         maximum( 100.0 ),
00050         singleStep( 1.0 ),
00051         pageStepCount( 1 ),
00052         stepAlignment( true ),
00053         value( 0.0 ),
00054         inverted( false ),
00055         wrapping( false )
00056     {
00057     };
00058 
00059     Qt::Orientation orientation;
00060     double viewAngle;
00061     double totalAngle;
00062     int tickCount;
00063     int wheelBorderWidth;
00064     int borderWidth;
00065     int wheelWidth;
00066 
00067     bool isScrolling;
00068     double mouseOffset;
00069 
00070     bool tracking;
00071     bool pendingValueChanged; // when not tracking
00072 
00073     int updateInterval;
00074     double mass;
00075 
00076     // for the flying wheel effect
00077     int timerId;
00078     QTime time;
00079     double speed;
00080     double mouseValue;
00081     double flyingValue;
00082 
00083     double minimum;
00084     double maximum;
00085 
00086     double singleStep;
00087     int pageStepCount;
00088     bool stepAlignment;
00089 
00090     double value;
00091 
00092     bool inverted;
00093     bool wrapping;
00094 };
00095 
00097 QwtWheel::QwtWheel( QWidget *parent ):
00098     QWidget( parent )
00099 {
00100     d_data = new PrivateData;
00101 
00102     setFocusPolicy( Qt::StrongFocus );
00103     setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
00104     setAttribute( Qt::WA_WState_OwnSizePolicy, false );
00105 }
00106 
00108 QwtWheel::~QwtWheel()
00109 {
00110     delete d_data;
00111 }
00112 
00125 void QwtWheel::setTracking( bool enable )
00126 {
00127     d_data->tracking = enable;
00128 }
00129 
00134 bool QwtWheel::isTracking() const
00135 {
00136     return d_data->tracking;
00137 }
00138 
00147 void QwtWheel::setUpdateInterval( int interval )
00148 {
00149     d_data->updateInterval = qMax( interval, 50 );
00150 }
00151 
00156 int QwtWheel::updateInterval() const
00157 {
00158     return d_data->updateInterval;
00159 }
00160 
00168 void QwtWheel::mousePressEvent( QMouseEvent *event )
00169 {
00170     stopFlying();
00171 
00172     d_data->isScrolling = wheelRect().contains( event->pos() );
00173 
00174     if ( d_data->isScrolling )
00175     {
00176         d_data->time.start();
00177         d_data->speed = 0.0;
00178         d_data->mouseValue = valueAt( event->pos() );
00179         d_data->mouseOffset = d_data->mouseValue - d_data->value;
00180         d_data->pendingValueChanged = false;
00181 
00182         Q_EMIT wheelPressed();
00183     }
00184 }
00185 
00193 void QwtWheel::mouseMoveEvent( QMouseEvent *event )
00194 {
00195     if ( !d_data->isScrolling )
00196         return;
00197 
00198     double mouseValue = valueAt( event->pos() );
00199 
00200     if ( d_data->mass > 0.0 )
00201     {
00202         double ms = d_data->time.restart();
00203 
00204         // the interval when mouse move events are posted are somehow
00205         // random. To avoid unrealistic speed values we limit ms
00206 
00207         ms = qMax( ms, 5.0 );
00208 
00209         d_data->speed = ( mouseValue - d_data->mouseValue ) / ms;
00210     }
00211     
00212     d_data->mouseValue = mouseValue; 
00213 
00214     double value = boundedValue( mouseValue - d_data->mouseOffset );
00215     if ( d_data->stepAlignment )
00216         value = alignedValue( value );
00217         
00218     if ( value != d_data->value )
00219     {
00220         d_data->value = value;
00221 
00222         update();
00223 
00224         Q_EMIT wheelMoved( d_data->value );
00225 
00226         if ( d_data->tracking )
00227             Q_EMIT valueChanged( d_data->value );
00228         else
00229             d_data->pendingValueChanged = true;
00230     }
00231 }
00232 
00242 void QwtWheel::mouseReleaseEvent( QMouseEvent *event )
00243 {
00244     Q_UNUSED( event );
00245 
00246     if ( !d_data->isScrolling )
00247         return;
00248 
00249     d_data->isScrolling = false;
00250 
00251     bool startFlying = false;
00252 
00253     if ( d_data->mass > 0.0 )
00254     {
00255         const int ms = d_data->time.elapsed();
00256         if ( ( qFabs( d_data->speed ) > 0.0 ) && ( ms < 50 ) )
00257             startFlying = true;
00258     }
00259 
00260     if ( startFlying )
00261     {
00262         d_data->flyingValue = 
00263             boundedValue( d_data->mouseValue - d_data->mouseOffset );
00264 
00265         d_data->timerId = startTimer( d_data->updateInterval );
00266     }
00267     else
00268     {
00269         if ( d_data->pendingValueChanged )
00270             Q_EMIT valueChanged( d_data->value );
00271     }
00272 
00273     d_data->pendingValueChanged = false;
00274     d_data->mouseOffset = 0.0;
00275 
00276     Q_EMIT wheelReleased();
00277 }
00278 
00288 void QwtWheel::timerEvent( QTimerEvent *event )
00289 {
00290     if ( event->timerId() != d_data->timerId )
00291     {
00292         QWidget::timerEvent( event );
00293         return;
00294     }
00295 
00296     d_data->speed *= qExp( -d_data->updateInterval * 0.001 / d_data->mass );
00297 
00298     d_data->flyingValue += d_data->speed * d_data->updateInterval;
00299     d_data->flyingValue = boundedValue( d_data->flyingValue );
00300 
00301     double value = d_data->flyingValue;
00302     if ( d_data->stepAlignment )
00303         value = alignedValue( value );
00304 
00305     if ( qFabs( d_data->speed ) < 0.001 * d_data->singleStep )
00306     {
00307         // stop if d_data->speed < one step per second
00308         stopFlying();
00309     }
00310 
00311     if ( value != d_data->value )
00312     {
00313         d_data->value = value;
00314         update();
00315 
00316         if ( d_data->tracking || d_data->timerId == 0 )
00317             Q_EMIT valueChanged( d_data->value );
00318     }
00319 }
00320 
00321 
00329 void QwtWheel::wheelEvent( QWheelEvent *event )
00330 {
00331     if ( !wheelRect().contains( event->pos() ) )
00332     {
00333         event->ignore();
00334         return;
00335     }
00336 
00337     if ( d_data->isScrolling )
00338         return;
00339 
00340     stopFlying();
00341 
00342     double increment = 0.0;
00343 
00344     if ( ( event->modifiers() & Qt::ControlModifier) || 
00345         ( event->modifiers() & Qt::ShiftModifier ) )
00346     {
00347         // one page regardless of delta
00348         increment = d_data->singleStep * d_data->pageStepCount;
00349         if ( event->delta() < 0 )
00350             increment = -increment;
00351     }
00352     else
00353     {
00354         const int numSteps = event->delta() / 120;
00355         increment = d_data->singleStep * numSteps;
00356     }
00357 
00358     if ( d_data->orientation == Qt::Vertical && d_data->inverted )
00359         increment = -increment;
00360 
00361     double value = boundedValue( d_data->value + increment );
00362 
00363     if ( d_data->stepAlignment )
00364         value = alignedValue( value );
00365 
00366     if ( value != d_data->value )
00367     {
00368         d_data->value = value;
00369         update();
00370 
00371         Q_EMIT valueChanged( d_data->value );
00372         Q_EMIT wheelMoved( d_data->value );
00373     }
00374 }
00375 
00403 void QwtWheel::keyPressEvent( QKeyEvent *event )
00404 {
00405     if ( d_data->isScrolling )
00406     {
00407         // don't interfere mouse scrolling
00408         return;
00409     }
00410 
00411     double value = d_data->value;
00412     double increment = 0.0;
00413 
00414     switch ( event->key() )
00415     {
00416         case Qt::Key_Down:
00417         {
00418             if ( d_data->orientation == Qt::Vertical && d_data->inverted )
00419                 increment = d_data->singleStep;
00420             else
00421                 increment = -d_data->singleStep;
00422 
00423             break;
00424         }
00425         case Qt::Key_Up:
00426         {
00427             if ( d_data->orientation == Qt::Vertical && d_data->inverted )
00428                 increment = -d_data->singleStep;
00429             else
00430                 increment = d_data->singleStep;
00431 
00432             break;
00433         }
00434         case Qt::Key_Left:
00435         {
00436             if ( d_data->orientation == Qt::Horizontal )
00437             {
00438                 if ( d_data->inverted )
00439                     increment = d_data->singleStep;
00440                 else
00441                     increment = -d_data->singleStep;
00442             }
00443             break;
00444         }
00445         case Qt::Key_Right:
00446         {
00447             if ( d_data->orientation == Qt::Horizontal )
00448             {
00449                 if ( d_data->inverted )
00450                     increment = -d_data->singleStep;
00451                 else
00452                     increment = d_data->singleStep;
00453             }
00454             break;
00455         }
00456         case Qt::Key_PageUp:
00457         {
00458             increment = d_data->pageStepCount * d_data->singleStep;
00459             break;
00460         }
00461         case Qt::Key_PageDown:
00462         {
00463             increment = -d_data->pageStepCount * d_data->singleStep;
00464             break;
00465         }
00466         case Qt::Key_Home:
00467         {
00468             value = d_data->minimum;
00469             break;
00470         }
00471         case Qt::Key_End:
00472         {
00473             value = d_data->maximum;
00474             break;
00475         }
00476         default:;
00477         {
00478             event->ignore();
00479         }
00480     }
00481 
00482     if ( event->isAccepted() )
00483         stopFlying();
00484     
00485     if ( increment != 0.0 )
00486     {
00487         value = boundedValue( d_data->value + increment );
00488 
00489         if ( d_data->stepAlignment )
00490             value = alignedValue( value );
00491     }
00492 
00493     if ( value != d_data->value )
00494     {
00495         d_data->value = value;
00496         update();
00497 
00498         Q_EMIT valueChanged( d_data->value );
00499         Q_EMIT wheelMoved( d_data->value );
00500     }
00501 }
00502 
00513 void QwtWheel::setTickCount( int count )
00514 {
00515     count = qBound( 6, count, 50 );
00516 
00517     if ( count != d_data->tickCount )
00518     {
00519         d_data->tickCount = qBound( 6, count, 50 );
00520         update();
00521     }
00522 }
00523 
00528 int QwtWheel::tickCount() const
00529 {
00530     return d_data->tickCount;
00531 }
00532 
00545 void QwtWheel::setWheelBorderWidth( int borderWidth )
00546 {
00547     const int d = qMin( width(), height() ) / 3;
00548     borderWidth = qMin( borderWidth, d );
00549     d_data->wheelBorderWidth = qMax( borderWidth, 1 );
00550     update();
00551 }
00552 
00557 int QwtWheel::wheelBorderWidth() const
00558 {
00559     return d_data->wheelBorderWidth;
00560 }
00561 
00570 void QwtWheel::setBorderWidth( int width )
00571 {
00572     d_data->borderWidth = qMax( width, 0 );
00573     update();
00574 }
00575 
00580 int QwtWheel::borderWidth() const
00581 {
00582     return d_data->borderWidth;
00583 }
00584 
00588 QRect QwtWheel::wheelRect() const
00589 {
00590     const int bw = d_data->borderWidth;
00591     return contentsRect().adjusted( bw, bw, -bw, -bw );
00592 }
00593 
00607 void QwtWheel::setTotalAngle( double angle )
00608 {
00609     if ( angle < 0.0 )
00610         angle = 0.0;
00611 
00612     d_data->totalAngle = angle;
00613     update();
00614 }
00615 
00620 double QwtWheel::totalAngle() const
00621 {
00622     return d_data->totalAngle;
00623 }
00624 
00633 void QwtWheel::setOrientation( Qt::Orientation orientation )
00634 {
00635     if ( d_data->orientation == orientation )
00636         return;
00637 
00638     if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
00639     {
00640         QSizePolicy sp = sizePolicy();
00641         sp.transpose();
00642         setSizePolicy( sp );
00643 
00644         setAttribute( Qt::WA_WState_OwnSizePolicy, false );
00645     }
00646 
00647     d_data->orientation = orientation;
00648     update();
00649 }
00650 
00655 Qt::Orientation QwtWheel::orientation() const
00656 {
00657     return d_data->orientation;
00658 }
00659 
00670 void QwtWheel::setViewAngle( double angle )
00671 {
00672     d_data->viewAngle = qBound( 10.0, angle, 175.0 );
00673     update();
00674 }
00675 
00680 double QwtWheel::viewAngle() const
00681 {
00682     return d_data->viewAngle;
00683 }
00684 
00691 double QwtWheel::valueAt( const QPoint &pos ) const
00692 {
00693     const QRectF rect = wheelRect();
00694 
00695     double w, dx;
00696     if ( d_data->orientation == Qt::Vertical )
00697     {
00698         w = rect.height();
00699         dx = rect.top() - pos.y();
00700     }
00701     else
00702     {
00703         w = rect.width();
00704         dx = pos.x() - rect.left();
00705     }
00706 
00707     if ( w == 0.0 )
00708         return 0.0;
00709 
00710     if ( d_data->inverted )
00711     {
00712         dx = w - dx;
00713     }
00714 
00715     // w pixels is an arc of viewAngle degrees,
00716     // so we convert change in pixels to change in angle
00717     const double ang = dx * d_data->viewAngle / w;
00718 
00719     // value range maps to totalAngle degrees,
00720     // so convert the change in angle to a change in value
00721     const double val = ang * ( maximum() - minimum() ) / d_data->totalAngle;
00722 
00723     return val;
00724 }
00725 
00730 void QwtWheel::paintEvent( QPaintEvent *event )
00731 {
00732     QPainter painter( this );
00733     painter.setClipRegion( event->region() );
00734 
00735     QStyleOption opt;
00736     opt.init(this);
00737     style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
00738 
00739     qDrawShadePanel( &painter, 
00740         contentsRect(), palette(), true, d_data->borderWidth );
00741 
00742     drawWheelBackground( &painter, wheelRect() );
00743     drawTicks( &painter, wheelRect() );
00744 
00745     if ( hasFocus() )
00746         QwtPainter::drawFocusRect( &painter, this );
00747 }
00748 
00755 void QwtWheel::drawWheelBackground( 
00756     QPainter *painter, const QRectF &rect )
00757 {
00758     painter->save();
00759 
00760     QPalette pal = palette();
00761 
00762     //  draw shaded background
00763     QLinearGradient gradient( rect.topLeft(), 
00764         ( d_data->orientation == Qt::Horizontal ) ? rect.topRight() : rect.bottomLeft() );
00765     gradient.setColorAt( 0.0, pal.color( QPalette::Button ) );
00766     gradient.setColorAt( 0.2, pal.color( QPalette::Midlight ) );
00767     gradient.setColorAt( 0.7, pal.color( QPalette::Mid ) );
00768     gradient.setColorAt( 1.0, pal.color( QPalette::Dark ) );
00769 
00770     painter->fillRect( rect, gradient );
00771 
00772     // draw internal border
00773 
00774     const QPen lightPen( palette().color( QPalette::Light ), 
00775         d_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap );
00776     const QPen darkPen( pal.color( QPalette::Dark ), 
00777         d_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap );
00778 
00779     const double bw2 = 0.5 * d_data->wheelBorderWidth;
00780 
00781     if ( d_data->orientation == Qt::Horizontal )
00782     {
00783         painter->setPen( lightPen );
00784         painter->drawLine( QPointF( rect.left(), rect.top() + bw2 ), 
00785             QPointF( rect.right(), rect.top() + bw2 ) );
00786 
00787         painter->setPen( darkPen );
00788         painter->drawLine( QPointF( rect.left(), rect.bottom() - bw2 ), 
00789             QPointF( rect.right(), rect.bottom() - bw2 ) );
00790     }
00791     else // Qt::Vertical
00792     {
00793         painter->setPen( lightPen );
00794         painter->drawLine( QPointF( rect.left() + bw2, rect.top() ), 
00795             QPointF( rect.left() + bw2, rect.bottom() ) );
00796 
00797         painter->setPen( darkPen );
00798         painter->drawLine( QPointF( rect.right() - bw2, rect.top() ), 
00799             QPointF( rect.right() - bw2, rect.bottom() ) );
00800     }
00801 
00802     painter->restore();
00803 }
00804 
00811 void QwtWheel::drawTicks( QPainter *painter, const QRectF &rect )
00812 {
00813     const double range = d_data->maximum - d_data->minimum;
00814 
00815     if ( range == 0.0 || d_data->totalAngle == 0.0 )
00816     {
00817         return;
00818     }
00819 
00820     const QPen lightPen( palette().color( QPalette::Light ), 
00821         0, Qt::SolidLine, Qt::FlatCap );
00822     const QPen darkPen( palette().color( QPalette::Dark ), 
00823         0, Qt::SolidLine, Qt::FlatCap );
00824 
00825     const double cnvFactor = qAbs( d_data->totalAngle / range );
00826     const double halfIntv = 0.5 * d_data->viewAngle / cnvFactor;
00827     const double loValue = value() - halfIntv;
00828     const double hiValue = value() + halfIntv;
00829     const double tickWidth = 360.0 / double( d_data->tickCount ) / cnvFactor;
00830     const double sinArc = qFastSin( d_data->viewAngle * M_PI / 360.0 );
00831 
00832     if ( d_data->orientation == Qt::Horizontal )
00833     {
00834         const double radius = rect.width() * 0.5;
00835 
00836         double l1 = rect.top() + d_data->wheelBorderWidth;
00837         double l2 = rect.bottom() - d_data->wheelBorderWidth - 1;
00838 
00839         // draw one point over the border if border > 1
00840         if ( d_data->wheelBorderWidth > 1 )
00841         {
00842             l1--;
00843             l2++;
00844         }
00845 
00846         const double maxpos = rect.right() - 2;
00847         const double minpos = rect.left() + 2;
00848 
00849         // draw tick marks
00850         for ( double tickValue = ::ceil( loValue / tickWidth ) * tickWidth;
00851             tickValue < hiValue; tickValue += tickWidth )
00852         {
00853             const double angle = qwtRadians( tickValue - value() );
00854             const double s = qFastSin( angle * cnvFactor );
00855 
00856             const double off = radius * ( sinArc + s ) / sinArc;
00857 
00858             double tickPos;
00859             if ( d_data->inverted ) 
00860                 tickPos = rect.left() + off;
00861             else
00862                 tickPos = rect.right() - off;
00863 
00864             if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) )
00865             {
00866                 painter->setPen( darkPen );
00867                 painter->drawLine( QPointF( tickPos - 1 , l1 ), 
00868                     QPointF( tickPos - 1,  l2 ) );
00869                 painter->setPen( lightPen );
00870                 painter->drawLine( QPointF( tickPos, l1 ), 
00871                     QPointF( tickPos, l2 ) );
00872             }
00873         }
00874     }
00875     else // Qt::Vertical
00876     {
00877         const double radius = rect.height() * 0.5;
00878 
00879         double l1 = rect.left() + d_data->wheelBorderWidth;
00880         double l2 = rect.right() - d_data->wheelBorderWidth - 1;
00881 
00882         if ( d_data->wheelBorderWidth > 1 )
00883         {
00884             l1--;
00885             l2++;
00886         }
00887 
00888         const double maxpos = rect.bottom() - 2;
00889         const double minpos = rect.top() + 2;
00890 
00891         for ( double tickValue = ::ceil( loValue / tickWidth ) * tickWidth;
00892             tickValue < hiValue; tickValue += tickWidth )
00893         {
00894             const double angle = qwtRadians( tickValue - value() );
00895             const double s = qFastSin( angle * cnvFactor );
00896 
00897             const double off = radius * ( sinArc + s ) / sinArc;
00898 
00899             double tickPos;
00900 
00901             if ( d_data->inverted )
00902                 tickPos = rect.bottom() - off;
00903             else
00904                 tickPos = rect.top() + off;
00905 
00906             if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) )
00907             {
00908                 painter->setPen( darkPen );
00909                 painter->drawLine( QPointF( l1, tickPos - 1 ), 
00910                     QPointF( l2, tickPos - 1 ) );
00911                 painter->setPen( lightPen );
00912                 painter->drawLine( QPointF( l1, tickPos ), 
00913                     QPointF( l2, tickPos ) );
00914             }
00915         }
00916     }
00917 }
00918 
00928 void QwtWheel::setWheelWidth( int width )
00929 {
00930     d_data->wheelWidth = width;
00931     update();
00932 }
00933 
00938 int QwtWheel::wheelWidth() const
00939 {
00940     return d_data->wheelWidth;
00941 }
00942 
00946 QSize QwtWheel::sizeHint() const
00947 {
00948     const QSize hint = minimumSizeHint();
00949     return hint.expandedTo( QApplication::globalStrut() );
00950 }
00951 
00956 QSize QwtWheel::minimumSizeHint() const
00957 {
00958     QSize sz( 3 * d_data->wheelWidth + 2 * d_data->borderWidth,
00959         d_data->wheelWidth + 2 * d_data->borderWidth );
00960     if ( d_data->orientation != Qt::Horizontal )
00961         sz.transpose();
00962 
00963     return sz;
00964 }
00965 
00974 void QwtWheel::setSingleStep( double stepSize )
00975 {
00976     d_data->singleStep = qMax( stepSize, 0.0 );
00977 }
00978 
00983 double QwtWheel::singleStep() const
00984 {
00985     return d_data->singleStep;
00986 }
00987 
00998 void QwtWheel::setStepAlignment( bool on )
00999 {
01000     if ( on != d_data->stepAlignment )
01001     {
01002         d_data->stepAlignment = on;
01003     }
01004 }
01005 
01010 bool QwtWheel::stepAlignment() const
01011 {
01012     return d_data->stepAlignment;
01013 }
01014 
01028 void QwtWheel::setPageStepCount( int count )
01029 {
01030     d_data->pageStepCount = qMax( 0, count );
01031 }
01032 
01037 int QwtWheel::pageStepCount() const
01038 {
01039     return d_data->pageStepCount;
01040 }
01041 
01053 void QwtWheel::setRange( double min, double max )
01054 {
01055     max = qMax( min, max );
01056 
01057     if ( d_data->minimum == min && d_data->maximum == max )
01058         return;
01059 
01060     d_data->minimum = min;
01061     d_data->maximum = max;
01062 
01063     if ( d_data->value < min || d_data->value > max )
01064     {
01065         d_data->value = qBound( min, d_data->value, max );
01066 
01067         update();
01068         Q_EMIT valueChanged( d_data->value );
01069     }
01070 }
01079 void QwtWheel::setMinimum( double value )
01080 {
01081     setRange( value, maximum() );
01082 }
01083 
01088 double QwtWheel::minimum() const
01089 {
01090     return d_data->minimum;
01091 }
01092 
01099 void QwtWheel::setMaximum( double value )
01100 {
01101     setRange( minimum(), value );
01102 }
01103 
01108 double QwtWheel::maximum() const
01109 {
01110     return d_data->maximum;
01111 }
01112 
01121 void QwtWheel::setValue( double value )
01122 {
01123     stopFlying();
01124     d_data->isScrolling = false;
01125 
01126     value = qBound( d_data->minimum, value, d_data->maximum );
01127 
01128     if ( d_data->value != value )
01129     {
01130         d_data->value = value;
01131 
01132         update();
01133         Q_EMIT valueChanged( d_data->value );
01134     }
01135 }
01136 
01141 double QwtWheel::value() const
01142 {
01143     return d_data->value;
01144 }
01145 
01157 void QwtWheel::setInverted( bool on )
01158 {
01159     if ( d_data->inverted != on )
01160     {
01161         d_data->inverted = on;
01162         update();
01163     }
01164 }
01165 
01170 bool QwtWheel::isInverted() const
01171 {
01172     return d_data->inverted;
01173 }
01174 
01184 void QwtWheel::setWrapping( bool on )
01185 {
01186     d_data->wrapping = on;
01187 }
01188 
01193 bool QwtWheel::wrapping() const
01194 {
01195     return d_data->wrapping;
01196 }
01197 
01215 void QwtWheel::setMass( double mass )
01216 {
01217     if ( mass < 0.001 )
01218     {
01219         d_data->mass = 0.0;
01220     }
01221     else
01222     {
01223         d_data->mass = qMin( 100.0, mass );
01224     }
01225 
01226     if ( d_data->mass <= 0.0 )
01227         stopFlying();
01228 }
01229 
01234 double QwtWheel::mass() const
01235 {
01236     return d_data->mass;
01237 }
01238 
01240 void QwtWheel::stopFlying()
01241 {
01242     if ( d_data->timerId != 0 )
01243     {
01244         killTimer( d_data->timerId );
01245         d_data->timerId = 0;
01246         d_data->speed = 0.0;
01247     }
01248 }
01249 
01250 double QwtWheel::boundedValue( double value ) const
01251 {
01252     const double range = d_data->maximum - d_data->minimum;
01253     
01254     if ( d_data->wrapping && range >= 0.0 )
01255     {
01256         if ( value < d_data->minimum )
01257         {
01258             value += ::ceil( ( d_data->minimum - value ) / range ) * range;
01259         }       
01260         else if ( value > d_data->maximum )
01261         {
01262             value -= ::ceil( ( value - d_data->maximum ) / range ) * range;
01263         }
01264     }
01265     else
01266     {
01267         value = qBound( d_data->minimum, value, d_data->maximum );
01268     }
01269 
01270     return value;
01271 }
01272 
01273 double QwtWheel::alignedValue( double value ) const
01274 {
01275     const double stepSize = d_data->singleStep;
01276 
01277     if ( stepSize > 0.0 )
01278     {
01279         value = d_data->minimum +
01280             qRound( ( value - d_data->minimum ) / stepSize ) * stepSize;
01281 
01282         if ( stepSize > 1e-12 )
01283         {
01284             if ( qFuzzyCompare( value + 1.0, 1.0 ) )
01285             {
01286                 // correct rounding error if value = 0
01287                 value = 0.0;
01288             }
01289             else if ( qFuzzyCompare( value, d_data->maximum ) )
01290             {
01291                 // correct rounding error at the border
01292                 value = d_data->maximum;
01293             }
01294         }
01295     }       
01296 
01297     return value;
01298 }
01299 


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:57