# qwt_abstract_slider.cpp

    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 <qevent.h>
    00011 #include <qdatetime.h>
    00012 #include "qwt_abstract_slider.h"
    00013 #include "qwt_math.h"
    00014
    00015 #ifndef WHEEL_DELTA
    00016 #define WHEEL_DELTA 120
    00017 #endif
    00018
    00019 class QwtAbstractSlider::PrivateData
    00020 {
    00021 public:
    00022     PrivateData():
    00023         scrollMode(ScrNone),
    00024         mouseOffset(0.0),
    00025         tracking(true),
    00026         tmrID(0),
    00027         updTime(150),
    00028         mass(0.0),
    00029         readOnly(false)
    00030     {
    00031     }
    00032
    00033     int scrollMode;
    00034     double mouseOffset;
    00035     int direction;
    00036     int tracking;
    00037
    00038     int tmrID;
    00039     int updTime;
    00040     int timerTick;
    00041     QTime time;
    00042     double speed;
    00043     double mass;
    00044     Qt::Orientation orientation;
    00045     bool readOnly;
    00046 };
    00047
    00054 QwtAbstractSlider::QwtAbstractSlider(
    00055         Qt::Orientation orientation, QWidget *parent):
    00056     QWidget(parent, NULL)
    00057 {
    00058     d_data = new QwtAbstractSlider::PrivateData;
    00059     d_data->orientation = orientation;
    00060
    00061 #if QT_VERSION >= 0x040000
    00062     using namespace Qt;
    00063 #endif
    00064     setFocusPolicy(TabFocus);
    00065 }
    00066
    00068 QwtAbstractSlider::~QwtAbstractSlider()
    00069 {
    00070     if(d_data->tmrID)
    00071         killTimer(d_data->tmrID);
    00072
    00073     delete d_data;
    00074 }
    00075
    00085 void QwtAbstractSlider::setReadOnly(bool readOnly)
    00086 {
    00087     d_data->readOnly = readOnly;
    00088     update();
    00089 }
    00090
    00098 bool QwtAbstractSlider::isReadOnly() const
    00099 {
    00100     return d_data->readOnly;
    00101 }
    00102
    00108 void QwtAbstractSlider::setOrientation(Qt::Orientation o)
    00109 {
    00110     d_data->orientation = o;
    00111 }
    00112
    00117 Qt::Orientation QwtAbstractSlider::orientation() const
    00118 {
    00119     return d_data->orientation;
    00120 }
    00121
    00123
    00124 void QwtAbstractSlider::stopMoving()
    00125 {
    00126     if(d_data->tmrID)
    00127     {
    00128         killTimer(d_data->tmrID);
    00129         d_data->tmrID = 0;
    00130     }
    00131 }
    00132
    00138 void QwtAbstractSlider::setUpdateTime(int t)
    00139 {
    00140     if (t < 50)
    00141         t = 50;
    00142     d_data->updTime = t;
    00143 }
    00144
    00145
    00147 void QwtAbstractSlider::mousePressEvent(QMouseEvent *e)
    00148 {
    00149     if ( isReadOnly() )
    00150     {
    00151         e->ignore();
    00152         return;
    00153     }
    00154     if ( !isValid() )
    00155         return;
    00156
    00157     const QPoint &p = e->pos();
    00158
    00159     d_data->timerTick = 0;
    00160
    00161     getScrollMode(p, d_data->scrollMode, d_data->direction);
    00162     stopMoving();
    00163
    00164     switch(d_data->scrollMode)
    00165     {
    00166         case ScrPage:
    00167         case ScrTimer:
    00168             d_data->mouseOffset = 0;
    00169             d_data->tmrID = startTimer(qwtMax(250, 2 * d_data->updTime));
    00170             break;
    00171
    00172         case ScrMouse:
    00173             d_data->time.start();
    00174             d_data->speed = 0;
    00175             d_data->mouseOffset = getValue(p) - value();
    00176             emit sliderPressed();
    00177             break;
    00178
    00179         default:
    00180             d_data->mouseOffset = 0;
    00181             d_data->direction = 0;
    00182             break;
    00183     }
    00184 }
    00185
    00186
    00188 void QwtAbstractSlider::buttonReleased()
    00189 {
    00190     if ((!d_data->tracking) || (value() != prevValue()))
    00191         emit valueChanged(value());
    00192 }
    00193
    00194
    00196 void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e)
    00197 {
    00198     if ( isReadOnly() )
    00199     {
    00200         e->ignore();
    00201         return;
    00202     }
    00203     if ( !isValid() )
    00204         return;
    00205
    00206     const double inc = step();
    00207
    00208     switch(d_data->scrollMode)
    00209     {
    00210         case ScrMouse:
    00211         {
    00212             setPosition(e->pos());
    00213             d_data->direction = 0;
    00214             d_data->mouseOffset = 0;
    00215             if (d_data->mass > 0.0)
    00216             {
    00217                 const int ms = d_data->time.elapsed();
    00218                 if ((fabs(d_data->speed) >  0.0) && (ms < 50))
    00219                     d_data->tmrID = startTimer(d_data->updTime);
    00220             }
    00221             else
    00222             {
    00223                 d_data->scrollMode = ScrNone;
    00224                 buttonReleased();
    00225             }
    00226             emit sliderReleased();
    00227
    00228             break;
    00229         }
    00230
    00231         case ScrDirect:
    00232         {
    00233             setPosition(e->pos());
    00234             d_data->direction = 0;
    00235             d_data->mouseOffset = 0;
    00236             d_data->scrollMode = ScrNone;
    00237             buttonReleased();
    00238             break;
    00239         }
    00240
    00241         case ScrPage:
    00242         {
    00243             stopMoving();
    00244             if (!d_data->timerTick)
    00245                 QwtDoubleRange::incPages(d_data->direction);
    00246             d_data->timerTick = 0;
    00247             buttonReleased();
    00248             d_data->scrollMode = ScrNone;
    00249             break;
    00250         }
    00251
    00252         case ScrTimer:
    00253         {
    00254             stopMoving();
    00255             if (!d_data->timerTick)
    00256                 QwtDoubleRange::fitValue(value() + double(d_data->direction) * inc);
    00257             d_data->timerTick = 0;
    00258             buttonReleased();
    00259             d_data->scrollMode = ScrNone;
    00260             break;
    00261         }
    00262
    00263         default:
    00264         {
    00265             d_data->scrollMode = ScrNone;
    00266             buttonReleased();
    00267         }
    00268     }
    00269 }
    00270
    00271
    00276 void QwtAbstractSlider::setPosition(const QPoint &p)
    00277 {
    00278     QwtDoubleRange::fitValue(getValue(p) - d_data->mouseOffset);
    00279 }
    00280
    00281
    00296 void QwtAbstractSlider::setTracking(bool enable)
    00297 {
    00298     d_data->tracking = enable;
    00299 }
    00300
    00305 void QwtAbstractSlider::mouseMoveEvent(QMouseEvent *e)
    00306 {
    00307     if ( isReadOnly() )
    00308     {
    00309         e->ignore();
    00310         return;
    00311     }
    00312
    00313     if ( !isValid() )
    00314         return;
    00315
    00316     if (d_data->scrollMode == ScrMouse )
    00317     {
    00318         setPosition(e->pos());
    00319         if (d_data->mass > 0.0)
    00320         {
    00321             double ms = double(d_data->time.elapsed());
    00322             if (ms < 1.0)
    00323                 ms = 1.0;
    00324             d_data->speed = (exactValue() - exactPrevValue()) / ms;
    00325             d_data->time.start();
    00326         }
    00327         if (value() != prevValue())
    00328             emit sliderMoved(value());
    00329     }
    00330 }
    00331
    00336 void QwtAbstractSlider::wheelEvent(QWheelEvent *e)
    00337 {
    00338     if ( isReadOnly() )
    00339     {
    00340         e->ignore();
    00341         return;
    00342     }
    00343
    00344     if ( !isValid() )
    00345         return;
    00346
    00347     int mode = ScrNone, direction = 0;
    00348
    00349     // Give derived classes a chance to say ScrNone
    00350     getScrollMode(e->pos(), mode, direction);
    00351     if ( mode != ScrNone )
    00352     {
    00353         const int inc = e->delta() / WHEEL_DELTA;
    00354         QwtDoubleRange::incPages(inc);
    00355         if (value() != prevValue())
    00356             emit sliderMoved(value());
    00357     }
    00358 }
    00359
    00371 void QwtAbstractSlider::keyPressEvent(QKeyEvent *e)
    00372 {
    00373     if ( isReadOnly() )
    00374     {
    00375         e->ignore();
    00376         return;
    00377     }
    00378
    00379     if ( !isValid() )
    00380         return;
    00381
    00382     int increment = 0;
    00383     switch ( e->key() )
    00384     {
    00385         case Qt::Key_Down:
    00386             if ( orientation() == Qt::Vertical )
    00387                 increment = -1;
    00388             break;
    00389         case Qt::Key_Up:
    00390             if ( orientation() == Qt::Vertical )
    00391                 increment = 1;
    00392             break;
    00393         case Qt::Key_Left:
    00394             if ( orientation() == Qt::Horizontal )
    00395                 increment = -1;
    00396             break;
    00397         case Qt::Key_Right:
    00398             if ( orientation() == Qt::Horizontal )
    00399                 increment = 1;
    00400             break;
    00401         default:;
    00402             e->ignore();
    00403     }
    00404
    00405     if ( increment != 0 )
    00406     {
    00407         QwtDoubleRange::incValue(increment);
    00408         if (value() != prevValue())
    00409             emit sliderMoved(value());
    00410     }
    00411 }
    00412
    00417 void QwtAbstractSlider::timerEvent(QTimerEvent *)
    00418 {
    00419     const double inc = step();
    00420
    00421     switch (d_data->scrollMode)
    00422     {
    00423         case ScrMouse:
    00424         {
    00425             if (d_data->mass > 0.0)
    00426             {
    00427                 d_data->speed *= exp( - double(d_data->updTime) * 0.001 / d_data->mass );
    00428                 const double newval =
    00429                     exactValue() + d_data->speed * double(d_data->updTime);
    00430                 QwtDoubleRange::fitValue(newval);
    00431                 // stop if d_data->speed < one step per second
    00432                 if (fabs(d_data->speed) < 0.001 * fabs(step()))
    00433                 {
    00434                     d_data->speed = 0;
    00435                     stopMoving();
    00436                     buttonReleased();
    00437                 }
    00438
    00439             }
    00440             else
    00441                stopMoving();
    00442             break;
    00443         }
    00444
    00445         case ScrPage:
    00446         {
    00447             QwtDoubleRange::incPages(d_data->direction);
    00448             if (!d_data->timerTick)
    00449             {
    00450                 killTimer(d_data->tmrID);
    00451                 d_data->tmrID = startTimer(d_data->updTime);
    00452             }
    00453             break;
    00454         }
    00455         case ScrTimer:
    00456         {
    00457             QwtDoubleRange::fitValue(value() +  double(d_data->direction) * inc);
    00458             if (!d_data->timerTick)
    00459             {
    00460                 killTimer(d_data->tmrID);
    00461                 d_data->tmrID = startTimer(d_data->updTime);
    00462             }
    00463             break;
    00464         }
    00465         default:
    00466         {
    00467             stopMoving();
    00468             break;
    00469         }
    00470     }
    00471
    00472     d_data->timerTick = 1;
    00473 }
    00474
    00475
    00484 void QwtAbstractSlider::valueChange()
    00485 {
    00486     if (d_data->tracking)
    00487        emit valueChanged(value());
    00488 }
    00489
    00507 void QwtAbstractSlider::setMass(double val)
    00508 {
    00509     if (val < 0.001)
    00510        d_data->mass = 0.0;
    00511     else if (val > 100.0)
    00512        d_data->mass = 100.0;
    00513     else
    00514        d_data->mass = val;
    00515 }
    00516
    00521 double QwtAbstractSlider::mass() const
    00522 {
    00523     return d_data->mass;
    00524 }
    00525
    00526
    00535 void QwtAbstractSlider::setValue(double val)
    00536 {
    00537     if (d_data->scrollMode == ScrMouse)
    00538         stopMoving();
    00539     QwtDoubleRange::setValue(val);
    00540 }
    00541
    00542
    00550 void QwtAbstractSlider::fitValue(double value)
    00551 {
    00552     if (d_data->scrollMode == ScrMouse)
    00553         stopMoving();
    00554     QwtDoubleRange::fitValue(value);
    00555 }
    00556
    00562 void QwtAbstractSlider::incValue(int steps)
    00563 {
    00564     if (d_data->scrollMode == ScrMouse)
    00565         stopMoving();
    00566     QwtDoubleRange::incValue(steps);
    00567 }
    00568
    00569 void QwtAbstractSlider::setMouseOffset(double offset)
    00570 {
    00571     d_data->mouseOffset = offset;
    00572 }
    00573
    00574 double QwtAbstractSlider::mouseOffset() const
    00575 {
    00576     return d_data->mouseOffset;
    00577 }
    00578
    00579 int QwtAbstractSlider::scrollMode() const
    00580 {
    00581     return d_data->scrollMode;
    00582 }