10 #include "qwt_wheel.h" 
   12 #include "qwt_painter.h" 
   16 #include <qdrawutil.h> 
   19 #include <qstyleoption.h> 
   20 #include <qelapsedtimer.h> 
   23 class QwtWheel::PrivateData
 
   46         , isScrolling( false )
 
   49         , pendingValueChanged( false )
 
   86     bool pendingValueChanged; 
 
   95     m_data = 
new PrivateData;
 
   97     setFocusPolicy( Qt::StrongFocus );
 
   98     setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
 
   99     setAttribute( Qt::WA_WState_OwnSizePolicy, 
false );
 
  122     m_data->tracking = enable;
 
  131     return m_data->tracking;
 
  144     m_data->updateInterval = qMax( interval, 50 );
 
  153     return m_data->updateInterval;
 
  167     m_data->isScrolling = 
wheelRect().contains( event->pos() );
 
  169     if ( m_data->isScrolling )
 
  171         m_data->timer.start();
 
  173         m_data->mouseValue = 
valueAt( event->pos() );
 
  174         m_data->mouseOffset = m_data->mouseValue - m_data->value;
 
  175         m_data->pendingValueChanged = 
false;
 
  190     if ( !m_data->isScrolling )
 
  193     double mouseValue = 
valueAt( event->pos() );
 
  195     if ( m_data->mass > 0.0 )
 
  197         double ms = m_data->timer.restart();
 
  202         ms = qMax( ms, 5.0 );
 
  204         m_data->speed = ( mouseValue - m_data->mouseValue ) / ms;
 
  207     m_data->mouseValue = mouseValue;
 
  209     double value = boundedValue( mouseValue - m_data->mouseOffset );
 
  210     if ( m_data->stepAlignment )
 
  213     if ( 
value != m_data->value )
 
  215         m_data->value = 
value;
 
  221         if ( m_data->tracking )
 
  224             m_data->pendingValueChanged = 
true;
 
  241     if ( !m_data->isScrolling )
 
  244     m_data->isScrolling = 
false;
 
  246     bool startFlying = 
false;
 
  248     if ( m_data->mass > 0.0 )
 
  250         const qint64 ms = m_data->timer.elapsed();
 
  251         if ( ( std::fabs( m_data->speed ) > 0.0 ) && ( ms < 50 ) )
 
  257         m_data->flyingValue =
 
  258             boundedValue( m_data->mouseValue - m_data->mouseOffset );
 
  260         m_data->timerId = startTimer( m_data->updateInterval );
 
  264         if ( m_data->pendingValueChanged )
 
  268     m_data->pendingValueChanged = 
false;
 
  269     m_data->mouseOffset = 0.0;
 
  285     if ( event->timerId() != m_data->timerId )
 
  287         QWidget::timerEvent( event );
 
  291     m_data->speed *= std::exp( -m_data->updateInterval * 0.001 / m_data->mass );
 
  293     m_data->flyingValue += m_data->speed * m_data->updateInterval;
 
  294     m_data->flyingValue = boundedValue( m_data->flyingValue );
 
  296     double value = m_data->flyingValue;
 
  297     if ( m_data->stepAlignment )
 
  300     if ( std::fabs( m_data->speed ) < 0.001 * m_data->singleStep )
 
  306     if ( 
value != m_data->value )
 
  308         m_data->value = 
value;
 
  311         if ( m_data->tracking || m_data->timerId == 0 )
 
  326 #if QT_VERSION < 0x050e00 
  327     const QPoint wheelPos = 
event->pos();
 
  328     const int wheelDelta = 
event->delta();
 
  330     const QPoint wheelPos = 
event->position().toPoint();
 
  332     const QPoint delta = 
event->angleDelta();
 
  333     const int wheelDelta = ( qAbs( delta.x() ) > qAbs( delta.y() ) )
 
  334         ? delta.x() : delta.y();
 
  343     if ( m_data->isScrolling )
 
  348     double increment = 0.0;
 
  350     if ( ( event->modifiers() & Qt::ControlModifier ) ||
 
  351         ( event->modifiers() & Qt::ShiftModifier ) )
 
  354         increment = m_data->singleStep * m_data->pageStepCount;
 
  355         if ( wheelDelta < 0 )
 
  356             increment = -increment;
 
  360         const int numSteps = wheelDelta / 120;
 
  361         increment = m_data->singleStep * numSteps;
 
  364     if ( m_data->orientation == Qt::Vertical && m_data->inverted )
 
  365         increment = -increment;
 
  367     double value = boundedValue( m_data->value + increment );
 
  369     if ( m_data->stepAlignment )
 
  372     if ( 
value != m_data->value )
 
  374         m_data->value = 
value;
 
  411     if ( m_data->isScrolling )
 
  417     double value = m_data->value;
 
  418     double increment = 0.0;
 
  420     switch ( event->key() )
 
  424             if ( m_data->orientation == Qt::Vertical && m_data->inverted )
 
  425                 increment = m_data->singleStep;
 
  427                 increment = -m_data->singleStep;
 
  433             if ( m_data->orientation == Qt::Vertical && m_data->inverted )
 
  434                 increment = -m_data->singleStep;
 
  436                 increment = m_data->singleStep;
 
  442             if ( m_data->orientation == Qt::Horizontal )
 
  444                 if ( m_data->inverted )
 
  445                     increment = m_data->singleStep;
 
  447                     increment = -m_data->singleStep;
 
  453             if ( m_data->orientation == Qt::Horizontal )
 
  455                 if ( m_data->inverted )
 
  456                     increment = -m_data->singleStep;
 
  458                     increment = m_data->singleStep;
 
  464             increment = m_data->pageStepCount * m_data->singleStep;
 
  467         case Qt::Key_PageDown:
 
  469             increment = -m_data->pageStepCount * m_data->singleStep;
 
  474             value = m_data->minimum;
 
  479             value = m_data->maximum;
 
  488     if ( event->isAccepted() )
 
  491     if ( increment != 0.0 )
 
  493         value = boundedValue( m_data->value + increment );
 
  495         if ( m_data->stepAlignment )
 
  499     if ( 
value != m_data->value )
 
  501         m_data->value = 
value;
 
  521     count = qBound( 6, count, 50 );
 
  523     if ( count != m_data->tickCount )
 
  525         m_data->tickCount = qBound( 6, count, 50 );
 
  536     return m_data->tickCount;
 
  553     const int d = qMin( width(), height() ) / 3;
 
  565     return m_data->wheelBorderWidth;
 
  578     m_data->borderWidth = qMax( width, 0 );
 
  588     return m_data->borderWidth;
 
  596     const int bw = m_data->borderWidth;
 
  597     return contentsRect().adjusted( bw, bw, -bw, -bw );
 
  618     m_data->totalAngle = angle;
 
  628     return m_data->totalAngle;
 
  644     if ( !testAttribute( Qt::WA_WState_OwnSizePolicy ) )
 
  646         QSizePolicy sp = sizePolicy();
 
  650         setAttribute( Qt::WA_WState_OwnSizePolicy, 
false );
 
  663     return m_data->orientation;
 
  678     m_data->viewAngle = qBound( 10.0, angle, 175.0 );
 
  688     return m_data->viewAngle;
 
  702     if ( m_data->orientation == Qt::Vertical )
 
  705         dx = rect.top() - pos.y();
 
  710         dx = pos.x() - rect.left();
 
  716     if ( m_data->inverted )
 
  723     const double ang = dx * m_data->viewAngle / w;
 
  727     const double val = ang * ( 
maximum() - 
minimum() ) / m_data->totalAngle;
 
  738     QPainter painter( 
this );
 
  739     painter.setClipRegion( event->region() );
 
  743     style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, 
this);
 
  745     qDrawShadePanel( &painter,
 
  746         contentsRect(), palette(), 
true, m_data->borderWidth );
 
  762     QPainter* painter, 
const QRectF& rect )
 
  766     QPalette pal = palette();
 
  769     QLinearGradient gradient( rect.topLeft(),
 
  770         ( m_data->orientation == Qt::Horizontal ) ? rect.topRight() : rect.bottomLeft() );
 
  771     gradient.setColorAt( 0.0, pal.color( QPalette::Button ) );
 
  772     gradient.setColorAt( 0.2, pal.color( QPalette::Midlight ) );
 
  773     gradient.setColorAt( 0.7, pal.color( QPalette::Mid ) );
 
  774     gradient.setColorAt( 1.0, pal.color( QPalette::Dark ) );
 
  776     painter->fillRect( rect, gradient );
 
  780     const QPen lightPen( palette().color( QPalette::Light ),
 
  781         m_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap );
 
  782     const QPen darkPen( pal.color( QPalette::Dark ),
 
  783         m_data->wheelBorderWidth, Qt::SolidLine, Qt::FlatCap );
 
  785     const double bw2 = 0.5 * m_data->wheelBorderWidth;
 
  787     if ( m_data->orientation == Qt::Horizontal )
 
  789         painter->setPen( lightPen );
 
  790         painter->drawLine( QPointF( rect.left(), rect.top() + bw2 ),
 
  791             QPointF( rect.right(), rect.top() + bw2 ) );
 
  793         painter->setPen( darkPen );
 
  794         painter->drawLine( QPointF( rect.left(), rect.bottom() - bw2 ),
 
  795             QPointF( rect.right(), rect.bottom() - bw2 ) );
 
  799         painter->setPen( lightPen );
 
  800         painter->drawLine( QPointF( rect.left() + bw2, rect.top() ),
 
  801             QPointF( rect.left() + bw2, rect.bottom() ) );
 
  803         painter->setPen( darkPen );
 
  804         painter->drawLine( QPointF( rect.right() - bw2, rect.top() ),
 
  805             QPointF( rect.right() - bw2, rect.bottom() ) );
 
  819     const double range = m_data->maximum - m_data->minimum;
 
  821     if ( range == 0.0 || m_data->totalAngle == 0.0 )
 
  826     const QPen lightPen( palette().color( QPalette::Light ),
 
  827         0, Qt::SolidLine, Qt::FlatCap );
 
  828     const QPen darkPen( palette().color( QPalette::Dark ),
 
  829         0, Qt::SolidLine, Qt::FlatCap );
 
  831     const double cnvFactor = qAbs( m_data->totalAngle / range );
 
  832     const double halfIntv = 0.5 * m_data->viewAngle / cnvFactor;
 
  833     const double loValue = 
value() - halfIntv;
 
  834     const double hiValue = 
value() + halfIntv;
 
  835     const double tickWidth = 360.0 / double( m_data->tickCount ) / cnvFactor;
 
  836     const double sinArc = qFastSin( m_data->viewAngle * M_PI / 360.0 );
 
  838     if ( m_data->orientation == Qt::Horizontal )
 
  840         const double radius = rect.width() * 0.5;
 
  842         double l1 = rect.top() + m_data->wheelBorderWidth;
 
  843         double l2 = rect.bottom() - m_data->wheelBorderWidth - 1;
 
  846         if ( m_data->wheelBorderWidth > 1 )
 
  852         const double maxpos = rect.right() - 2;
 
  853         const double minpos = rect.left() + 2;
 
  856         for ( 
double tickValue = std::ceil( loValue / tickWidth ) * tickWidth;
 
  857             tickValue < hiValue; tickValue += tickWidth )
 
  859             const double angle = qwtRadians( tickValue - 
value() );
 
  860             const double s = qFastSin( angle * cnvFactor );
 
  862             const double off = radius * ( sinArc + s ) / sinArc;
 
  865             if ( m_data->inverted )
 
  866                 tickPos = rect.left() + off;
 
  868                 tickPos = rect.right() - off;
 
  870             if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) )
 
  872                 painter->setPen( darkPen );
 
  873                 painter->drawLine( QPointF( tickPos - 1, l1 ),
 
  874                     QPointF( tickPos - 1,  l2 ) );
 
  875                 painter->setPen( lightPen );
 
  876                 painter->drawLine( QPointF( tickPos, l1 ),
 
  877                     QPointF( tickPos, l2 ) );
 
  883         const double radius = rect.height() * 0.5;
 
  885         double l1 = rect.left() + m_data->wheelBorderWidth;
 
  886         double l2 = rect.right() - m_data->wheelBorderWidth - 1;
 
  888         if ( m_data->wheelBorderWidth > 1 )
 
  894         const double maxpos = rect.bottom() - 2;
 
  895         const double minpos = rect.top() + 2;
 
  897         for ( 
double tickValue = std::ceil( loValue / tickWidth ) * tickWidth;
 
  898             tickValue < hiValue; tickValue += tickWidth )
 
  900             const double angle = qwtRadians( tickValue - 
value() );
 
  901             const double s = qFastSin( angle * cnvFactor );
 
  903             const double off = radius * ( sinArc + s ) / sinArc;
 
  907             if ( m_data->inverted )
 
  908                 tickPos = rect.bottom() - off;
 
  910                 tickPos = rect.top() + off;
 
  912             if ( ( tickPos <= maxpos ) && ( tickPos > minpos ) )
 
  914                 painter->setPen( darkPen );
 
  915                 painter->drawLine( QPointF( l1, tickPos - 1 ),
 
  916                     QPointF( l2, tickPos - 1 ) );
 
  917                 painter->setPen( lightPen );
 
  918                 painter->drawLine( QPointF( l1, tickPos ),
 
  919                     QPointF( l2, tickPos ) );
 
  936     m_data->wheelWidth = width;
 
  946     return m_data->wheelWidth;
 
  955     return qwtExpandedToGlobalStrut( hint );
 
  964     QSize sz( 3 * m_data->wheelWidth + 2 * m_data->borderWidth,
 
  965         m_data->wheelWidth + 2 * m_data->borderWidth );
 
  966     if ( m_data->orientation != Qt::Horizontal )
 
  982     m_data->singleStep = qwtMaxF( stepSize, 0.0 );
 
  991     return m_data->singleStep;
 
 1006     if ( on != m_data->stepAlignment )
 
 1008         m_data->stepAlignment = on;
 
 1018     return m_data->stepAlignment;
 
 1036     m_data->pageStepCount = qMax( 0, count );
 
 1045     return m_data->pageStepCount;
 
 1061     max = qwtMaxF( min, max );
 
 1063     if ( m_data->minimum == min && m_data->maximum == max )
 
 1066     m_data->minimum = min;
 
 1067     m_data->maximum = max;
 
 1069     if ( m_data->value < min || m_data->value > max )
 
 1071         m_data->value = qBound( min, m_data->value, max );
 
 1096     return m_data->minimum;
 
 1116     return m_data->maximum;
 
 1130     m_data->isScrolling = 
false;
 
 1132     value = qBound( m_data->minimum, 
value, m_data->maximum );
 
 1134     if ( m_data->value != 
value )
 
 1136         m_data->value = 
value;
 
 1149     return m_data->value;
 
 1165     if ( m_data->inverted != on )
 
 1167         m_data->inverted = on;
 
 1178     return m_data->inverted;
 
 1192     m_data->wrapping = on;
 
 1201     return m_data->wrapping;
 
 1229         m_data->mass = qwtMinF( 100.0, 
mass );
 
 1232     if ( m_data->mass <= 0.0 )
 
 1242     return m_data->mass;
 
 1248     if ( m_data->timerId != 0 )
 
 1250         killTimer( m_data->timerId );
 
 1251         m_data->timerId = 0;
 
 1252         m_data->speed = 0.0;
 
 1256 double QwtWheel::boundedValue( 
double value )
 const 
 1258     const double range = m_data->maximum - m_data->minimum;
 
 1260     if ( m_data->wrapping && range >= 0.0 )
 
 1262         if ( value < m_data->
minimum )
 
 1264             value += std::ceil( ( m_data->minimum - 
value ) / range ) * range;
 
 1266         else if ( 
value > m_data->maximum )
 
 1268             value -= std::ceil( ( 
value - m_data->maximum ) / range ) * range;
 
 1273         value = qBound( m_data->minimum, 
value, m_data->maximum );
 
 1279 double QwtWheel::alignedValue( 
double value )
 const 
 1281     const double stepSize = m_data->singleStep;
 
 1283     if ( stepSize > 0.0 )
 
 1285         value = m_data->minimum +
 
 1286             qRound( ( 
value - m_data->minimum ) / stepSize ) * stepSize;
 
 1288         if ( stepSize > 1e-12 )
 
 1290             if ( qFuzzyCompare( 
value + 1.0, 1.0 ) )
 
 1295             else if ( qFuzzyCompare( 
value, m_data->maximum ) )
 
 1298                 value = m_data->maximum;
 
 1307 #include "moc_qwt_wheel.cpp" 
static void drawFocusRect(QPainter *, const QWidget *)
Draw a focus rectangle on a widget using its style.
virtual void paintEvent(QPaintEvent *) override
Qt Paint Event.
virtual void wheelEvent(QWheelEvent *) override
Handle wheel events.
Qt::Orientation orientation() const
bool stepAlignment() const
virtual QSize sizeHint() const override
void setMass(double)
Set the slider's mass for flywheel effect.
virtual void drawWheelBackground(QPainter *, const QRectF &)
virtual QSize minimumSizeHint() const override
void setTracking(bool)
En/Disable tracking.
virtual void mouseReleaseEvent(QMouseEvent *) override
Mouse Release Event handler.
void setWheelBorderWidth(int)
Set the wheel border width of the wheel.
void setBorderWidth(int)
Set the border width.
void setRange(double min, double max)
Set the minimum and maximum values.
virtual ~QwtWheel()
Destructor.
int updateInterval() const
virtual void timerEvent(QTimerEvent *) override
Qt timer event.
void setUpdateInterval(int)
Specify the update interval when the wheel is flying.
void setStepAlignment(bool on)
En/Disable step alignment.
virtual void mouseMoveEvent(QMouseEvent *) override
Mouse Move Event handler.
void setSingleStep(double)
Set the step size of the counter.
void setValue(double)
Set a new value without adjusting to the step raster.
void wheelMoved(double value)
int pageStepCount() const
void setViewAngle(double)
Specify the visible portion of the wheel.
virtual void mousePressEvent(QMouseEvent *) override
Mouse press event handler.
QwtWheel(QWidget *parent=NULL)
Constructor.
int wheelBorderWidth() const
virtual double valueAt(const QPoint &) const
virtual void drawTicks(QPainter *, const QRectF &)
void setWheelWidth(int)
Set the width of the wheel.
void setOrientation(Qt::Orientation)
Set the wheel's orientation.
void valueChanged(double value)
Notify a change of value.
void setPageStepCount(int)
Set the page step count.
void setTickCount(int)
Adjust the number of grooves in the wheel's surface.
virtual void keyPressEvent(QKeyEvent *) override
void setTotalAngle(double)
Set the total angle which the wheel can be turned.
void setWrapping(bool)
En/Disable wrapping.
double totalAngle() const
double singleStep() const
void stopFlying()
Stop the flying movement of the wheel.
void setInverted(bool)
En/Disable inverted appearance.