Logo Search packages:      
Sourcecode: pcp-gui version File versions

qwt_abstract_slider.cpp

/* -*- 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 <qevent.h>
#include <qdatetime.h>
#include "qwt_abstract_slider.h"
#include "qwt_math.h"

#ifndef WHEEL_DELTA
#define WHEEL_DELTA 120
#endif

class QwtAbstractSlider::PrivateData
{
public:
    PrivateData():
        scrollMode(ScrNone),
        mouseOffset(0.0),
        tracking(true),
        tmrID(0),
        updTime(150),
        mass(0.0),
        readOnly(false)
    {
    }

    int scrollMode;
    double mouseOffset;
    int direction;
    int tracking;

    int tmrID;
    int updTime;
    int timerTick;
    QTime time;
    double speed;
    double mass;
    Qt::Orientation orientation;
    bool readOnly;
};

/*! 
   \brief Constructor

   \param orientation Orientation
   \param parent Parent widget
*/
00054 QwtAbstractSlider::QwtAbstractSlider(
        Qt::Orientation orientation, QWidget *parent): 
    QWidget(parent, NULL)
{
    d_data = new QwtAbstractSlider::PrivateData;
    d_data->orientation = orientation;

#if QT_VERSION >= 0x040000
    using namespace Qt;
#endif
    setFocusPolicy(TabFocus);
}

//! Destructor
00068 QwtAbstractSlider::~QwtAbstractSlider()
{
    if(d_data->tmrID) 
        killTimer(d_data->tmrID);

    delete d_data;
}

/*!
  En/Disable read only mode

  In read only mode the slider can't be controlled by mouse
  or keyboard.

  \param readOnly Enables in case of true
  \sa isReadOnly()
*/
00085 void QwtAbstractSlider::setReadOnly(bool readOnly)
{
    d_data->readOnly = readOnly;
    update();
}

/*!
  In read only mode the slider can't be controlled by mouse
  or keyboard.

  \return true if read only
  \sa setReadOnly()
*/
00098 bool QwtAbstractSlider::isReadOnly() const
{
    return d_data->readOnly;
}

/*!
  \brief Set the orientation.
  \param o Orientation. Allowed values are
           Qt::Horizontal and Qt::Vertical.
*/
void QwtAbstractSlider::setOrientation(Qt::Orientation o)
{
    d_data->orientation = o;
}

/*! 
  \return Orientation
  \sa setOrientation()
*/
Qt::Orientation QwtAbstractSlider::orientation() const
{
    return d_data->orientation;
}

//! Stop updating if automatic scrolling is active

00124 void QwtAbstractSlider::stopMoving() 
{
    if(d_data->tmrID)
    {
        killTimer(d_data->tmrID);
        d_data->tmrID = 0;
    }
}

/*!
  \brief Specify the update interval for automatic scrolling
  \param t update interval in milliseconds
  \sa getScrollMode()
*/
00138 void QwtAbstractSlider::setUpdateTime(int t) 
{
    if (t < 50) 
        t = 50;
    d_data->updTime = t;
}


//! Mouse press event handler
00147 void QwtAbstractSlider::mousePressEvent(QMouseEvent *e) 
{
    if ( isReadOnly() )
    {
        e->ignore();
        return;
    }
    if ( !isValid() )
        return;

    const QPoint &p = e->pos();

    d_data->timerTick = 0;

    getScrollMode(p, d_data->scrollMode, d_data->direction);
    stopMoving();
    
    switch(d_data->scrollMode)
    {
        case ScrPage:
        case ScrTimer:
            d_data->mouseOffset = 0;
            d_data->tmrID = startTimer(qwtMax(250, 2 * d_data->updTime));
            break;
        
        case ScrMouse:
            d_data->time.start();
            d_data->speed = 0;
            d_data->mouseOffset = getValue(p) - value();
            emit sliderPressed();
            break;
        
        default:
            d_data->mouseOffset = 0;
            d_data->direction = 0;
            break;
    }
}


//! Emits a valueChanged() signal if necessary
00188 void QwtAbstractSlider::buttonReleased()
{
    if ((!d_data->tracking) || (value() != prevValue()))
        emit valueChanged(value());
}


//! Mouse Release Event handler
00196 void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e)
{
    if ( isReadOnly() )
    {
        e->ignore();
        return;
    }
    if ( !isValid() )
        return;

    const double inc = step();
    
    switch(d_data->scrollMode) 
    {
        case ScrMouse:
        {
            setPosition(e->pos());
            d_data->direction = 0;
            d_data->mouseOffset = 0;
            if (d_data->mass > 0.0) 
            {
                const int ms = d_data->time.elapsed();
                if ((fabs(d_data->speed) >  0.0) && (ms < 50))
                    d_data->tmrID = startTimer(d_data->updTime);
            }
            else
            {
                d_data->scrollMode = ScrNone;
                buttonReleased();
            }
            emit sliderReleased();
            
            break;
        }

        case ScrDirect:
        {
            setPosition(e->pos());
            d_data->direction = 0;
            d_data->mouseOffset = 0;
            d_data->scrollMode = ScrNone;
            buttonReleased();
            break;
        }

        case ScrPage:
        {
            stopMoving();
            if (!d_data->timerTick)
                QwtDoubleRange::incPages(d_data->direction);
            d_data->timerTick = 0;
            buttonReleased();
            d_data->scrollMode = ScrNone;
            break;
        }

        case ScrTimer:
        {
            stopMoving();
            if (!d_data->timerTick)
                QwtDoubleRange::fitValue(value() + double(d_data->direction) * inc);
            d_data->timerTick = 0;
            buttonReleased();
            d_data->scrollMode = ScrNone;
            break;
        }

        default:
        {
            d_data->scrollMode = ScrNone;
            buttonReleased();
        }
    }
}


/*!
  Move the slider to a specified point, adjust the value
  and emit signals if necessary.
*/
00276 void QwtAbstractSlider::setPosition(const QPoint &p) 
{
    QwtDoubleRange::fitValue(getValue(p) - d_data->mouseOffset);
}


/*!
  \brief Enables or disables tracking.

  If tracking is enabled, the slider emits a
  valueChanged() signal whenever its value
  changes (the default behaviour). If tracking
  is disabled, the value changed() signal will only
  be emitted if:<ul>
  <li>the user releases the mouse
      button and the value has changed or
  <li>at the end of automatic scrolling.</ul>
  Tracking is enabled by default.
  \param enable \c true (enable) or \c false (disable) tracking.
*/
00296 void QwtAbstractSlider::setTracking(bool enable)
{
    d_data->tracking = enable;
}

/*! 
   Mouse Move Event handler
   \param e Mouse event
*/
00305 void QwtAbstractSlider::mouseMoveEvent(QMouseEvent *e)
{
    if ( isReadOnly() )
    {
        e->ignore();
        return;
    }

    if ( !isValid() )
        return;

    if (d_data->scrollMode == ScrMouse )
    {
        setPosition(e->pos());
        if (d_data->mass > 0.0) 
        {
            double ms = double(d_data->time.elapsed());
            if (ms < 1.0) 
                ms = 1.0;
            d_data->speed = (exactValue() - exactPrevValue()) / ms;
            d_data->time.start();
        }
        if (value() != prevValue())
            emit sliderMoved(value());
    }
}

/*! 
   Wheel Event handler
   \param e Whell event
*/
00336 void QwtAbstractSlider::wheelEvent(QWheelEvent *e)
{
    if ( isReadOnly() )
    {
        e->ignore();
        return;
    }

    if ( !isValid() )
        return;

    int mode = ScrNone, direction = 0;

    // Give derived classes a chance to say ScrNone
    getScrollMode(e->pos(), mode, direction);
    if ( mode != ScrNone )
    {
        const int inc = e->delta() / WHEEL_DELTA;
        QwtDoubleRange::incPages(inc);
        if (value() != prevValue())
            emit sliderMoved(value());
    }
}

/*!
  Handles key events

  - Key_Down, KeyLeft\n
    Decrement by 1
  - Key_Up, Key_Right\n
    Increment by 1

  \param e Key event
  \sa isReadOnly()
*/
00371 void QwtAbstractSlider::keyPressEvent(QKeyEvent *e)
{
    if ( isReadOnly() )
    {
        e->ignore();
        return;
    }

    if ( !isValid() )
        return;

    int increment = 0;
    switch ( e->key() ) 
    {
        case Qt::Key_Down:
            if ( orientation() == Qt::Vertical )
                increment = -1;
            break;
        case Qt::Key_Up:
            if ( orientation() == Qt::Vertical )
                increment = 1;
            break;
        case Qt::Key_Left:
            if ( orientation() == Qt::Horizontal )
                increment = -1;
            break;
        case Qt::Key_Right:
            if ( orientation() == Qt::Horizontal )
                increment = 1;
            break;
        default:;
            e->ignore();
    }

    if ( increment != 0 )
    {
        QwtDoubleRange::incValue(increment);
        if (value() != prevValue())
            emit sliderMoved(value());
    }
}

/*! 
   Qt timer event
   \param e Timer event
*/
00417 void QwtAbstractSlider::timerEvent(QTimerEvent *)
{
    const double inc = step();

    switch (d_data->scrollMode)
    {
        case ScrMouse:
        {
            if (d_data->mass > 0.0)
            {
                d_data->speed *= exp( - double(d_data->updTime) * 0.001 / d_data->mass );
                const double newval = 
                    exactValue() + d_data->speed * double(d_data->updTime);
                QwtDoubleRange::fitValue(newval);
                // stop if d_data->speed < one step per second
                if (fabs(d_data->speed) < 0.001 * fabs(step()))
                {
                    d_data->speed = 0;
                    stopMoving();
                    buttonReleased();
                }

            }
            else
               stopMoving();
            break;
        }

        case ScrPage:
        {
            QwtDoubleRange::incPages(d_data->direction);
            if (!d_data->timerTick) 
            {
                killTimer(d_data->tmrID);
                d_data->tmrID = startTimer(d_data->updTime);
            }
            break;
        }
        case ScrTimer:
        {
            QwtDoubleRange::fitValue(value() +  double(d_data->direction) * inc);
            if (!d_data->timerTick) 
            {
                killTimer(d_data->tmrID);
                d_data->tmrID = startTimer(d_data->updTime);
            }
            break;
        }
        default:
        {
            stopMoving();
            break;
        }
    }

    d_data->timerTick = 1;
}


/*!
  Notify change of value

  This function can be reimplemented by derived classes
  in order to keep track of changes, i.e. repaint the widget.
  The default implementation emits a valueChanged() signal
  if tracking is enabled.
*/
00484 void QwtAbstractSlider::valueChange() 
{
    if (d_data->tracking)
       emit valueChanged(value());  
}

/*!
  \brief Set the slider's mass for flywheel effect.

  If the slider's mass is greater then 0, it will continue
  to move after the mouse button has been released. Its speed
  decreases with time at a rate depending on the slider's mass.
  A large mass means that it will continue to move for a
  long time.

  Derived widgets may overload this function to make it public.

  \param val New mass in kg

  \bug If the mass is smaller than 1g, it is set to zero.
       The maximal mass is limited to 100kg.
  \sa mass()
*/
00507 void QwtAbstractSlider::setMass(double val)
{
    if (val < 0.001)
       d_data->mass = 0.0;
    else if (val > 100.0)
       d_data->mass = 100.0;
    else
       d_data->mass = val;
}

/*!
    \return mass
    \sa setMass()
*/
double QwtAbstractSlider::mass() const
{   
    return d_data->mass; 
}


/*!
  \brief Move the slider to a specified value

  This function can be used to move the slider to a value
  which is not an integer multiple of the step size.
  \param val new value
  \sa fitValue()
*/
00535 void QwtAbstractSlider::setValue(double val)
{
    if (d_data->scrollMode == ScrMouse) 
        stopMoving();
    QwtDoubleRange::setValue(val);
}


/*!
  \brief Set the slider's value to the nearest integer multiple
         of the step size.

   \param valeu Value
   \sa setValue(), incValue()
*/
00550 void QwtAbstractSlider::fitValue(double value)
{
    if (d_data->scrollMode == ScrMouse) 
        stopMoving();
    QwtDoubleRange::fitValue(value);
}

/*!
  \brief Increment the value by a specified number of steps
  \param steps number of steps
  \sa setValue()
*/
00562 void QwtAbstractSlider::incValue(int steps)
{
    if (d_data->scrollMode == ScrMouse) 
        stopMoving();
    QwtDoubleRange::incValue(steps);
}

void QwtAbstractSlider::setMouseOffset(double offset)
{
    d_data->mouseOffset = offset;
} 

double QwtAbstractSlider::mouseOffset() const
{
    return d_data->mouseOffset;
}

int QwtAbstractSlider::scrollMode() const
{
    return d_data->scrollMode;
}

Generated by  Doxygen 1.6.0   Back to index