QskBoundedControl added

This commit is contained in:
Uwe Rathmann 2020-07-31 07:41:25 +02:00
parent 1e6f1c810b
commit 2186765763
8 changed files with 259 additions and 183 deletions

View File

@ -0,0 +1,143 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskBoundedControl.h"
#include "QskFunctions.h"
#include "QskIntervalF.h"
QskBoundedControl::QskBoundedControl( QQuickItem* parent )
: QskBoundedControl( 0.0, 1.0, parent )
{
}
QskBoundedControl::QskBoundedControl( qreal min, qreal max, QQuickItem* parent )
: QskControl( parent )
, m_minimum( qMin( min, max ) )
, m_maximum( qMax( min, max ) )
{
}
QskBoundedControl::~QskBoundedControl()
{
}
void QskBoundedControl::setMinimum( qreal minimum )
{
if ( qskFuzzyCompare( m_minimum, minimum ) )
return;
m_minimum = minimum;
Q_EMIT minimumChanged( minimum );
if ( isComponentComplete() )
adjustBoundaries( false );
Q_EMIT boundariesChanged( boundaries() );
update();
}
qreal QskBoundedControl::minimum() const
{
return m_minimum;
}
void QskBoundedControl::setMaximum( qreal maximum )
{
if ( qskFuzzyCompare( m_maximum, maximum ) )
return;
m_maximum = maximum;
Q_EMIT maximumChanged( maximum );
if ( isComponentComplete() )
adjustBoundaries( true );
Q_EMIT boundariesChanged( boundaries() );
update();
}
qreal QskBoundedControl::maximum() const
{
return m_maximum;
}
void QskBoundedControl::setBoundaries( qreal min, qreal max )
{
if ( max < min )
max = min;
const auto oldMin = m_minimum;
const auto oldMax = m_maximum;
if ( min == oldMin && max == oldMax )
return;
m_minimum = min;
m_maximum = max;
if ( isComponentComplete() )
adjustBoundaries( false );
if ( m_minimum != oldMin )
Q_EMIT minimumChanged( m_minimum );
if ( m_maximum != oldMax )
Q_EMIT maximumChanged( m_maximum );
Q_EMIT boundariesChanged( boundaries() );
update();
}
void QskBoundedControl::setBoundaries( const QskIntervalF& boundaries )
{
setBoundaries( boundaries.lowerBound(), boundaries.upperBound() );
}
QskIntervalF QskBoundedControl::boundaries() const
{
return QskIntervalF( m_minimum, m_maximum );
}
void QskBoundedControl::adjustBoundaries( bool increasing )
{
if ( m_maximum >= m_minimum )
return;
if ( increasing )
{
m_minimum = m_maximum;
Q_EMIT minimumChanged( m_minimum );
}
else
{
m_maximum = m_minimum;
Q_EMIT maximumChanged( m_maximum );
}
Q_EMIT boundariesChanged( boundaries() );
}
qreal QskBoundedControl::boundaryLength() const
{
return m_maximum - m_minimum;
}
void QskBoundedControl::componentComplete()
{
Inherited::componentComplete();
adjustBoundaries( true );
}
qreal QskBoundedControl::boundedValue( qreal value ) const
{
return qBound( minimum(), value, maximum() );
}
qreal QskBoundedControl::valueAsRatio( qreal value ) const
{
return ( value - m_minimum ) / ( m_maximum - m_minimum );
}
#include "moc_QskBoundedControl.cpp"

View File

@ -0,0 +1,61 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_BOUNDED_CONTROL_H
#define QSK_BOUNDED_CONTROL_H
#include "QskControl.h"
class QskIntervalF;
class QSK_EXPORT QskBoundedControl : public QskControl
{
Q_OBJECT
Q_PROPERTY( qreal minimum READ minimum WRITE setMinimum NOTIFY minimumChanged )
Q_PROPERTY( qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged )
Q_PROPERTY( QskIntervalF boundaries READ boundaries
WRITE setBoundaries NOTIFY boundariesChanged )
using Inherited = QskControl;
public:
~QskBoundedControl() override;
qreal minimum() const;
qreal maximum() const;
qreal boundaryLength() const;
void setBoundaries( qreal min, qreal max );
QskIntervalF boundaries() const;
qreal boundedValue( qreal ) const;
qreal valueAsRatio( qreal ) const;
public Q_SLOTS:
void setMinimum( qreal );
void setMaximum( qreal );
void setBoundaries( const QskIntervalF& );
Q_SIGNALS:
void minimumChanged( qreal );
void maximumChanged( qreal );
void boundariesChanged( const QskIntervalF& );
protected:
QskBoundedControl( QQuickItem* parent = nullptr );
QskBoundedControl( qreal min, qreal max, QQuickItem* parent = nullptr );
void componentComplete() override;
void adjustBoundaries( bool increasing );
private:
qreal m_minimum;
qreal m_maximum;
};
#endif

View File

@ -11,203 +11,90 @@
QSK_SYSTEM_STATE( QskBoundedInput, ReadOnly, ( QskAspect::FirstSystemState << 1 ) ) QSK_SYSTEM_STATE( QskBoundedInput, ReadOnly, ( QskAspect::FirstSystemState << 1 ) )
class QskBoundedInput::PrivateData
{
public:
PrivateData()
: minimum( 0.0 )
, maximum( 1.0 )
, stepSize( 0.1 )
, pageSize( 1 )
, snap( false )
{
}
qreal minimum;
qreal maximum;
qreal stepSize;
int pageSize;
bool snap : 1;
};
QskBoundedInput::QskBoundedInput( QQuickItem* parent ) QskBoundedInput::QskBoundedInput( QQuickItem* parent )
: QskControl( parent ) : Inherited( parent )
, m_data( new PrivateData() ) , m_stepSize( 0.1 )
, m_pageSize( 1 )
, m_snap( false )
{ {
setFocusPolicy( Qt::StrongFocus ); setFocusPolicy( Qt::StrongFocus );
setAcceptedMouseButtons( Qt::LeftButton ); setAcceptedMouseButtons( Qt::LeftButton );
setWheelEnabled( true ); setWheelEnabled( true );
if ( isComponentComplete() )
{
connect( this, &QskBoundedControl::boundariesChanged,
this, &QskBoundedInput::alignInput );
}
} }
QskBoundedInput::~QskBoundedInput() QskBoundedInput::~QskBoundedInput()
{ {
} }
void QskBoundedInput::setMinimum( qreal minimum )
{
if ( m_data->minimum == minimum )
return;
m_data->minimum = minimum;
Q_EMIT minimumChanged( minimum );
if ( isComponentComplete() )
adjustBoundaries( false );
Q_EMIT boundariesChanged( boundaries() );
update();
}
qreal QskBoundedInput::minimum() const
{
return m_data->minimum;
}
void QskBoundedInput::setMaximum( qreal maximum )
{
if ( m_data->maximum == maximum )
return;
m_data->maximum = maximum;
Q_EMIT maximumChanged( maximum );
if ( isComponentComplete() )
adjustBoundaries( true );
Q_EMIT boundariesChanged( boundaries() );
update();
}
qreal QskBoundedInput::maximum() const
{
return m_data->maximum;
}
void QskBoundedInput::setBoundaries( qreal min, qreal max )
{
if ( max < min )
max = min;
const auto oldMin = m_data->minimum;
const auto oldMax = m_data->maximum;
if ( min == oldMin && max == oldMax )
return;
m_data->minimum = min;
m_data->maximum = max;
if ( isComponentComplete() )
adjustBoundaries( false );
if ( m_data->minimum != oldMin )
Q_EMIT minimumChanged( m_data->minimum );
if ( m_data->maximum != oldMax )
Q_EMIT maximumChanged( m_data->maximum );
Q_EMIT boundariesChanged( boundaries() );
update();
}
void QskBoundedInput::setBoundaries( const QskIntervalF& boundaries )
{
setBoundaries( boundaries.lowerBound(), boundaries.upperBound() );
}
QskIntervalF QskBoundedInput::boundaries() const
{
return QskIntervalF( m_data->minimum, m_data->maximum );
}
void QskBoundedInput::adjustBoundaries( bool increasing )
{
if ( m_data->maximum < m_data->minimum )
{
if ( increasing )
{
m_data->minimum = m_data->maximum;
Q_EMIT minimumChanged( m_data->minimum );
}
else
{
m_data->maximum = m_data->minimum;
Q_EMIT maximumChanged( m_data->maximum );
}
alignInput();
}
}
qreal QskBoundedInput::boundaryLength() const
{
return m_data->maximum - m_data->minimum;
}
void QskBoundedInput::setStepSize( qreal stepSize ) void QskBoundedInput::setStepSize( qreal stepSize )
{ {
if ( qFuzzyIsNull( stepSize ) ) if ( qFuzzyIsNull( stepSize ) )
stepSize = 0.0; stepSize = 0.0;
if ( qFuzzyCompare( m_data->stepSize, stepSize ) ) if ( qFuzzyCompare( m_stepSize, stepSize ) )
return; return;
m_data->stepSize = stepSize; m_stepSize = stepSize;
Q_EMIT stepSizeChanged( stepSize ); Q_EMIT stepSizeChanged( stepSize );
if ( isComponentComplete() ) if ( isComponentComplete() )
{ {
if ( m_data->snap && stepSize ) if ( m_snap && stepSize )
alignInput(); alignInput();
} }
} }
qreal QskBoundedInput::stepSize() const qreal QskBoundedInput::stepSize() const
{ {
return m_data->stepSize; return m_stepSize;
} }
void QskBoundedInput::setPageSize( int pageSize ) void QskBoundedInput::setPageSize( int pageSize )
{ {
if ( m_data->pageSize == pageSize ) if ( m_pageSize == pageSize )
return; return;
m_data->pageSize = pageSize; m_pageSize = pageSize;
Q_EMIT pageSizeChanged( pageSize ); Q_EMIT pageSizeChanged( pageSize );
} }
int QskBoundedInput::pageSize() const int QskBoundedInput::pageSize() const
{ {
return m_data->pageSize; return m_pageSize;
} }
void QskBoundedInput::stepUp() void QskBoundedInput::stepUp()
{ {
increment( m_data->stepSize ); increment( m_stepSize );
} }
void QskBoundedInput::stepDown() void QskBoundedInput::stepDown()
{ {
increment( -m_data->stepSize ); increment( -m_stepSize );
} }
void QskBoundedInput::pageUp() void QskBoundedInput::pageUp()
{ {
increment( m_data->pageSize * m_data->stepSize ); increment( m_pageSize * m_stepSize );
} }
void QskBoundedInput::pageDown() void QskBoundedInput::pageDown()
{ {
increment( -m_data->pageSize * m_data->stepSize ); increment( -m_pageSize * m_stepSize );
} }
void QskBoundedInput::setSnap( bool snap ) void QskBoundedInput::setSnap( bool snap )
{ {
if ( m_data->snap == snap ) if ( m_snap == snap )
return; return;
m_data->snap = snap; m_snap = snap;
Q_EMIT snapChanged( snap ); Q_EMIT snapChanged( snap );
if ( isComponentComplete() && snap ) if ( isComponentComplete() && snap )
@ -216,7 +103,18 @@ void QskBoundedInput::setSnap( bool snap )
bool QskBoundedInput::snap() const bool QskBoundedInput::snap() const
{ {
return m_data->snap; return m_snap;
}
void QskBoundedInput::componentComplete()
{
if ( isComponentComplete() )
{
connect( this, &QskBoundedControl::boundariesChanged,
this, &QskBoundedInput::alignInput, Qt::UniqueConnection );
}
Inherited::componentComplete();
} }
void QskBoundedInput::alignInput() void QskBoundedInput::alignInput()
@ -225,20 +123,20 @@ void QskBoundedInput::alignInput()
qreal QskBoundedInput::alignedValue( qreal value ) const qreal QskBoundedInput::alignedValue( qreal value ) const
{ {
if ( m_data->snap ) if ( m_snap )
{ {
if ( const auto step = m_data->stepSize ) if ( const auto step = m_stepSize )
value = qRound( value / step ) * step; value = qRound( value / step ) * step;
} }
return qBound( minimum(), value, maximum() ); return boundedValue( value );
} }
QskIntervalF QskBoundedInput::alignedInterval( const QskIntervalF& interval ) const QskIntervalF QskBoundedInput::alignedInterval( const QskIntervalF& interval ) const
{ {
if ( m_data->snap ) if ( m_snap )
{ {
if ( const auto step = m_data->stepSize ) if ( const auto step = m_stepSize )
{ {
const qreal lower = std::floor( interval.lowerBound() / step ) * step; const qreal lower = std::floor( interval.lowerBound() / step ) * step;
const qreal upper = std::ceil( interval.upperBound() / step ) * step; const qreal upper = std::ceil( interval.upperBound() / step ) * step;
@ -276,13 +174,13 @@ void QskBoundedInput::keyPressEvent( QKeyEvent* event )
{ {
if ( event->key() == Qt::Key_Up || event->matches( QKeySequence::MoveToNextChar ) ) if ( event->key() == Qt::Key_Up || event->matches( QKeySequence::MoveToNextChar ) )
{ {
increment( m_data->stepSize ); increment( m_stepSize );
return; return;
} }
if ( event->key() == Qt::Key_Down || event->matches( QKeySequence::MoveToPreviousChar ) ) if ( event->key() == Qt::Key_Down || event->matches( QKeySequence::MoveToPreviousChar ) )
{ {
increment( -m_data->stepSize ); increment( -m_stepSize );
return; return;
} }
} }
@ -311,10 +209,4 @@ void QskBoundedInput::wheelEvent( QWheelEvent* event )
#endif #endif
void QskBoundedInput::componentComplete()
{
Inherited::componentComplete();
adjustBoundaries( true );
}
#include "moc_QskBoundedInput.cpp" #include "moc_QskBoundedInput.cpp"

View File

@ -6,26 +6,21 @@
#ifndef QSK_BOUNDED_INPUT_H #ifndef QSK_BOUNDED_INPUT_H
#define QSK_BOUNDED_INPUT_H #define QSK_BOUNDED_INPUT_H
#include "QskControl.h" #include "QskBoundedControl.h"
class QskIntervalF; class QskIntervalF;
class QSK_EXPORT QskBoundedInput : public QskControl class QSK_EXPORT QskBoundedInput : public QskBoundedControl
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY( qreal minimum READ minimum WRITE setMinimum NOTIFY minimumChanged )
Q_PROPERTY( qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged )
Q_PROPERTY( QskIntervalF boundaries READ boundaries
WRITE setBoundaries NOTIFY boundariesChanged )
Q_PROPERTY( qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged ) Q_PROPERTY( qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged )
Q_PROPERTY( int pageSize READ pageSize WRITE setPageSize NOTIFY pageSizeChanged ) Q_PROPERTY( int pageSize READ pageSize WRITE setPageSize NOTIFY pageSizeChanged )
Q_PROPERTY( bool snap READ snap WRITE setSnap NOTIFY snapChanged ) Q_PROPERTY( bool snap READ snap WRITE setSnap NOTIFY snapChanged )
Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged ) Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged )
using Inherited = QskControl; using Inherited = QskBoundedControl;
public: public:
QSK_STATES( ReadOnly ) QSK_STATES( ReadOnly )
@ -33,14 +28,6 @@ class QSK_EXPORT QskBoundedInput : public QskControl
QskBoundedInput( QQuickItem* parent = nullptr ); QskBoundedInput( QQuickItem* parent = nullptr );
~QskBoundedInput() override; ~QskBoundedInput() override;
qreal minimum() const;
qreal maximum() const;
qreal boundaryLength() const;
void setBoundaries( qreal min, qreal max );
QskIntervalF boundaries() const;
qreal stepSize() const; qreal stepSize() const;
int pageSize() const; int pageSize() const;
@ -51,10 +38,6 @@ class QSK_EXPORT QskBoundedInput : public QskControl
bool isReadOnly() const; bool isReadOnly() const;
public Q_SLOTS: public Q_SLOTS:
void setMinimum( qreal );
void setMaximum( qreal );
void setBoundaries( const QskIntervalF& );
void setStepSize( qreal ); void setStepSize( qreal );
void setPageSize( int ); void setPageSize( int );
@ -66,10 +49,6 @@ class QSK_EXPORT QskBoundedInput : public QskControl
virtual void increment( qreal offset ) = 0; virtual void increment( qreal offset ) = 0;
Q_SIGNALS: Q_SIGNALS:
void minimumChanged( qreal );
void maximumChanged( qreal );
void boundariesChanged( const QskIntervalF& );
void stepSizeChanged( qreal ); void stepSizeChanged( qreal );
void pageSizeChanged( qreal ); void pageSizeChanged( qreal );
void snapChanged( bool ); void snapChanged( bool );
@ -84,17 +63,15 @@ class QSK_EXPORT QskBoundedInput : public QskControl
#endif #endif
void componentComplete() override; void componentComplete() override;
virtual void alignInput(); virtual void alignInput();
qreal alignedValue( qreal ) const; qreal alignedValue( qreal ) const;
QskIntervalF alignedInterval( const QskIntervalF& ) const; QskIntervalF alignedInterval( const QskIntervalF& ) const;
private: private:
void adjustBoundaries( bool increasing ); qreal m_stepSize = 0.1;
int m_pageSize = 1;
class PrivateData; bool m_snap = false;
std::unique_ptr< PrivateData > m_data;
}; };
#endif #endif

View File

@ -50,7 +50,7 @@ void QskBoundedRangeInput::setLowerValue( qreal value )
if ( isComponentComplete() ) if ( isComponentComplete() )
{ {
value = std::min( value, m_range.upperBound() ); value = std::min( value, m_range.upperBound() );
value = qBound( minimum(), value, maximum() ); value = boundedValue( value );
} }
setRange( QskIntervalF( value, m_range.upperBound() ) ); setRange( QskIntervalF( value, m_range.upperBound() ) );
@ -66,7 +66,7 @@ void QskBoundedRangeInput::setUpperValue( qreal value )
if ( isComponentComplete() ) if ( isComponentComplete() )
{ {
value = std::max( m_range.lowerBound(), value ); value = std::max( m_range.lowerBound(), value );
value = qBound( minimum(), value, maximum() ); value = boundedValue( value );
} }
setRange( QskIntervalF( m_range.lowerBound(), value ) ); setRange( QskIntervalF( m_range.lowerBound(), value ) );

View File

@ -34,9 +34,9 @@ void QskBoundedValueInput::setValueAsRatio( qreal ratio )
setValue( minimum() + ratio * boundaryLength() ); setValue( minimum() + ratio * boundaryLength() );
} }
qreal QskBoundedValueInput::valueAsRatio() const qreal QskBoundedValueInput::valueAsRatio() const
{ {
return ( m_value - minimum() ) / boundaryLength(); return valueAsRatio( m_value );
} }
void QskBoundedValueInput::setValue( qreal value ) void QskBoundedValueInput::setValue( qreal value )

View File

@ -26,6 +26,7 @@ class QSK_EXPORT QskBoundedValueInput : public QskBoundedInput
// [0.0, 1.0] // [0.0, 1.0]
qreal valueAsRatio() const; qreal valueAsRatio() const;
using QskBoundedInput::valueAsRatio;
public Q_SLOTS: public Q_SLOTS:
void setValue( qreal ); void setValue( qreal );

View File

@ -110,6 +110,7 @@ HEADERS += \
controls/QskAbstractButton.h \ controls/QskAbstractButton.h \
controls/QskAnimationHint.h \ controls/QskAnimationHint.h \
controls/QskAnimator.h \ controls/QskAnimator.h \
controls/QskBoundedControl.h \
controls/QskBoundedInput.h \ controls/QskBoundedInput.h \
controls/QskBoundedRangeInput.h \ controls/QskBoundedRangeInput.h \
controls/QskBoundedValueInput.h \ controls/QskBoundedValueInput.h \
@ -180,6 +181,7 @@ HEADERS += \
SOURCES += \ SOURCES += \
controls/QskAbstractButton.cpp \ controls/QskAbstractButton.cpp \
controls/QskAnimator.cpp \ controls/QskAnimator.cpp \
controls/QskBoundedControl.cpp \
controls/QskBoundedInput.cpp \ controls/QskBoundedInput.cpp \
controls/QskBoundedRangeInput.cpp \ controls/QskBoundedRangeInput.cpp \
controls/QskBoundedValueInput.cpp \ controls/QskBoundedValueInput.cpp \