00001
00002
00003
00004
00005
00006
00007
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;
00072
00073 int updateInterval;
00074 double mass;
00075
00076
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
00205
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
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
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
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
00716
00717 const double ang = dx * d_data->viewAngle / w;
00718
00719
00720
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
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
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
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
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
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
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
01287 value = 0.0;
01288 }
01289 else if ( qFuzzyCompare( value, d_data->maximum ) )
01290 {
01291
01292 value = d_data->maximum;
01293 }
01294 }
01295 }
01296
01297 return value;
01298 }
01299