Loading...
Searching...
No Matches
qwt_abstract_slider.cpp
/******************************************************************************
* 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_abstract_slider.h"
#include "qwt_scale_map.h"
#include "qwt_scale_div.h"
#include "qwt_math.h"
#include <qevent.h>
static double qwtAlignToScaleDiv(
const QwtAbstractSlider* slider, double value )
{
const QwtScaleDiv& sd = slider->scaleDiv();
const int tValue = slider->transform( value );
if ( tValue == slider->transform( sd.lowerBound() ) )
return sd.lowerBound();
if ( tValue == slider->transform( sd.upperBound() ) )
return sd.upperBound();
for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
{
const QList< double > ticks = sd.ticks( i );
for ( int j = 0; j < ticks.size(); j++ )
{
if ( slider->transform( ticks[ j ] ) == tValue )
return ticks[ j ];
}
}
return value;
}
class QwtAbstractSlider::PrivateData
{
public:
PrivateData()
: isScrolling( false )
, isTracking( true )
, pendingValueChanged( false )
, readOnly( false )
, totalSteps( 100 )
, singleSteps( 1 )
, pageSteps( 10 )
, stepAlignment( true )
, isValid( false )
, value( 0.0 )
, wrapping( false )
, invertedControls( false )
{
}
bool isScrolling;
bool isTracking;
bool pendingValueChanged;
bool readOnly;
uint totalSteps;
uint singleSteps;
uint pageSteps;
bool stepAlignment;
bool isValid;
double value;
bool wrapping;
bool invertedControls;
};
QwtAbstractSlider::QwtAbstractSlider( QWidget* parent )
: QwtAbstractScale( parent )
{
m_data = new QwtAbstractSlider::PrivateData;
setScale( 0.0, 100.0 );
setFocusPolicy( Qt::StrongFocus );
}
QwtAbstractSlider::~QwtAbstractSlider()
{
delete m_data;
}
void QwtAbstractSlider::setValid( bool on )
{
if ( on != m_data->isValid )
{
m_data->isValid = on;
sliderChange();
Q_EMIT valueChanged( m_data->value );
}
}
bool QwtAbstractSlider::isValid() const
{
return m_data->isValid;
}
void QwtAbstractSlider::setReadOnly( bool on )
{
if ( m_data->readOnly != on )
{
m_data->readOnly = on;
setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus );
update();
}
}
bool QwtAbstractSlider::isReadOnly() const
{
return m_data->readOnly;
}
void QwtAbstractSlider::setTracking( bool on )
{
m_data->isTracking = on;
}
bool QwtAbstractSlider::isTracking() const
{
return m_data->isTracking;
}
void QwtAbstractSlider::mousePressEvent( QMouseEvent* event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( !m_data->isValid || lowerBound() == upperBound() )
return;
m_data->isScrolling = isScrollPosition( event->pos() );
if ( m_data->isScrolling )
{
m_data->pendingValueChanged = false;
Q_EMIT sliderPressed();
}
}
void QwtAbstractSlider::mouseMoveEvent( QMouseEvent* event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( m_data->isValid && m_data->isScrolling )
{
double value = scrolledTo( event->pos() );
if ( value != m_data->value )
{
value = boundedValue( value );
if ( m_data->stepAlignment )
{
value = alignedValue( value );
}
else
{
value = qwtAlignToScaleDiv( this, value );
}
if ( value != m_data->value )
{
m_data->value = value;
sliderChange();
Q_EMIT sliderMoved( m_data->value );
if ( m_data->isTracking )
Q_EMIT valueChanged( m_data->value );
else
m_data->pendingValueChanged = true;
}
}
}
}
void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent* event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( m_data->isScrolling && m_data->isValid )
{
m_data->isScrolling = false;
if ( m_data->pendingValueChanged )
Q_EMIT valueChanged( m_data->value );
Q_EMIT sliderReleased();
}
}
void QwtAbstractSlider::wheelEvent( QWheelEvent* event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( !m_data->isValid || m_data->isScrolling )
return;
#if QT_VERSION < 0x050000
const int wheelDelta = event->delta();
#else
const QPoint delta = event->angleDelta();
const int wheelDelta = ( qAbs( delta.x() ) > qAbs( delta.y() ) )
? delta.x() : delta.y();
#endif
int numSteps = 0;
if ( ( event->modifiers() & Qt::ControlModifier ) ||
( event->modifiers() & Qt::ShiftModifier ) )
{
// one page regardless of delta
numSteps = m_data->pageSteps;
if ( wheelDelta < 0 )
numSteps = -numSteps;
}
else
{
const int numTurns = ( wheelDelta / 120 );
numSteps = numTurns * m_data->singleSteps;
}
if ( m_data->invertedControls )
numSteps = -numSteps;
const double value = incrementedValue( m_data->value, numSteps );
if ( value != m_data->value )
{
m_data->value = value;
sliderChange();
Q_EMIT sliderMoved( m_data->value );
Q_EMIT valueChanged( m_data->value );
}
}
void QwtAbstractSlider::keyPressEvent( QKeyEvent* event )
{
if ( isReadOnly() )
{
event->ignore();
return;
}
if ( !m_data->isValid || m_data->isScrolling )
return;
int numSteps = 0;
double value = m_data->value;
switch ( event->key() )
{
case Qt::Key_Left:
{
numSteps = -static_cast< int >( m_data->singleSteps );
if ( isInverted() )
numSteps = -numSteps;
break;
}
case Qt::Key_Right:
{
numSteps = m_data->singleSteps;
if ( isInverted() )
numSteps = -numSteps;
break;
}
case Qt::Key_Down:
{
numSteps = -static_cast< int >( m_data->singleSteps );
if ( m_data->invertedControls )
numSteps = -numSteps;
break;
}
case Qt::Key_Up:
{
numSteps = m_data->singleSteps;
if ( m_data->invertedControls )
numSteps = -numSteps;
break;
}
case Qt::Key_PageUp:
{
numSteps = m_data->pageSteps;
if ( m_data->invertedControls )
numSteps = -numSteps;
break;
}
case Qt::Key_PageDown:
{
numSteps = -static_cast< int >( m_data->pageSteps );
if ( m_data->invertedControls )
numSteps = -numSteps;
break;
}
case Qt::Key_Home:
{
value = minimum();
break;
}
case Qt::Key_End:
{
value = maximum();
break;
}
default:
{
event->ignore();
}
}
if ( numSteps != 0 )
{
value = incrementedValue( m_data->value, numSteps );
}
if ( value != m_data->value )
{
m_data->value = value;
sliderChange();
Q_EMIT sliderMoved( m_data->value );
Q_EMIT valueChanged( m_data->value );
}
}
void QwtAbstractSlider::setTotalSteps( uint stepCount )
{
m_data->totalSteps = stepCount;
}
uint QwtAbstractSlider::totalSteps() const
{
return m_data->totalSteps;
}
void QwtAbstractSlider::setSingleSteps( uint stepCount )
{
m_data->singleSteps = stepCount;
}
uint QwtAbstractSlider::singleSteps() const
{
return m_data->singleSteps;
}
void QwtAbstractSlider::setPageSteps( uint stepCount )
{
m_data->pageSteps = stepCount;
}
uint QwtAbstractSlider::pageSteps() const
{
return m_data->pageSteps;
}
void QwtAbstractSlider::setStepAlignment( bool on )
{
if ( on != m_data->stepAlignment )
{
m_data->stepAlignment = on;
}
}
bool QwtAbstractSlider::stepAlignment() const
{
return m_data->stepAlignment;
}
void QwtAbstractSlider::setValue( double value )
{
value = qBound( minimum(), value, maximum() );
const bool changed = ( m_data->value != value ) || !m_data->isValid;
m_data->value = value;
m_data->isValid = true;
if ( changed )
{
sliderChange();
Q_EMIT valueChanged( m_data->value );
}
}
double QwtAbstractSlider::value() const
{
return m_data->value;
}
void QwtAbstractSlider::setWrapping( bool on )
{
m_data->wrapping = on;
}
bool QwtAbstractSlider::wrapping() const
{
return m_data->wrapping;
}
void QwtAbstractSlider::setInvertedControls( bool on )
{
m_data->invertedControls = on;
}
bool QwtAbstractSlider::invertedControls() const
{
return m_data->invertedControls;
}
void QwtAbstractSlider::incrementValue( int stepCount )
{
const double value = incrementedValue(
m_data->value, stepCount );
if ( value != m_data->value )
{
m_data->value = value;
sliderChange();
}
}
double QwtAbstractSlider::incrementedValue(
double value, int stepCount ) const
{
if ( m_data->totalSteps == 0 )
return value;
const QwtTransform* transformation =
scaleMap().transformation();
if ( transformation == NULL )
{
const double range = maximum() - minimum();
value += stepCount * range / m_data->totalSteps;
}
else
{
QwtScaleMap map = scaleMap();
map.setPaintInterval( 0, m_data->totalSteps );
// we need equidistant steps according to
// paint device coordinates
const double range = transformation->transform( maximum() )
- transformation->transform( minimum() );
const double stepSize = range / m_data->totalSteps;
double v = transformation->transform( value );
v = qRound( v / stepSize ) * stepSize;
v += stepCount * range / m_data->totalSteps;
value = transformation->invTransform( v );
}
value = boundedValue( value );
if ( m_data->stepAlignment )
value = alignedValue( value );
return value;
}
double QwtAbstractSlider::boundedValue( double value ) const
{
const double vmin = minimum();
const double vmax = maximum();
if ( m_data->wrapping && vmin != vmax )
{
if ( qFuzzyCompare( scaleMap().pDist(), 360.0 ) )
{
// full circle scales: min and max are the same
if ( qFuzzyCompare( value, vmax ) )
{
value = vmin;
}
else
{
const double range = vmax - vmin;
if ( value < vmin )
{
value += std::ceil( ( vmin - value ) / range ) * range;
}
else if ( value > vmax )
{
value -= std::ceil( ( value - vmax ) / range ) * range;
}
}
}
else
{
if ( value < vmin )
value = vmax;
else if ( value > vmax )
value = vmin;
}
}
else
{
value = qBound( vmin, value, vmax );
}
return value;
}
double QwtAbstractSlider::alignedValue( double value ) const
{
if ( m_data->totalSteps == 0 )
return value;
double stepSize;
if ( scaleMap().transformation() == NULL )
{
stepSize = ( maximum() - minimum() ) / m_data->totalSteps;
if ( stepSize > 0.0 )
{
value = lowerBound() +
qRound( ( value - lowerBound() ) / stepSize ) * stepSize;
}
}
else
{
stepSize = ( scaleMap().p2() - scaleMap().p1() ) / m_data->totalSteps;
if ( stepSize > 0.0 )
{
double v = scaleMap().transform( value );
v = scaleMap().p1() +
qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize;
value = scaleMap().invTransform( v );
}
}
if ( qAbs( stepSize ) > 1e-12 )
{
if ( qFuzzyCompare( value + 1.0, 1.0 ) )
{
// correct rounding error if value = 0
value = 0.0;
}
else
{
// correct rounding error at the border
if ( qFuzzyCompare( value, upperBound() ) )
value = upperBound();
else if ( qFuzzyCompare( value, lowerBound() ) )
value = lowerBound();
}
}
return value;
}
void QwtAbstractSlider::scaleChange()
{
const double value = qBound( minimum(), m_data->value, maximum() );
const bool changed = ( value != m_data->value );
if ( changed )
{
m_data->value = value;
}
if ( m_data->isValid || changed )
Q_EMIT valueChanged( m_data->value );
updateGeometry();
update();
}
void QwtAbstractSlider::sliderChange()
{
update();
}
#include "moc_qwt_abstract_slider.cpp"
QList< double >
QwtAbstractScale
An abstract base class for widgets having a scale.
Definition qwt_abstract_scale.h:37
QwtAbstractScale::scaleMap
const QwtScaleMap & scaleMap() const
Definition qwt_abstract_scale.cpp:357
QwtAbstractScale::lowerBound
double lowerBound() const
Definition qwt_abstract_scale.cpp:88
QwtAbstractScale::scaleDiv
const QwtScaleDiv & scaleDiv() const
Definition qwt_abstract_scale.cpp:349
QwtAbstractScale::transform
int transform(double) const
Definition qwt_abstract_scale.cpp:369
QwtAbstractScale::minimum
double minimum() const
Definition qwt_abstract_scale.cpp:399
QwtAbstractScale::isInverted
bool isInverted() const
Definition qwt_abstract_scale.cpp:390
QwtAbstractScale::maximum
double maximum() const
Definition qwt_abstract_scale.cpp:409
QwtAbstractScale::upperBound
double upperBound() const
Definition qwt_abstract_scale.cpp:111
QwtAbstractScale::setScale
void setScale(double lowerBound, double upperBound)
Specify a scale.
Definition qwt_abstract_scale.cpp:130
QwtAbstractSlider
An abstract base class for slider widgets with a scale.
Definition qwt_abstract_slider.h:33
QwtAbstractSlider::invertedControls
bool invertedControls() const
Definition qwt_abstract_slider.cpp:637
QwtAbstractSlider::scaleChange
virtual void scaleChange() override
Definition qwt_abstract_slider.cpp:811
QwtAbstractSlider::mouseReleaseEvent
virtual void mouseReleaseEvent(QMouseEvent *) override
Definition qwt_abstract_slider.cpp:265
QwtAbstractSlider::~QwtAbstractSlider
virtual ~QwtAbstractSlider()
Destructor.
Definition qwt_abstract_slider.cpp:101
QwtAbstractSlider::sliderChange
virtual void sliderChange()
Calling update()
Definition qwt_abstract_slider.cpp:829
QwtAbstractSlider::singleSteps
uint singleSteps() const
Definition qwt_abstract_slider.cpp:508
QwtAbstractSlider::keyPressEvent
virtual void keyPressEvent(QKeyEvent *) override
Definition qwt_abstract_slider.cpp:370
QwtAbstractSlider::setTracking
void setTracking(bool)
Enables or disables tracking.
Definition qwt_abstract_slider.cpp:177
QwtAbstractSlider::mousePressEvent
virtual void mousePressEvent(QMouseEvent *) override
Definition qwt_abstract_slider.cpp:195
QwtAbstractSlider::setTotalSteps
void setTotalSteps(uint)
Set the number of steps.
Definition qwt_abstract_slider.cpp:474
QwtAbstractSlider::setValid
void setValid(bool)
Definition qwt_abstract_slider.cpp:113
QwtAbstractSlider::valueChanged
void valueChanged(double value)
Notify a change of value.
QwtAbstractSlider::setValue
void setValue(double value)
Definition qwt_abstract_slider.cpp:570
QwtAbstractSlider::wrapping
bool wrapping() const
Definition qwt_abstract_slider.cpp:608
QwtAbstractSlider::incrementedValue
double incrementedValue(double value, int stepCount) const
Definition qwt_abstract_slider.cpp:670
QwtAbstractSlider::isTracking
bool isTracking() const
Definition qwt_abstract_slider.cpp:186
QwtAbstractSlider::setStepAlignment
void setStepAlignment(bool)
Enable step alignment.
Definition qwt_abstract_slider.cpp:547
QwtAbstractSlider::isReadOnly
bool isReadOnly() const
Definition qwt_abstract_slider.cpp:159
QwtAbstractSlider::setInvertedControls
void setInvertedControls(bool)
Definition qwt_abstract_slider.cpp:628
QwtAbstractSlider::incrementValue
void incrementValue(int stepCount)
Definition qwt_abstract_slider.cpp:650
QwtAbstractSlider::totalSteps
uint totalSteps() const
Definition qwt_abstract_slider.cpp:483
QwtAbstractSlider::stepAlignment
bool stepAlignment() const
Definition qwt_abstract_slider.cpp:559
QwtAbstractSlider::setReadOnly
void setReadOnly(bool)
Definition qwt_abstract_slider.cpp:141
QwtAbstractSlider::isValid
bool isValid() const
Definition qwt_abstract_slider.cpp:125
QwtAbstractSlider::mouseMoveEvent
virtual void mouseMoveEvent(QMouseEvent *) override
Definition qwt_abstract_slider.cpp:220
QwtAbstractSlider::sliderReleased
void sliderReleased()
QwtAbstractSlider::wheelEvent
virtual void wheelEvent(QWheelEvent *) override
Definition qwt_abstract_slider.cpp:296
QwtAbstractSlider::setSingleSteps
void setSingleSteps(uint)
Set the number of steps for a single increment.
Definition qwt_abstract_slider.cpp:499
QwtAbstractSlider::value
double value() const
Returns the current value.
Definition qwt_abstract_slider.cpp:587
QwtAbstractSlider::setWrapping
void setWrapping(bool)
Definition qwt_abstract_slider.cpp:599
QwtAbstractSlider::pageSteps
uint pageSteps() const
Definition qwt_abstract_slider.cpp:533
QwtAbstractSlider::setPageSteps
void setPageSteps(uint)
Set the number of steps for a page increment.
Definition qwt_abstract_slider.cpp:524
QwtAbstractSlider::sliderMoved
void sliderMoved(double value)
QwtAbstractSlider::isScrollPosition
virtual bool isScrollPosition(const QPoint &pos) const =0
Determine what to do when the user presses a mouse button.
QwtAbstractSlider::scrolledTo
virtual double scrolledTo(const QPoint &pos) const =0
Determine the value for a new position of the movable part of the slider.
QwtAbstractSlider::QwtAbstractSlider
QwtAbstractSlider(QWidget *parent=NULL)
Constructor.
Definition qwt_abstract_slider.cpp:91
QwtAbstractSlider::sliderPressed
void sliderPressed()
QwtScaleDiv
A class representing a scale division.
Definition qwt_scale_div.h:34
QwtScaleDiv::lowerBound
double lowerBound() const
Definition qwt_scale_div.cpp:131
QwtScaleDiv::upperBound
double upperBound() const
Definition qwt_scale_div.cpp:151
QwtScaleDiv::ticks
QList< double > ticks(int tickType) const
Definition qwt_scale_div.cpp:309
QwtScaleDiv::NTickTypes
@ NTickTypes
Number of valid tick types.
Definition qwt_scale_div.h:52
QwtScaleMap
A scale map.
Definition qwt_scale_map.h:27
QwtScaleMap::p1
double p1() const
Definition qwt_scale_map.h:99
QwtScaleMap::transform
double transform(double s) const
Definition qwt_scale_map.h:137
QwtScaleMap::transformation
const QwtTransform * transformation() const
Get the transformation.
Definition qwt_scale_map.cpp:88
QwtScaleMap::setPaintInterval
void setPaintInterval(double p1, double p2)
Specify the borders of the paint device interval.
Definition qwt_scale_map.cpp:119
QwtScaleMap::invTransform
double invTransform(double p) const
Definition qwt_scale_map.h:154
QwtScaleMap::p2
double p2() const
Definition qwt_scale_map.h:107
QwtTransform
A transformation between coordinate systems.
Definition qwt_transform.h:36
QwtTransform::transform
virtual double transform(double value) const =0
QwtTransform::invTransform
virtual double invTransform(double value) const =0