Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / ground / gcs / src / libs / qwt / src / qwt_wheel.cpp
blob5078184e08925b12fb5d2a67a2c8ffae050f4962
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
10 #include "qwt_wheel.h"
11 #include "qwt_math.h"
12 #include "qwt_painter.h"
13 #include <qevent.h>
14 #include <qdrawutil.h>
15 #include <qpainter.h>
16 #include <qstyle.h>
17 #include <qstyleoption.h>
18 #include <qapplication.h>
19 #include <qdatetime.h>
21 #if QT_VERSION < 0x040601
22 #define qFabs(x) ::fabs(x)
23 #define qFastSin(x) ::sin(x)
24 #define qExp(x) ::exp(x)
25 #endif
27 class QwtWheel::PrivateData
29 public:
30 PrivateData():
31 orientation( Qt::Horizontal ),
32 viewAngle( 175.0 ),
33 totalAngle( 360.0 ),
34 tickCount( 10 ),
35 wheelBorderWidth( 2 ),
36 borderWidth( 2 ),
37 wheelWidth( 20 ),
38 isScrolling( false ),
39 mouseOffset( 0.0 ),
40 tracking( true ),
41 pendingValueChanged( false ),
42 updateInterval( 50 ),
43 mass( 0.0 ),
44 timerId( 0 ),
45 speed( 0.0 ),
46 mouseValue( 0.0 ),
47 flyingValue( 0.0 ),
48 minimum( 0.0 ),
49 maximum( 100.0 ),
50 singleStep( 1.0 ),
51 pageStepCount( 1 ),
52 stepAlignment( true ),
53 value( 0.0 ),
54 inverted( false ),
55 wrapping( false )
59 Qt::Orientation orientation;
60 double viewAngle;
61 double totalAngle;
62 int tickCount;
63 int wheelBorderWidth;
64 int borderWidth;
65 int wheelWidth;
67 bool isScrolling;
68 double mouseOffset;
70 bool tracking;
71 bool pendingValueChanged; // when not tracking
73 int updateInterval;
74 double mass;
76 // for the flying wheel effect
77 int timerId;
78 QTime time;
79 double speed;
80 double mouseValue;
81 double flyingValue;
83 double minimum;
84 double maximum;
86 double singleStep;
87 int pageStepCount;
88 bool stepAlignment;
90 double value;
92 bool inverted;
93 bool wrapping;
96 //! Constructor
97 QwtWheel::QwtWheel( QWidget *parent ):
98 QWidget( parent )
100 d_data = new PrivateData;
102 setFocusPolicy( Qt::StrongFocus );
103 setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
104 setAttribute( Qt::WA_WState_OwnSizePolicy, false );
107 //! Destructor
108 QwtWheel::~QwtWheel()
110 delete d_data;
114 \brief En/Disable tracking
116 If tracking is enabled (the default), the wheel emits the valueChanged()
117 signal while the wheel is moving. If tracking is disabled, the wheel
118 emits the valueChanged() signal only when the wheel movement is terminated.
120 The wheelMoved() signal is emitted regardless id tracking is enabled or not.
122 \param enable On/Off
123 \sa isTracking()
125 void QwtWheel::setTracking( bool enable )
127 d_data->tracking = enable;
131 \return True, when tracking is enabled
132 \sa setTracking(), valueChanged(), wheelMoved()
134 bool QwtWheel::isTracking() const
136 return d_data->tracking;
140 \brief Specify the update interval when the wheel is flying
142 Default and minimum value is 50 ms.
144 \param interval Interval in milliseconds
145 \sa updateInterval(), setMass(), setTracking()
147 void QwtWheel::setUpdateInterval( int interval )
149 d_data->updateInterval = qMax( interval, 50 );
153 \return Update interval when the wheel is flying
154 \sa setUpdateInterval(), mass(), isTracking()
156 int QwtWheel::updateInterval() const
158 return d_data->updateInterval;
162 \brief Mouse press event handler
164 Start movement of the wheel.
166 \param event Mouse event
168 void QwtWheel::mousePressEvent( QMouseEvent *event )
170 stopFlying();
172 d_data->isScrolling = wheelRect().contains( event->pos() );
174 if ( d_data->isScrolling )
176 d_data->time.start();
177 d_data->speed = 0.0;
178 d_data->mouseValue = valueAt( event->pos() );
179 d_data->mouseOffset = d_data->mouseValue - d_data->value;
180 d_data->pendingValueChanged = false;
182 Q_EMIT wheelPressed();
187 \brief Mouse Move Event handler
189 Turn the wheel according to the mouse position
191 \param event Mouse event
193 void QwtWheel::mouseMoveEvent( QMouseEvent *event )
195 if ( !d_data->isScrolling )
196 return;
198 double mouseValue = valueAt( event->pos() );
200 if ( d_data->mass > 0.0 )
202 double ms = d_data->time.restart();
204 // the interval when mouse move events are posted are somehow
205 // random. To avoid unrealistic speed values we limit ms
207 ms = qMax( ms, 5.0 );
209 d_data->speed = ( mouseValue - d_data->mouseValue ) / ms;
212 d_data->mouseValue = mouseValue;
214 double value = boundedValue( mouseValue - d_data->mouseOffset );
215 if ( d_data->stepAlignment )
216 value = alignedValue( value );
218 if ( value != d_data->value )
220 d_data->value = value;
222 update();
224 Q_EMIT wheelMoved( d_data->value );
226 if ( d_data->tracking )
227 Q_EMIT valueChanged( d_data->value );
228 else
229 d_data->pendingValueChanged = true;
234 \brief Mouse Release Event handler
236 When the wheel has no mass the movement of the wheel stops, otherwise
237 it starts flying.
239 \param event Mouse event
242 void QwtWheel::mouseReleaseEvent( QMouseEvent *event )
244 Q_UNUSED( event );
246 if ( !d_data->isScrolling )
247 return;
249 d_data->isScrolling = false;
251 bool startFlying = false;
253 if ( d_data->mass > 0.0 )
255 const int ms = d_data->time.elapsed();
256 if ( ( qFabs( d_data->speed ) > 0.0 ) && ( ms < 50 ) )
257 startFlying = true;
260 if ( startFlying )
262 d_data->flyingValue =
263 boundedValue( d_data->mouseValue - d_data->mouseOffset );
265 d_data->timerId = startTimer( d_data->updateInterval );
267 else
269 if ( d_data->pendingValueChanged )
270 Q_EMIT valueChanged( d_data->value );
273 d_data->pendingValueChanged = false;
274 d_data->mouseOffset = 0.0;
276 Q_EMIT wheelReleased();
280 \brief Qt timer event
282 The flying wheel effect is implemented using a timer
284 \param event Timer event
286 \sa updateInterval()
288 void QwtWheel::timerEvent( QTimerEvent *event )
290 if ( event->timerId() != d_data->timerId )
292 QWidget::timerEvent( event );
293 return;
296 d_data->speed *= qExp( -d_data->updateInterval * 0.001 / d_data->mass );
298 d_data->flyingValue += d_data->speed * d_data->updateInterval;
299 d_data->flyingValue = boundedValue( d_data->flyingValue );
301 double value = d_data->flyingValue;
302 if ( d_data->stepAlignment )
303 value = alignedValue( value );
305 if ( qFabs( d_data->speed ) < 0.001 * d_data->singleStep )
307 // stop if d_data->speed < one step per second
308 stopFlying();
311 if ( value != d_data->value )
313 d_data->value = value;
314 update();
316 if ( d_data->tracking || d_data->timerId == 0 )
317 Q_EMIT valueChanged( d_data->value );
323 \brief Handle wheel events
325 In/Decrement the value
327 \param event Wheel event
329 void QwtWheel::wheelEvent( QWheelEvent *event )
331 if ( !wheelRect().contains( event->pos() ) )
333 event->ignore();
334 return;
337 if ( d_data->isScrolling )
338 return;
340 stopFlying();
342 double increment = 0.0;
344 if ( ( event->modifiers() & Qt::ControlModifier) ||
345 ( event->modifiers() & Qt::ShiftModifier ) )
347 // one page regardless of delta
348 increment = d_data->singleStep * d_data->pageStepCount;
349 if ( event->delta() < 0 )
350 increment = -increment;
352 else
354 const int numSteps = event->delta() / 120;
355 increment = d_data->singleStep * numSteps;
358 if ( d_data->orientation == Qt::Vertical && d_data->inverted )
359 increment = -increment;
361 double value = boundedValue( d_data->value + increment );
363 if ( d_data->stepAlignment )
364 value = alignedValue( value );
366 if ( value != d_data->value )
368 d_data->value = value;
369 update();
371 Q_EMIT valueChanged( d_data->value );
372 Q_EMIT wheelMoved( d_data->value );
377 Handle key events
379 - Qt::Key_Home\n
380 Step to minimum()
382 - Qt::Key_End\n
383 Step to maximum()
385 - Qt::Key_Up\n
386 In case of a horizontal or not inverted vertical wheel the value
387 will be incremented by the step size. For an inverted vertical wheel
388 the value will be decremented by the step size.
390 - Qt::Key_Down\n
391 In case of a horizontal or not inverted vertical wheel the value
392 will be decremented by the step size. For an inverted vertical wheel
393 the value will be incremented by the step size.
395 - Qt::Key_PageUp\n
396 The value will be incremented by pageStepSize() * singleStepSize().
398 - Qt::Key_PageDown\n
399 The value will be decremented by pageStepSize() * singleStepSize().
401 \param event Key event
403 void QwtWheel::keyPressEvent( QKeyEvent *event )
405 if ( d_data->isScrolling )
407 // don't interfere mouse scrolling
408 return;
411 double value = d_data->value;
412 double increment = 0.0;
414 switch ( event->key() )
416 case Qt::Key_Down:
418 if ( d_data->orientation == Qt::Vertical && d_data->inverted )
419 increment = d_data->singleStep;
420 else
421 increment = -d_data->singleStep;
423 break;
425 case Qt::Key_Up:
427 if ( d_data->orientation == Qt::Vertical && d_data->inverted )
428 increment = -d_data->singleStep;
429 else
430 increment = d_data->singleStep;
432 break;
434 case Qt::Key_Left:
436 if ( d_data->orientation == Qt::Horizontal )
438 if ( d_data->inverted )
439 increment = d_data->singleStep;
440 else
441 increment = -d_data->singleStep;
443 break;
445 case Qt::Key_Right:
447 if ( d_data->orientation == Qt::Horizontal )
449 if ( d_data->inverted )
450 increment = -d_data->singleStep;
451 else
452 increment = d_data->singleStep;
454 break;
456 case Qt::Key_PageUp:
458 increment = d_data->pageStepCount * d_data->singleStep;
459 break;
461 case Qt::Key_PageDown:
463 increment = -d_data->pageStepCount * d_data->singleStep;
464 break;
466 case Qt::Key_Home:
468 value = d_data->minimum;
469 break;
471 case Qt::Key_End:
473 value = d_data->maximum;
474 break;
476 default:;
478 event->ignore();
482 if ( event->isAccepted() )
483 stopFlying();
485 if ( increment != 0.0 )
487 value = boundedValue( d_data->value + increment );
489 if ( d_data->stepAlignment )
490 value = alignedValue( value );
493 if ( value != d_data->value )
495 d_data->value = value;
496 update();
498 Q_EMIT valueChanged( d_data->value );
499 Q_EMIT wheelMoved( d_data->value );
504 \brief Adjust the number of grooves in the wheel's surface.
506 The number of grooves is limited to 6 <= count <= 50.
507 Values outside this range will be clipped.
508 The default value is 10.
510 \param count Number of grooves per 360 degrees
511 \sa tickCount()
513 void QwtWheel::setTickCount( int count )
515 count = qBound( 6, count, 50 );
517 if ( count != d_data->tickCount )
519 d_data->tickCount = qBound( 6, count, 50 );
520 update();
525 \return Number of grooves in the wheel's surface.
526 \sa setTickCnt()
528 int QwtWheel::tickCount() const
530 return d_data->tickCount;
534 \brief Set the wheel border width of the wheel.
536 The wheel border must not be smaller than 1
537 and is limited in dependence on the wheel's size.
538 Values outside the allowed range will be clipped.
540 The wheel border defaults to 2.
542 \param borderWidth Border width
543 \sa internalBorder()
545 void QwtWheel::setWheelBorderWidth( int borderWidth )
547 const int d = qMin( width(), height() ) / 3;
548 borderWidth = qMin( borderWidth, d );
549 d_data->wheelBorderWidth = qMax( borderWidth, 1 );
550 update();
554 \return Wheel border width
555 \sa setWheelBorderWidth()
557 int QwtWheel::wheelBorderWidth() const
559 return d_data->wheelBorderWidth;
563 \brief Set the border width
565 The border defaults to 2.
567 \param width Border width
568 \sa borderWidth()
570 void QwtWheel::setBorderWidth( int width )
572 d_data->borderWidth = qMax( width, 0 );
573 update();
577 \return Border width
578 \sa setBorderWidth()
580 int QwtWheel::borderWidth() const
582 return d_data->borderWidth;
586 \return Rectangle of the wheel without the outer border
588 QRect QwtWheel::wheelRect() const
590 const int bw = d_data->borderWidth;
591 return contentsRect().adjusted( bw, bw, -bw, -bw );
595 \brief Set the total angle which the wheel can be turned.
597 One full turn of the wheel corresponds to an angle of
598 360 degrees. A total angle of n*360 degrees means
599 that the wheel has to be turned n times around its axis
600 to get from the minimum value to the maximum value.
602 The default setting of the total angle is 360 degrees.
604 \param angle total angle in degrees
605 \sa totalAngle()
607 void QwtWheel::setTotalAngle( double angle )
609 if ( angle < 0.0 )
610 angle = 0.0;
612 d_data->totalAngle = angle;
613 update();
617 \return Total angle which the wheel can be turned.
618 \sa setTotalAngle()
620 double QwtWheel::totalAngle() const
622 return d_data->totalAngle;
626 \brief Set the wheel's orientation.
628 The default orientation is Qt::Horizontal.
630 \param orientation Qt::Horizontal or Qt::Vertical.
631 \sa orientation()
633 void QwtWheel::setOrientation( Qt::Orientation orientation )
635 if ( d_data->orientation == orientation )
636 return;
638 if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
640 QSizePolicy sp = sizePolicy();
641 sp.transpose();
642 setSizePolicy( sp );
644 setAttribute( Qt::WA_WState_OwnSizePolicy, false );
647 d_data->orientation = orientation;
648 update();
652 \return Orientation
653 \sa setOrientation()
655 Qt::Orientation QwtWheel::orientation() const
657 return d_data->orientation;
661 \brief Specify the visible portion of the wheel.
663 You may use this function for fine-tuning the appearance of
664 the wheel. The default value is 175 degrees. The value is
665 limited from 10 to 175 degrees.
667 \param angle Visible angle in degrees
668 \sa viewAngle(), setTotalAngle()
670 void QwtWheel::setViewAngle( double angle )
672 d_data->viewAngle = qBound( 10.0, angle, 175.0 );
673 update();
677 \return Visible portion of the wheel
678 \sa setViewAngle(), totalAngle()
680 double QwtWheel::viewAngle() const
682 return d_data->viewAngle;
685 /*!
686 Determine the value corresponding to a specified point
688 \param pos Position
689 \return Value corresponding to pos
691 double QwtWheel::valueAt( const QPoint &pos ) const
693 const QRectF rect = wheelRect();
695 double w, dx;
696 if ( d_data->orientation == Qt::Vertical )
698 w = rect.height();
699 dx = rect.top() - pos.y();
701 else
703 w = rect.width();
704 dx = pos.x() - rect.left();
707 if ( w == 0.0 )
708 return 0.0;
710 if ( d_data->inverted )
712 dx = w - dx;
715 // w pixels is an arc of viewAngle degrees,
716 // so we convert change in pixels to change in angle
717 const double ang = dx * d_data->viewAngle / w;
719 // value range maps to totalAngle degrees,
720 // so convert the change in angle to a change in value
721 const double val = ang * ( maximum() - minimum() ) / d_data->totalAngle;
723 return val;
726 /*!
727 \brief Qt Paint Event
728 \param event Paint event
730 void QwtWheel::paintEvent( QPaintEvent *event )
732 QPainter painter( this );
733 painter.setClipRegion( event->region() );
735 QStyleOption opt;
736 opt.init(this);
737 style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
739 qDrawShadePanel( &painter,
740 contentsRect(), palette(), true, d_data->borderWidth );
742 drawWheelBackground( &painter, wheelRect() );
743 drawTicks( &painter, wheelRect() );
745 if ( hasFocus() )
746 QwtPainter::drawFocusRect( &painter, this );
750 Draw the Wheel's background gradient
752 \param painter Painter
753 \param rect Geometry for the wheel
755 void QwtWheel::drawWheelBackground(
756 QPainter *painter, const QRectF &rect )
758 painter->save();
760 QPalette pal = palette();
762 // draw shaded background
763 QLinearGradient gradient( rect.topLeft(),
764 ( d_data->orientation == Qt::Horizontal ) ? rect.topRight() : rect.bottomLeft() );
765 gradient.setColorAt( 0.0, pal.color( QPalette::Button ) );
766 gradient.setColorAt( 0.2, pal.color( QPalette::Midlight ) );
767 gradient.setColorAt( 0.7, pal.color( QPalette::Mid ) );
768 gradient.setColorAt( 1.0, pal.color( QPalette::Dark ) );
770 painter->fillRect( rect, gradient );
772 // draw internal border
774 const QPen lightPen( palette().color( QPalette::Light ),
775 d_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap );
776 const QPen darkPen( pal.color( QPalette::Dark ),
777 d_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap );
779 const double bw2 = 0.5 * d_data->wheelBorderWidth;
781 if ( d_data->orientation == Qt::Horizontal )
783 painter->setPen( lightPen );
784 painter->drawLine( QPointF( rect.left(), rect.top() + bw2 ),
785 QPointF( rect.right(), rect.top() + bw2 ) );
787 painter->setPen( darkPen );
788 painter->drawLine( QPointF( rect.left(), rect.bottom() - bw2 ),
789 QPointF( rect.right(), rect.bottom() - bw2 ) );
791 else // Qt::Vertical
793 painter->setPen( lightPen );
794 painter->drawLine( QPointF( rect.left() + bw2, rect.top() ),
795 QPointF( rect.left() + bw2, rect.bottom() ) );
797 painter->setPen( darkPen );
798 painter->drawLine( QPointF( rect.right() - bw2, rect.top() ),
799 QPointF( rect.right() - bw2, rect.bottom() ) );
802 painter->restore();
806 Draw the Wheel's ticks
808 \param painter Painter
809 \param rect Geometry for the wheel
811 void QwtWheel::drawTicks( QPainter *painter, const QRectF &rect )
813 const double range = d_data->maximum - d_data->minimum;
815 if ( range == 0.0 || d_data->totalAngle == 0.0 )
817 return;
820 const QPen lightPen( palette().color( QPalette::Light ),
821 0, Qt::SolidLine, Qt::FlatCap );
822 const QPen darkPen( palette().color( QPalette::Dark ),
823 0, Qt::SolidLine, Qt::FlatCap );
825 const double cnvFactor = qAbs( d_data->totalAngle / range );
826 const double halfIntv = 0.5 * d_data->viewAngle / cnvFactor;
827 const double loValue = value() - halfIntv;
828 const double hiValue = value() + halfIntv;
829 const double tickWidth = 360.0 / double( d_data->tickCount ) / cnvFactor;
830 const double sinArc = qFastSin( d_data->viewAngle * M_PI / 360.0 );
832 if ( d_data->orientation == Qt::Horizontal )
834 const double radius = rect.width() * 0.5;
836 double l1 = rect.top() + d_data->wheelBorderWidth;
837 double l2 = rect.bottom() - d_data->wheelBorderWidth - 1;
839 // draw one point over the border if border > 1
840 if ( d_data->wheelBorderWidth > 1 )
842 l1--;
843 l2++;
846 const double maxpos = rect.right() - 2;
847 const double minpos = rect.left() + 2;
849 // draw tick marks
850 for ( double tickValue = ::ceil( loValue / tickWidth ) * tickWidth;
851 tickValue < hiValue; tickValue += tickWidth )
853 const double angle = qwtRadians( tickValue - value() );
854 const double s = qFastSin( angle * cnvFactor );
856 const double off = radius * ( sinArc + s ) / sinArc;
858 double tickPos;
859 if ( d_data->inverted )
860 tickPos = rect.left() + off;
861 else
862 tickPos = rect.right() - off;
864 if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) )
866 painter->setPen( darkPen );
867 painter->drawLine( QPointF( tickPos - 1 , l1 ),
868 QPointF( tickPos - 1, l2 ) );
869 painter->setPen( lightPen );
870 painter->drawLine( QPointF( tickPos, l1 ),
871 QPointF( tickPos, l2 ) );
875 else // Qt::Vertical
877 const double radius = rect.height() * 0.5;
879 double l1 = rect.left() + d_data->wheelBorderWidth;
880 double l2 = rect.right() - d_data->wheelBorderWidth - 1;
882 if ( d_data->wheelBorderWidth > 1 )
884 l1--;
885 l2++;
888 const double maxpos = rect.bottom() - 2;
889 const double minpos = rect.top() + 2;
891 for ( double tickValue = ::ceil( loValue / tickWidth ) * tickWidth;
892 tickValue < hiValue; tickValue += tickWidth )
894 const double angle = qwtRadians( tickValue - value() );
895 const double s = qFastSin( angle * cnvFactor );
897 const double off = radius * ( sinArc + s ) / sinArc;
899 double tickPos;
901 if ( d_data->inverted )
902 tickPos = rect.bottom() - off;
903 else
904 tickPos = rect.top() + off;
906 if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) )
908 painter->setPen( darkPen );
909 painter->drawLine( QPointF( l1, tickPos - 1 ),
910 QPointF( l2, tickPos - 1 ) );
911 painter->setPen( lightPen );
912 painter->drawLine( QPointF( l1, tickPos ),
913 QPointF( l2, tickPos ) );
920 \brief Set the width of the wheel
922 Corresponds to the wheel height for horizontal orientation,
923 and the wheel width for vertical orientation.
925 \param width the wheel's width
926 \sa wheelWidth()
928 void QwtWheel::setWheelWidth( int width )
930 d_data->wheelWidth = width;
931 update();
935 \return Width of the wheel
936 \sa setWheelWidth()
938 int QwtWheel::wheelWidth() const
940 return d_data->wheelWidth;
944 \return a size hint
946 QSize QwtWheel::sizeHint() const
948 const QSize hint = minimumSizeHint();
949 return hint.expandedTo( QApplication::globalStrut() );
953 \return Minimum size hint
954 \warning The return value is based on the wheel width.
956 QSize QwtWheel::minimumSizeHint() const
958 QSize sz( 3 * d_data->wheelWidth + 2 * d_data->borderWidth,
959 d_data->wheelWidth + 2 * d_data->borderWidth );
960 if ( d_data->orientation != Qt::Horizontal )
961 sz.transpose();
963 return sz;
967 \brief Set the step size of the counter
969 A value <= 0.0 disables stepping
971 \param stepSize Single step size
972 \sa singleStep(), setPageStepCount()
974 void QwtWheel::setSingleStep( double stepSize )
976 d_data->singleStep = qMax( stepSize, 0.0 );
980 \return Single step size
981 \sa setSingleStep()
983 double QwtWheel::singleStep() const
985 return d_data->singleStep;
989 \brief En/Disable step alignment
991 When step alignment is enabled value changes initiated by
992 user input ( mouse, keyboard, wheel ) are aligned to
993 the multiples of the single step.
995 \param on On/Off
996 \sa stepAlignment(), setSingleStep()
998 void QwtWheel::setStepAlignment( bool on )
1000 if ( on != d_data->stepAlignment )
1002 d_data->stepAlignment = on;
1007 \return True, when the step alignment is enabled
1008 \sa setStepAlignment(), singleStep()
1010 bool QwtWheel::stepAlignment() const
1012 return d_data->stepAlignment;
1016 \brief Set the page step count
1018 pageStepCount is a multiplicator for the single step size
1019 that typically corresponds to the user pressing PageUp or PageDown.
1021 A value of 0 disables page stepping.
1023 The default value is 1.
1025 \param count Multiplicator for the single step size
1026 \sa pageStepCount(), setSingleStep()
1028 void QwtWheel::setPageStepCount( int count )
1030 d_data->pageStepCount = qMax( 0, count );
1033 /*!
1034 \return Page step count
1035 \sa setPageStepCount(), singleStep()
1037 int QwtWheel::pageStepCount() const
1039 return d_data->pageStepCount;
1043 \brief Set the minimum and maximum values
1045 The maximum is adjusted if necessary to ensure that the range remains valid.
1046 The value might be modified to be inside of the range.
1048 \param min Minimum value
1049 \param max Maximum value
1051 \sa minimum(), maximum()
1053 void QwtWheel::setRange( double min, double max )
1055 max = qMax( min, max );
1057 if ( d_data->minimum == min && d_data->maximum == max )
1058 return;
1060 d_data->minimum = min;
1061 d_data->maximum = max;
1063 if ( d_data->value < min || d_data->value > max )
1065 d_data->value = qBound( min, d_data->value, max );
1067 update();
1068 Q_EMIT valueChanged( d_data->value );
1072 Set the minimum value of the range
1074 \param value Minimum value
1075 \sa setRange(), setMaximum(), minimum()
1077 \note The maximum is adjusted if necessary to ensure that the range remains valid.
1079 void QwtWheel::setMinimum( double value )
1081 setRange( value, maximum() );
1085 \return The minimum of the range
1086 \sa setRange(), setMinimum(), maximum()
1088 double QwtWheel::minimum() const
1090 return d_data->minimum;
1094 Set the maximum value of the range
1096 \param value Maximum value
1097 \sa setRange(), setMinimum(), maximum()
1099 void QwtWheel::setMaximum( double value )
1101 setRange( minimum(), value );
1105 \return The maximum of the range
1106 \sa setRange(), setMaximum(), minimum()
1108 double QwtWheel::maximum() const
1110 return d_data->maximum;
1114 \brief Set a new value without adjusting to the step raster
1116 \param value New value
1118 \sa value(), valueChanged()
1119 \warning The value is clipped when it lies outside the range.
1121 void QwtWheel::setValue( double value )
1123 stopFlying();
1124 d_data->isScrolling = false;
1126 value = qBound( d_data->minimum, value, d_data->maximum );
1128 if ( d_data->value != value )
1130 d_data->value = value;
1132 update();
1133 Q_EMIT valueChanged( d_data->value );
1138 \return Current value of the wheel
1139 \sa setValue(), valueChanged()
1141 double QwtWheel::value() const
1143 return d_data->value;
1147 \brief En/Disable inverted appearance
1149 An inverted wheel increases its values in the opposite direction.
1150 The direction of an inverted horizontal wheel will be from right to left
1151 an inverted vertical wheel will increase from bottom to top.
1153 \param on En/Disable inverted appearance
1154 \sa isInverted()
1157 void QwtWheel::setInverted( bool on )
1159 if ( d_data->inverted != on )
1161 d_data->inverted = on;
1162 update();
1167 \return True, when the wheel is inverted
1168 \sa setInverted()
1170 bool QwtWheel::isInverted() const
1172 return d_data->inverted;
1176 \brief En/Disable wrapping
1178 If wrapping is true stepping up from maximum() value will take
1179 you to the minimum() value and vice versa.
1181 \param on En/Disable wrapping
1182 \sa wrapping()
1184 void QwtWheel::setWrapping( bool on )
1186 d_data->wrapping = on;
1190 \return True, when wrapping is set
1191 \sa setWrapping()
1193 bool QwtWheel::wrapping() const
1195 return d_data->wrapping;
1199 \brief Set the slider's mass for flywheel effect.
1201 If the slider's mass is greater then 0, it will continue
1202 to move after the mouse button has been released. Its speed
1203 decreases with time at a rate depending on the slider's mass.
1204 A large mass means that it will continue to move for a
1205 long time.
1207 Derived widgets may overload this function to make it public.
1209 \param mass New mass in kg
1211 \bug If the mass is smaller than 1g, it is set to zero.
1212 The maximal mass is limited to 100kg.
1213 \sa mass()
1215 void QwtWheel::setMass( double mass )
1217 if ( mass < 0.001 )
1219 d_data->mass = 0.0;
1221 else
1223 d_data->mass = qMin( 100.0, mass );
1226 if ( d_data->mass <= 0.0 )
1227 stopFlying();
1231 \return mass
1232 \sa setMass()
1234 double QwtWheel::mass() const
1236 return d_data->mass;
1239 //! Stop the flying movement of the wheel
1240 void QwtWheel::stopFlying()
1242 if ( d_data->timerId != 0 )
1244 killTimer( d_data->timerId );
1245 d_data->timerId = 0;
1246 d_data->speed = 0.0;
1250 double QwtWheel::boundedValue( double value ) const
1252 const double range = d_data->maximum - d_data->minimum;
1254 if ( d_data->wrapping && range >= 0.0 )
1256 if ( value < d_data->minimum )
1258 value += ::ceil( ( d_data->minimum - value ) / range ) * range;
1260 else if ( value > d_data->maximum )
1262 value -= ::ceil( ( value - d_data->maximum ) / range ) * range;
1265 else
1267 value = qBound( d_data->minimum, value, d_data->maximum );
1270 return value;
1273 double QwtWheel::alignedValue( double value ) const
1275 const double stepSize = d_data->singleStep;
1277 if ( stepSize > 0.0 )
1279 value = d_data->minimum +
1280 qRound( ( value - d_data->minimum ) / stepSize ) * stepSize;
1282 if ( stepSize > 1e-12 )
1284 if ( qFuzzyCompare( value + 1.0, 1.0 ) )
1286 // correct rounding error if value = 0
1287 value = 0.0;
1289 else if ( qFuzzyCompare( value, d_data->maximum ) )
1291 // correct rounding error at the border
1292 value = d_data->maximum;
1297 return value;