You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
552 lines
0 B
552 lines
0 B
15 years ago
|
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
|
||
|
* Qwt Widget Library
|
||
|
* Copyright (C) 1997 Josef Wilgen
|
||
|
* Copyright (C) 2002 Uwe Rathmann
|
||
14 years ago
|
*
|
||
15 years ago
|
* 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),
|
||
14 years ago
|
readOnly(false) {
|
||
15 years ago
|
}
|
||
|
|
||
|
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;
|
||
|
};
|
||
|
|
||
14 years ago
|
/*!
|
||
15 years ago
|
\brief Constructor
|
||
|
|
||
|
\param orientation Orientation
|
||
|
\param parent Parent widget
|
||
|
*/
|
||
|
QwtAbstractSlider::QwtAbstractSlider(
|
||
14 years ago
|
Qt::Orientation orientation, QWidget *parent):
|
||
15 years ago
|
QWidget(parent, NULL)
|
||
|
{
|
||
|
d_data = new QwtAbstractSlider::PrivateData;
|
||
|
d_data->orientation = orientation;
|
||
|
|
||
|
#if QT_VERSION >= 0x040000
|
||
|
using namespace Qt;
|
||
|
#endif
|
||
|
setFocusPolicy(TabFocus);
|
||
|
}
|
||
|
|
||
|
//! Destructor
|
||
|
QwtAbstractSlider::~QwtAbstractSlider()
|
||
|
{
|
||
14 years ago
|
if(d_data->tmrID)
|
||
15 years ago
|
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()
|
||
|
*/
|
||
|
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()
|
||
|
*/
|
||
|
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;
|
||
|
}
|
||
|
|
||
14 years ago
|
/*!
|
||
15 years ago
|
\return Orientation
|
||
|
\sa setOrientation()
|
||
|
*/
|
||
|
Qt::Orientation QwtAbstractSlider::orientation() const
|
||
|
{
|
||
|
return d_data->orientation;
|
||
|
}
|
||
|
|
||
|
//! Stop updating if automatic scrolling is active
|
||
|
|
||
14 years ago
|
void QwtAbstractSlider::stopMoving()
|
||
15 years ago
|
{
|
||
14 years ago
|
if(d_data->tmrID) {
|
||
15 years ago
|
killTimer(d_data->tmrID);
|
||
|
d_data->tmrID = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Specify the update interval for automatic scrolling
|
||
|
\param t update interval in milliseconds
|
||
|
\sa getScrollMode()
|
||
|
*/
|
||
14 years ago
|
void QwtAbstractSlider::setUpdateTime(int t)
|
||
15 years ago
|
{
|
||
14 years ago
|
if (t < 50)
|
||
15 years ago
|
t = 50;
|
||
|
d_data->updTime = t;
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Mouse press event handler
|
||
14 years ago
|
void QwtAbstractSlider::mousePressEvent(QMouseEvent *e)
|
||
15 years ago
|
{
|
||
14 years ago
|
if ( isReadOnly() ) {
|
||
15 years ago
|
e->ignore();
|
||
|
return;
|
||
|
}
|
||
|
if ( !isValid() )
|
||
|
return;
|
||
|
|
||
|
const QPoint &p = e->pos();
|
||
|
|
||
|
d_data->timerTick = 0;
|
||
|
|
||
|
getScrollMode(p, d_data->scrollMode, d_data->direction);
|
||
|
stopMoving();
|
||
14 years ago
|
|
||
|
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;
|
||
15 years ago
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Emits a valueChanged() signal if necessary
|
||
|
void QwtAbstractSlider::buttonReleased()
|
||
|
{
|
||
|
if ((!d_data->tracking) || (value() != prevValue()))
|
||
|
emit valueChanged(value());
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Mouse Release Event handler
|
||
|
void QwtAbstractSlider::mouseReleaseEvent(QMouseEvent *e)
|
||
|
{
|
||
14 years ago
|
if ( isReadOnly() ) {
|
||
15 years ago
|
e->ignore();
|
||
|
return;
|
||
|
}
|
||
|
if ( !isValid() )
|
||
|
return;
|
||
|
|
||
|
const double inc = step();
|
||
|
|
||
14 years ago
|
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 {
|
||
15 years ago
|
d_data->scrollMode = ScrNone;
|
||
|
buttonReleased();
|
||
|
}
|
||
14 years ago
|
emit sliderReleased();
|
||
15 years ago
|
|
||
14 years ago
|
break;
|
||
|
}
|
||
15 years ago
|
|
||
14 years ago
|
case ScrDirect: {
|
||
|
setPosition(e->pos());
|
||
|
d_data->direction = 0;
|
||
|
d_data->mouseOffset = 0;
|
||
|
d_data->scrollMode = ScrNone;
|
||
|
buttonReleased();
|
||
|
break;
|
||
|
}
|
||
15 years ago
|
|
||
14 years ago
|
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();
|
||
|
}
|
||
15 years ago
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*!
|
||
|
Move the slider to a specified point, adjust the value
|
||
|
and emit signals if necessary.
|
||
|
*/
|
||
14 years ago
|
void QwtAbstractSlider::setPosition(const QPoint &p)
|
||
15 years ago
|
{
|
||
|
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.
|
||
|
*/
|
||
|
void QwtAbstractSlider::setTracking(bool enable)
|
||
|
{
|
||
|
d_data->tracking = enable;
|
||
|
}
|
||
|
|
||
14 years ago
|
/*!
|
||
15 years ago
|
Mouse Move Event handler
|
||
|
\param e Mouse event
|
||
|
*/
|
||
|
void QwtAbstractSlider::mouseMoveEvent(QMouseEvent *e)
|
||
|
{
|
||
14 years ago
|
if ( isReadOnly() ) {
|
||
15 years ago
|
e->ignore();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !isValid() )
|
||
|
return;
|
||
|
|
||
14 years ago
|
if (d_data->scrollMode == ScrMouse ) {
|
||
15 years ago
|
setPosition(e->pos());
|
||
14 years ago
|
if (d_data->mass > 0.0) {
|
||
15 years ago
|
double ms = double(d_data->time.elapsed());
|
||
14 years ago
|
if (ms < 1.0)
|
||
15 years ago
|
ms = 1.0;
|
||
|
d_data->speed = (exactValue() - exactPrevValue()) / ms;
|
||
|
d_data->time.start();
|
||
|
}
|
||
|
if (value() != prevValue())
|
||
|
emit sliderMoved(value());
|
||
|
}
|
||
|
}
|
||
|
|
||
14 years ago
|
/*!
|
||
15 years ago
|
Wheel Event handler
|
||
|
\param e Whell event
|
||
|
*/
|
||
|
void QwtAbstractSlider::wheelEvent(QWheelEvent *e)
|
||
|
{
|
||
14 years ago
|
if ( isReadOnly() ) {
|
||
15 years ago
|
e->ignore();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !isValid() )
|
||
|
return;
|
||
|
|
||
|
int mode = ScrNone, direction = 0;
|
||
|
|
||
|
// Give derived classes a chance to say ScrNone
|
||
|
getScrollMode(e->pos(), mode, direction);
|
||
14 years ago
|
if ( mode != ScrNone ) {
|
||
15 years ago
|
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()
|
||
|
*/
|
||
|
void QwtAbstractSlider::keyPressEvent(QKeyEvent *e)
|
||
|
{
|
||
14 years ago
|
if ( isReadOnly() ) {
|
||
15 years ago
|
e->ignore();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !isValid() )
|
||
|
return;
|
||
|
|
||
|
int increment = 0;
|
||
14 years ago
|
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();
|
||
15 years ago
|
}
|
||
|
|
||
14 years ago
|
if ( increment != 0 ) {
|
||
15 years ago
|
QwtDoubleRange::incValue(increment);
|
||
|
if (value() != prevValue())
|
||
|
emit sliderMoved(value());
|
||
|
}
|
||
|
}
|
||
|
|
||
14 years ago
|
/*!
|
||
15 years ago
|
Qt timer event
|
||
|
\param e Timer event
|
||
|
*/
|
||
|
void QwtAbstractSlider::timerEvent(QTimerEvent *)
|
||
|
{
|
||
|
const double inc = step();
|
||
|
|
||
14 years ago
|
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();
|
||
15 years ago
|
}
|
||
|
|
||
14 years ago
|
} else
|
||
15 years ago
|
stopMoving();
|
||
14 years ago
|
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);
|
||
15 years ago
|
}
|
||
14 years ago
|
break;
|
||
|
}
|
||
|
default: {
|
||
|
stopMoving();
|
||
|
break;
|
||
|
}
|
||
15 years ago
|
}
|
||
|
|
||
|
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.
|
||
|
*/
|
||
14 years ago
|
void QwtAbstractSlider::valueChange()
|
||
15 years ago
|
{
|
||
|
if (d_data->tracking)
|
||
14 years ago
|
emit valueChanged(value());
|
||
15 years ago
|
}
|
||
|
|
||
|
/*!
|
||
|
\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()
|
||
|
*/
|
||
|
void QwtAbstractSlider::setMass(double val)
|
||
|
{
|
||
|
if (val < 0.001)
|
||
14 years ago
|
d_data->mass = 0.0;
|
||
15 years ago
|
else if (val > 100.0)
|
||
14 years ago
|
d_data->mass = 100.0;
|
||
15 years ago
|
else
|
||
14 years ago
|
d_data->mass = val;
|
||
15 years ago
|
}
|
||
|
|
||
|
/*!
|
||
|
\return mass
|
||
|
\sa setMass()
|
||
|
*/
|
||
|
double QwtAbstractSlider::mass() const
|
||
14 years ago
|
{
|
||
|
return d_data->mass;
|
||
15 years ago
|
}
|
||
|
|
||
|
|
||
|
/*!
|
||
|
\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()
|
||
|
*/
|
||
|
void QwtAbstractSlider::setValue(double val)
|
||
|
{
|
||
14 years ago
|
if (d_data->scrollMode == ScrMouse)
|
||
15 years ago
|
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()
|
||
|
*/
|
||
|
void QwtAbstractSlider::fitValue(double value)
|
||
|
{
|
||
14 years ago
|
if (d_data->scrollMode == ScrMouse)
|
||
15 years ago
|
stopMoving();
|
||
|
QwtDoubleRange::fitValue(value);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Increment the value by a specified number of steps
|
||
|
\param steps number of steps
|
||
|
\sa setValue()
|
||
|
*/
|
||
|
void QwtAbstractSlider::incValue(int steps)
|
||
|
{
|
||
14 years ago
|
if (d_data->scrollMode == ScrMouse)
|
||
15 years ago
|
stopMoving();
|
||
|
QwtDoubleRange::incValue(steps);
|
||
|
}
|
||
|
|
||
|
void QwtAbstractSlider::setMouseOffset(double offset)
|
||
|
{
|
||
|
d_data->mouseOffset = offset;
|
||
14 years ago
|
}
|
||
15 years ago
|
|
||
|
double QwtAbstractSlider::mouseOffset() const
|
||
|
{
|
||
|
return d_data->mouseOffset;
|
||
|
}
|
||
|
|
||
|
int QwtAbstractSlider::scrollMode() const
|
||
|
{
|
||
|
return d_data->scrollMode;
|
||
|
}
|