| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 | 
							- /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 
-  * Qwt Widget Library
 
-  * Copyright (C) 1997   Josef Wilgen
 
-  * Copyright (C) 2002   Uwe Rathmann
 
-  *
 
-  * This library is free software; you can redistribute it and/or
 
-  * modify it under the terms of the Qwt License, Version 1.0
 
-  *****************************************************************************/
 
- #include "qwt_knob.h"
 
- #include "qwt_round_scale_draw.h"
 
- #include "qwt_math.h"
 
- #include "qwt_painter.h"
 
- #include <qpainter.h>
 
- #include <qpalette.h>
 
- #include <qstyle.h>
 
- #include <qevent.h>
 
- #include <qmath.h>
 
- #if QT_VERSION < 0x040601
 
- #define qAtan2(y, x) ::atan2(y, x)
 
- #define qFabs(x) ::fabs(x)
 
- #define qFastCos(x) ::cos(x)
 
- #define qFastSin(x) ::sin(x)
 
- #endif
 
- class QwtKnob::PrivateData
 
- {
 
- public:
 
-     PrivateData()
 
-     {
 
-         angle = 0.0;
 
-         nTurns = 0.0;
 
-         borderWidth = 2;
 
-         borderDist = 4;
 
-         totalAngle = 270.0;
 
-         scaleDist = 4;
 
-         symbol = Line;
 
-         maxScaleTicks = 11;
 
-         knobWidth = 50;
 
-         dotWidth = 8;
 
-     }
 
-     int borderWidth;
 
-     int borderDist;
 
-     int scaleDist;
 
-     int maxScaleTicks;
 
-     int knobWidth;
 
-     int dotWidth;
 
-     Symbol symbol;
 
-     double angle;
 
-     double totalAngle;
 
-     double nTurns;
 
-     QRect knobRect; // bounding rect of the knob without scale
 
- };
 
- /*!
 
-   Constructor
 
-   \param parent Parent widget
 
- */
 
- QwtKnob::QwtKnob( QWidget* parent ):
 
-     QwtAbstractSlider( Qt::Horizontal, parent )
 
- {
 
-     initKnob();
 
- }
 
- void QwtKnob::initKnob()
 
- {
 
-     d_data = new PrivateData;
 
-     setScaleDraw( new QwtRoundScaleDraw() );
 
-     setUpdateTime( 50 );
 
-     setTotalAngle( 270.0 );
 
-     recalcAngle();
 
-     setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
 
-     setRange( 0.0, 10.0, 1.0 );
 
-     setValue( 0.0 );
 
- }
 
- //! Destructor
 
- QwtKnob::~QwtKnob()
 
- {
 
-     delete d_data;
 
- }
 
- /*!
 
-   \brief Set the symbol of the knob
 
-   \sa symbol()
 
- */
 
- void QwtKnob::setSymbol( QwtKnob::Symbol s )
 
- {
 
-     if ( d_data->symbol != s )
 
-     {
 
-         d_data->symbol = s;
 
-         update();
 
-     }
 
- }
 
- /*!
 
-     \return symbol of the knob
 
-     \sa setSymbol()
 
- */
 
- QwtKnob::Symbol QwtKnob::symbol() const
 
- {
 
-     return d_data->symbol;
 
- }
 
- /*!
 
-   \brief Set the total angle by which the knob can be turned
 
-   \param angle Angle in degrees.
 
-   The default angle is 270 degrees. It is possible to specify
 
-   an angle of more than 360 degrees so that the knob can be
 
-   turned several times around its axis.
 
- */
 
- void QwtKnob::setTotalAngle ( double angle )
 
- {
 
-     if ( angle < 10.0 )
 
-         d_data->totalAngle = 10.0;
 
-     else
 
-         d_data->totalAngle = angle;
 
-     scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle,
 
-         0.5 * d_data->totalAngle );
 
-     layoutKnob();
 
- }
 
- //! Return the total angle
 
- double QwtKnob::totalAngle() const
 
- {
 
-     return d_data->totalAngle;
 
- }
 
- /*!
 
-    Change the scale draw of the knob
 
-    For changing the labels of the scales, it
 
-    is necessary to derive from QwtRoundScaleDraw and
 
-    overload QwtRoundScaleDraw::label().
 
-    \sa scaleDraw()
 
- */
 
- void QwtKnob::setScaleDraw( QwtRoundScaleDraw *scaleDraw )
 
- {
 
-     setAbstractScaleDraw( scaleDraw );
 
-     setTotalAngle( d_data->totalAngle );
 
- }
 
- /*!
 
-    \return the scale draw of the knob
 
-    \sa setScaleDraw()
 
- */
 
- const QwtRoundScaleDraw *QwtKnob::scaleDraw() const
 
- {
 
-     return static_cast<const QwtRoundScaleDraw *>( abstractScaleDraw() );
 
- }
 
- /*!
 
-    \return the scale draw of the knob
 
-    \sa setScaleDraw()
 
- */
 
- QwtRoundScaleDraw *QwtKnob::scaleDraw()
 
- {
 
-     return static_cast<QwtRoundScaleDraw *>( abstractScaleDraw() );
 
- }
 
- /*!
 
-   \brief Draw the knob
 
-   \param painter painter
 
-   \param r Bounding rectangle of the knob (without scale)
 
- */
 
- void QwtKnob::drawKnob( QPainter *painter, const QRect &r )
 
- {
 
-     const QBrush buttonBrush = palette().brush( QPalette::Button );
 
-     const QColor buttonTextColor = palette().color( QPalette::ButtonText );
 
-     const QColor lightColor = palette().color( QPalette::Light );
 
-     const QColor darkColor = palette().color( QPalette::Dark );
 
-     const int bw2 = d_data->borderWidth / 2;
 
-     const int radius = ( qMin( r.width(), r.height() ) - bw2 ) / 2;
 
-     const QRect aRect(
 
-         r.center().x() - radius, r.center().y() - radius,
 
-         2 * radius, 2 * radius );
 
-     //
 
-     // draw button face
 
-     //
 
-     painter->setBrush( buttonBrush );
 
-     painter->drawEllipse( aRect );
 
-     //
 
-     // draw button shades
 
-     //
 
-     QPen pn;
 
-     pn.setWidth( d_data->borderWidth );
 
-     pn.setColor( lightColor );
 
-     painter->setPen( pn );
 
-     painter->drawArc( aRect, 45*16, 180*16 );
 
-     pn.setColor( darkColor );
 
-     painter->setPen( pn );
 
-     painter->drawArc( aRect, 225*16, 180*16 );
 
-     //
 
-     // draw marker
 
-     //
 
-     if ( isValid() )
 
-         drawMarker( painter, d_data->angle, buttonTextColor );
 
- }
 
- /*!
 
-   \brief Notify change of value
 
-   Sets the knob's value to the nearest multiple
 
-   of the step size.
 
- */
 
- void QwtKnob::valueChange()
 
- {
 
-     recalcAngle();
 
-     update();
 
-     QwtAbstractSlider::valueChange();
 
- }
 
- /*!
 
-   \brief Determine the value corresponding to a specified position
 
-   Called by QwtAbstractSlider
 
-   \param p point
 
- */
 
- double QwtKnob::getValue( const QPoint &p )
 
- {
 
-     const double dx = double( ( rect().x() + rect().width() / 2 ) - p.x() );
 
-     const double dy = double( ( rect().y() + rect().height() / 2 ) - p.y() );
 
-     const double arc = qAtan2( -dx, dy ) * 180.0 / M_PI;
 
-     double newValue =  0.5 * ( minValue() + maxValue() )
 
-         + ( arc + d_data->nTurns * 360.0 ) * ( maxValue() - minValue() )
 
-         / d_data->totalAngle;
 
-     const double oneTurn = qFabs( maxValue() - minValue() ) * 360.0 / d_data->totalAngle;
 
-     const double eqValue = value() + mouseOffset();
 
-     if ( qFabs( newValue - eqValue ) > 0.5 * oneTurn )
 
-     {
 
-         if ( newValue < eqValue )
 
-             newValue += oneTurn;
 
-         else
 
-             newValue -= oneTurn;
 
-     }
 
-     return newValue;
 
- }
 
- /*!
 
-   \brief Set the scrolling mode and direction
 
-   Called by QwtAbstractSlider
 
-   \param p Point in question
 
- */
 
- void QwtKnob::getScrollMode( const QPoint &p, int &scrollMode, int &direction )
 
- {
 
-     const int r = d_data->knobRect.width() / 2;
 
-     const int dx = d_data->knobRect.x() + r - p.x();
 
-     const int dy = d_data->knobRect.y() + r - p.y();
 
-     if ( ( dx * dx ) + ( dy * dy ) <= ( r * r ) ) // point is inside the knob
 
-     {
 
-         scrollMode = ScrMouse;
 
-         direction = 0;
 
-     }
 
-     else                                // point lies outside
 
-     {
 
-         scrollMode = ScrTimer;
 
-         double arc = qAtan2( double( -dx ), double( dy ) ) * 180.0 / M_PI;
 
-         if ( arc < d_data->angle )
 
-             direction = -1;
 
-         else if ( arc > d_data->angle )
 
-             direction = 1;
 
-         else
 
-             direction = 0;
 
-     }
 
- }
 
- /*!
 
-   \brief Notify a change of the range
 
-   Called by QwtAbstractSlider
 
- */
 
- void QwtKnob::rangeChange()
 
- {
 
-     if ( autoScale() )
 
-         rescale( minValue(), maxValue() );
 
-     layoutKnob();
 
-     recalcAngle();
 
- }
 
- /*!
 
-   Qt Resize Event
 
- */
 
- void QwtKnob::resizeEvent( QResizeEvent * )
 
- {
 
-     layoutKnob( false );
 
- }
 
- /*!
 
-    Recalculate the knob's geometry and layout based on
 
-    the current rect and fonts.
 
-    \param update_geometry notify the layout system and call update
 
-                           to redraw the scale
 
- */
 
- void QwtKnob::layoutKnob( bool update_geometry )
 
- {
 
-     const QRect r = rect();
 
-     const int radius = d_data->knobWidth / 2;
 
-     d_data->knobRect.setWidth( 2 * radius );
 
-     d_data->knobRect.setHeight( 2 * radius );
 
-     d_data->knobRect.moveCenter( r.center() );
 
-     scaleDraw()->setRadius( radius + d_data->scaleDist );
 
-     scaleDraw()->moveCenter( r.center() );
 
-     if ( update_geometry )
 
-     {
 
-         updateGeometry();
 
-         update();
 
-     }
 
- }
 
- /*!
 
-   Repaint the knob
 
-   \param e Paint event
 
- */
 
- void QwtKnob::paintEvent( QPaintEvent *e )
 
- {
 
-     const QRect &ur = e->rect();
 
-     if ( ur.isValid() )
 
-     {
 
-         QPainter painter( this );
 
-         painter.setRenderHint( QPainter::Antialiasing );
 
-         draw( &painter, ur );
 
-     }
 
- }
 
- /*!
 
-   Repaint the knob
 
-   \param painter Painter
 
-   \param rect Update rectangle
 
- */
 
- void QwtKnob::draw( QPainter *painter, const QRect& rect )
 
- {
 
-     if ( !d_data->knobRect.contains( rect ) ) // event from valueChange()
 
-         scaleDraw()->draw( painter, palette() );
 
-     drawKnob( painter, d_data->knobRect );
 
-     if ( hasFocus() )
 
-         QwtPainter::drawFocusRect( painter, this, rect );
 
- }
 
- /*!
 
-   \brief Draw the marker at the knob's front
 
-   \param p Painter
 
-   \param arc Angle of the marker
 
-   \param c Marker color
 
- */
 
- void QwtKnob::drawMarker( QPainter *p, double arc, const QColor &c )
 
- {
 
-     const double rarc = arc * M_PI / 180.0;
 
-     const double ca = qFastCos( rarc );
 
-     const double sa = - qFastSin( rarc );
 
-     int radius = d_data->knobRect.width() / 2 - d_data->borderWidth;
 
-     if ( radius < 3 )
 
-         radius = 3;
 
-     const int ym = d_data->knobRect.y() + radius + d_data->borderWidth;
 
-     const int xm = d_data->knobRect.x() + radius + d_data->borderWidth;
 
-     switch ( d_data->symbol )
 
-     {
 
-         case Dot:
 
-         {
 
-             p->setBrush( c );
 
-             p->setPen( Qt::NoPen );
 
-             const double rb = double( qMax( radius - 4 - d_data->dotWidth / 2, 0 ) );
 
-             p->drawEllipse( xm - qRound( sa * rb ) - d_data->dotWidth / 2,
 
-                 ym - qRound( ca * rb ) - d_data->dotWidth / 2,
 
-                 d_data->dotWidth, d_data->dotWidth );
 
-             break;
 
-         }
 
-         case Line:
 
-         {
 
-             p->setPen( QPen( c, 2 ) );
 
-             const double rb = qMax( double( ( radius - 4 ) / 3.0 ), 0.0 );
 
-             const double re = qMax( double( radius - 4 ), 0.0 );
 
-             p->drawLine ( xm - qRound( sa * rb ), ym - qRound( ca * rb ),
 
-                 xm - qRound( sa * re ), ym - qRound( ca * re ) );
 
-             break;
 
-         }
 
-     }
 
- }
 
- /*!
 
-   \brief Change the knob's width.
 
-   The specified width must be >= 5, or it will be clipped.
 
-   \param w New width
 
- */
 
- void QwtKnob::setKnobWidth( int w )
 
- {
 
-     d_data->knobWidth = qMax( w, 5 );
 
-     layoutKnob();
 
- }
 
- //! Return the width of the knob
 
- int QwtKnob::knobWidth() const
 
- {
 
-     return d_data->knobWidth;
 
- }
 
- /*!
 
-   \brief Set the knob's border width
 
-   \param bw new border width
 
- */
 
- void QwtKnob::setBorderWidth( int bw )
 
- {
 
-     d_data->borderWidth = qMax( bw, 0 );
 
-     layoutKnob();
 
- }
 
- //! Return the border width
 
- int QwtKnob::borderWidth() const
 
- {
 
-     return d_data->borderWidth;
 
- }
 
- /*!
 
-   \brief Recalculate the marker angle corresponding to the
 
-     current value
 
- */
 
- void QwtKnob::recalcAngle()
 
- {
 
-     //
 
-     // calculate the angle corresponding to the value
 
-     //
 
-     if ( maxValue() == minValue() )
 
-     {
 
-         d_data->angle = 0;
 
-         d_data->nTurns = 0;
 
-     }
 
-     else
 
-     {
 
-         d_data->angle = ( value() - 0.5 * ( minValue() + maxValue() ) )
 
-             / ( maxValue() - minValue() ) * d_data->totalAngle;
 
-         d_data->nTurns = qFloor( ( d_data->angle + 180.0 ) / 360.0 );
 
-         d_data->angle = d_data->angle - d_data->nTurns * 360.0;
 
-     }
 
- }
 
- /*!
 
-     Recalculates the layout
 
-     \sa layoutKnob()
 
- */
 
- void QwtKnob::scaleChange()
 
- {
 
-     layoutKnob();
 
- }
 
- /*!
 
-     Recalculates the layout
 
-     \sa layoutKnob()
 
- */
 
- void QwtKnob::fontChange( const QFont &f )
 
- {
 
-     QwtAbstractSlider::fontChange( f );
 
-     layoutKnob();
 
- }
 
- /*!
 
-   \return minimumSizeHint()
 
- */
 
- QSize QwtKnob::sizeHint() const
 
- {
 
-     return minimumSizeHint();
 
- }
 
- /*!
 
-   \brief Return a minimum size hint
 
-   \warning The return value of QwtKnob::minimumSizeHint() depends on the
 
-            font and the scale.
 
- */
 
- QSize QwtKnob::minimumSizeHint() const
 
- {
 
-     // Add the scale radial thickness to the knobWidth
 
-     const int sh = qCeil( scaleDraw()->extent( font() ) );
 
-     const int d = 2 * sh + 2 * d_data->scaleDist + d_data->knobWidth;
 
-     return QSize( d, d );
 
- }
 
 
  |