From 9bd3e608ba5319614f6dfa824bb4496a9cfa3f10 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sat, 25 Jul 2020 18:46:04 +0200 Subject: [PATCH] QskBoundedRangeInput added --- src/controls/QskBoundedInput.cpp | 42 +++++++- src/controls/QskBoundedInput.h | 3 + src/controls/QskBoundedRangeInput.cpp | 135 ++++++++++++++++++++++++++ src/controls/QskBoundedRangeInput.h | 70 +++++++++++++ src/controls/QskBoundedValueInput.cpp | 42 +++----- src/controls/QskBoundedValueInput.h | 3 +- src/src.pro | 2 + 7 files changed, 265 insertions(+), 32 deletions(-) create mode 100644 src/controls/QskBoundedRangeInput.cpp create mode 100644 src/controls/QskBoundedRangeInput.h diff --git a/src/controls/QskBoundedInput.cpp b/src/controls/QskBoundedInput.cpp index 9624ca55..afaa7ef6 100644 --- a/src/controls/QskBoundedInput.cpp +++ b/src/controls/QskBoundedInput.cpp @@ -7,6 +7,8 @@ #include "QskFunctions.h" #include "QskIntervalF.h" +#include + QSK_SYSTEM_STATE( QskBoundedInput, ReadOnly, ( QskAspect::FirstSystemState << 1 ) ) class QskBoundedInput::PrivateData @@ -145,13 +147,20 @@ qreal QskBoundedInput::boundaryLength() const void QskBoundedInput::setStepSize( qreal stepSize ) { - if ( qskFuzzyCompare( m_data->stepSize, stepSize ) ) + if ( qFuzzyIsNull( stepSize ) ) + stepSize = 0.0; + + if ( qFuzzyCompare( m_data->stepSize, stepSize ) ) return; m_data->stepSize = stepSize; Q_EMIT stepSizeChanged( stepSize ); - update(); + if ( isComponentComplete() ) + { + if ( m_data->snap && stepSize ) + alignInput(); + } } qreal QskBoundedInput::stepSize() const @@ -166,8 +175,6 @@ void QskBoundedInput::setPageSize( int pageSize ) m_data->pageSize = pageSize; Q_EMIT pageSizeChanged( pageSize ); - - update(); } int QskBoundedInput::pageSize() const @@ -212,6 +219,33 @@ bool QskBoundedInput::snap() const return m_data->snap; } +qreal QskBoundedInput::alignedValue( qreal value ) const +{ + if ( m_data->snap ) + { + if ( const auto step = m_data->stepSize ) + value = qRound( value / step ) * step; + } + + return qBound( minimum(), value, maximum() ); +} + +QskIntervalF QskBoundedInput::alignedInterval( const QskIntervalF& interval ) const +{ + if ( m_data->snap ) + { + if ( const auto step = m_data->stepSize ) + { + const qreal lower = std::floor( interval.lowerBound() / step ) * step; + const qreal upper = std::ceil( interval.upperBound() / step ) * step; + + return QskIntervalF( lower, upper ); + } + } + + return interval; +} + void QskBoundedInput::setReadOnly( bool readOnly ) { if ( readOnly == isReadOnly() ) diff --git a/src/controls/QskBoundedInput.h b/src/controls/QskBoundedInput.h index 4036d116..3a3302a7 100644 --- a/src/controls/QskBoundedInput.h +++ b/src/controls/QskBoundedInput.h @@ -87,6 +87,9 @@ class QSK_EXPORT QskBoundedInput : public QskControl virtual void alignInput() = 0; + qreal alignedValue( qreal ) const; + QskIntervalF alignedInterval( const QskIntervalF& ) const; + private: void adjustBoundaries( bool increasing ); diff --git a/src/controls/QskBoundedRangeInput.cpp b/src/controls/QskBoundedRangeInput.cpp new file mode 100644 index 00000000..caf79ba9 --- /dev/null +++ b/src/controls/QskBoundedRangeInput.cpp @@ -0,0 +1,135 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#include "QskBoundedRangeInput.h" +#include "QskIntervalF.h" +#include "QskFunctions.h" + +QskBoundedRangeInput::QskBoundedRangeInput( QQuickItem* parent ) + : QskBoundedInput( parent ) +{ +} + +QskBoundedRangeInput::QskBoundedRangeInput( + const QskIntervalF& range, QQuickItem* parent ) + : QskBoundedInput( parent ) + , m_range( range ) +{ +} + +QskBoundedRangeInput::~QskBoundedRangeInput() +{ +} + +void QskBoundedRangeInput::setLowerValueAsRatio( qreal ratio ) +{ + ratio = qBound( 0.0, ratio, 1.0 ); + setLowerValue( minimum() + ratio * boundaryLength() ); +} + +qreal QskBoundedRangeInput::lowerValueAsRatio() const +{ + return ( lowerValue() - minimum() ) / boundaryLength(); +} + +void QskBoundedRangeInput::setUpperValueAsRatio( qreal ratio ) +{ + ratio = qBound( 0.0, ratio, 1.0 ); + setUpperValue( minimum() + ratio * boundaryLength() ); +} + +qreal QskBoundedRangeInput::upperValueAsRatio() const +{ + return ( upperValue() - minimum() ) / boundaryLength(); +} + +void QskBoundedRangeInput::setLowerValue( qreal value ) +{ + if ( isComponentComplete() ) + value = qBound( minimum(), value, maximum() ); + + const auto upperValue = std::max( m_range.upperBound(), value ); + setRange( QskIntervalF( value, upperValue ) ); +} + +qreal QskBoundedRangeInput::lowerValue() const +{ + return m_range.lowerBound(); +} + +void QskBoundedRangeInput::setUpperValue( qreal value ) +{ + if ( isComponentComplete() ) + value = qBound( minimum(), value, maximum() ); + + const auto lowerValue = std::min( m_range.lowerBound(), value ); + setRange( QskIntervalF( lowerValue, value ) ); +} + +qreal QskBoundedRangeInput::upperValue() const +{ + return m_range.upperBound(); +} + +void QskBoundedRangeInput::setRange( qreal lowerValue, qreal upperValue ) +{ + setRange( QskIntervalF( lowerValue, upperValue ) ); +} + +void QskBoundedRangeInput::setRange( const QskIntervalF& range ) +{ + auto newRange = range; + + if ( isComponentComplete() ) + { + newRange = alignedInterval( newRange ); + newRange = fixupRange( newRange ); + } + + setRangeInternal( range ); +} + +void QskBoundedRangeInput::resetRange() +{ + if ( m_range.isValid() ) + { + m_range.invalidate(); + Q_EMIT rangeChanged( m_range ); + } +} + +void QskBoundedRangeInput::setRangeInternal( const QskIntervalF& range ) +{ + if ( range != m_range ) + { + const auto oldRange = m_range; + m_range = range; + + if ( !qskFuzzyCompare( m_range.lowerBound(), oldRange.lowerBound() ) ) + Q_EMIT lowerValueChanged( m_range.lowerBound() ); + + if ( !qskFuzzyCompare( m_range.upperBound(), oldRange.upperBound() ) ) + Q_EMIT upperValueChanged( m_range.upperBound() ); + + Q_EMIT rangeChanged( m_range ); + } +} + +QskIntervalF QskBoundedRangeInput::range() const +{ + return m_range; +} + +void QskBoundedRangeInput::alignInput() +{ + setRangeInternal( alignedInterval( m_range ) ); +} + +QskIntervalF QskBoundedRangeInput::fixupRange( const QskIntervalF& range ) const +{ + return range; +} + +#include "moc_QskBoundedRangeInput.cpp" diff --git a/src/controls/QskBoundedRangeInput.h b/src/controls/QskBoundedRangeInput.h new file mode 100644 index 00000000..a945c878 --- /dev/null +++ b/src/controls/QskBoundedRangeInput.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * This file may be used under the terms of the QSkinny License, Version 1.0 + *****************************************************************************/ + +#ifndef QSK_BOUNDED_RANGE_INPUT_H +#define QSK_BOUNDED_RANGE_INPUT_H + +#include "QskBoundedInput.h" +#include "QskIntervalF.h" + +class QSK_EXPORT QskBoundedRangeInput : public QskBoundedInput +{ + Q_OBJECT + + Q_PROPERTY( qreal lowerValue READ lowerValue + WRITE setLowerValue NOTIFY lowerValueChanged ) + + Q_PROPERTY( qreal upperValue READ upperValue + WRITE setUpperValue NOTIFY upperValueChanged ) + + Q_PROPERTY( QskIntervalF range READ range WRITE setRange + RESET resetRange NOTIFY rangeChanged ) + + using Inherited = QskBoundedInput; + + public: + QskBoundedRangeInput( QQuickItem* parent = nullptr ); + QskBoundedRangeInput( const QskIntervalF&, QQuickItem* parent = nullptr ); + ~QskBoundedRangeInput() override; + + void setRange( qreal lowerValue, qreal upperValue ); + void resetRange(); + + QskIntervalF range() const; + + qreal lowerValue() const; + qreal upperValue() const; + + // [0.0, 1.0] + qreal lowerValueAsRatio() const; + qreal upperValueAsRatio() const; + + public Q_SLOTS: + void setRange( const QskIntervalF& ); + + void setLowerValue( qreal ); + void setUpperValue( qreal ); + + void setLowerValueAsRatio( qreal ); + void setUpperValueAsRatio( qreal ); + + Q_SIGNALS: + void rangeChanged( const QskIntervalF& ); + void lowerValueChanged( qreal ); + void upperValueChanged( qreal ); + + protected: + virtual QskIntervalF fixupRange( const QskIntervalF& ) const; + + void alignInput() override; + + private: + void setRangeInternal( const QskIntervalF& ); + void adjustValue(); + + QskIntervalF m_range; +}; + +#endif diff --git a/src/controls/QskBoundedValueInput.cpp b/src/controls/QskBoundedValueInput.cpp index e7d1a53e..7a35515a 100644 --- a/src/controls/QskBoundedValueInput.cpp +++ b/src/controls/QskBoundedValueInput.cpp @@ -15,26 +15,12 @@ QskBoundedValueInput::~QskBoundedValueInput() { } -qreal QskBoundedValueInput::alignedValue( qreal value ) const -{ - if ( snap() ) - { - if ( const auto step = stepSize() ) - value = qRound( value / step ) * step; - } - - return qBound( minimum(), value, maximum() ); -} - void QskBoundedValueInput::alignInput() { - const auto newValue = alignedValue( m_value ); + auto value = alignedValue( m_value ); + value = fixupValue( value ); - if ( newValue != m_value ) - { - m_value = newValue; - Q_EMIT valueChanged( newValue ); - } + setValueInternal( value ); } qreal QskBoundedValueInput::fixupValue( qreal value ) const @@ -58,17 +44,10 @@ void QskBoundedValueInput::setValue( qreal value ) if ( isComponentComplete() ) { value = alignedValue( value ); + value = fixupValue( value ); } - value = fixupValue( value ); - - if ( !qskFuzzyCompare( value, m_value ) ) - { - m_value = value; - Q_EMIT valueChanged( value ); - - update(); - } + setValueInternal( value ); } qreal QskBoundedValueInput::value() const @@ -81,4 +60,15 @@ void QskBoundedValueInput::increment( qreal offset ) setValue( m_value + offset ); } +void QskBoundedValueInput::setValueInternal( qreal value ) +{ + if ( !qskFuzzyCompare( value, m_value ) ) + { + m_value = value; + Q_EMIT valueChanged( value ); + + update(); + } +} + #include "moc_QskBoundedValueInput.cpp" diff --git a/src/controls/QskBoundedValueInput.h b/src/controls/QskBoundedValueInput.h index c8ebdbcc..0b66ce3e 100644 --- a/src/controls/QskBoundedValueInput.h +++ b/src/controls/QskBoundedValueInput.h @@ -40,10 +40,9 @@ class QSK_EXPORT QskBoundedValueInput : public QskBoundedInput void alignInput() override; private: + void setValueInternal( qreal value ); void adjustValue(); - qreal alignedValue( qreal value ) const; - qreal m_value = 0.0; }; diff --git a/src/src.pro b/src/src.pro index 1ca8aeaa..37d4feae 100644 --- a/src/src.pro +++ b/src/src.pro @@ -111,6 +111,7 @@ HEADERS += \ controls/QskAnimationHint.h \ controls/QskAnimator.h \ controls/QskBoundedInput.h \ + controls/QskBoundedRangeInput.h \ controls/QskBoundedValueInput.h \ controls/QskBox.h \ controls/QskBoxSkinlet.h \ @@ -180,6 +181,7 @@ SOURCES += \ controls/QskAbstractButton.cpp \ controls/QskAnimator.cpp \ controls/QskBoundedInput.cpp \ + controls/QskBoundedRangeInput.cpp \ controls/QskBoundedValueInput.cpp \ controls/QskBox.cpp \ controls/QskBoxSkinlet.cpp \