/****************************************************************************** * QSkinny - Copyright (C) 2016 Uwe Rathmann * This file may be used under the terms of the QSkinny License, Version 1.0 *****************************************************************************/ #include "QskBoundedValueControl.h" #include "QskFunctions.h" #include "QskIntervalF.h" QSK_SYSTEM_STATE( QskBoundedValueControl, ReadOnly, ( QskAspect::FirstSystemState << 1 ) ) class QskBoundedValueControl::PrivateData { public: PrivateData() : minimum( 0.0 ) , maximum( 1.0 ) , value( 0.0 ) , stepSize( 0.1 ) , pageSize( 1 ) , snap( false ) { } qreal minimum; qreal maximum; qreal value; qreal stepSize; int pageSize; bool snap : 1; }; QskBoundedValueControl::QskBoundedValueControl( QQuickItem* parent ) : QskControl( parent ) , m_data( new PrivateData() ) { setFocusPolicy( Qt::StrongFocus ); setAcceptedMouseButtons( Qt::LeftButton ); setWheelEnabled( true ); } QskBoundedValueControl::~QskBoundedValueControl() { } void QskBoundedValueControl::setMinimum( qreal minimum ) { if ( m_data->minimum == minimum ) return; m_data->minimum = minimum; Q_EMIT minimumChanged( minimum ); if ( isComponentComplete() ) adjustBoundariesAndValue( false ); Q_EMIT boundariesChanged( boundaries() ); update(); } qreal QskBoundedValueControl::minimum() const { return m_data->minimum; } void QskBoundedValueControl::setMaximum( qreal maximum ) { if ( m_data->maximum == maximum ) return; m_data->maximum = maximum; Q_EMIT maximumChanged( maximum ); if ( isComponentComplete() ) adjustBoundariesAndValue( true ); Q_EMIT boundariesChanged( boundaries() ); update(); } qreal QskBoundedValueControl::maximum() const { return m_data->maximum; } void QskBoundedValueControl::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() ) adjustBoundariesAndValue( 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 QskBoundedValueControl::setBoundaries( const QskIntervalF& boundaries ) { setBoundaries( boundaries.lowerBound(), boundaries.upperBound() ); } QskIntervalF QskBoundedValueControl::boundaries() const { return QskIntervalF( m_data->minimum, m_data->maximum ); } void QskBoundedValueControl::adjustBoundariesAndValue( 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 ); } } qreal newValue = m_data->value; if ( m_data->snap && m_data->stepSize != 0.0 ) newValue = qRound( newValue / m_data->stepSize ) * m_data->stepSize; newValue = qBound( m_data->minimum, newValue, m_data->maximum ); if ( newValue != m_data->value ) { m_data->value = newValue; Q_EMIT valueChanged( newValue ); } } qreal QskBoundedValueControl::boundaryLength() const { return m_data->maximum - m_data->minimum; } qreal QskBoundedValueControl::fixupValue( qreal value ) const { return value; } void QskBoundedValueControl::setValueAsRatio( qreal ratio ) { ratio = qBound( 0.0, ratio, 1.0 ); setValue( m_data->minimum + ratio * ( m_data->maximum - m_data->minimum ) ); } qreal QskBoundedValueControl::valueAsRatio() const { return ( m_data->value - m_data->minimum ) / ( m_data->maximum - m_data->minimum ); } void QskBoundedValueControl::setValue( qreal value ) { if ( isComponentComplete() ) { if ( m_data->snap && m_data->stepSize != 0.0 ) value = qRound( value / m_data->stepSize ) * m_data->stepSize; value = qBound( m_data->minimum, value, m_data->maximum ); } value = fixupValue( value ); if ( !qskFuzzyCompare( value, m_data->value ) ) { m_data->value = value; Q_EMIT valueChanged( value ); update(); } } qreal QskBoundedValueControl::value() const { return m_data->value; } void QskBoundedValueControl::setStepSize( qreal stepSize ) { if ( qskFuzzyCompare( m_data->stepSize, stepSize ) ) return; m_data->stepSize = stepSize; Q_EMIT stepSizeChanged( stepSize ); update(); } qreal QskBoundedValueControl::stepSize() const { return m_data->stepSize; } void QskBoundedValueControl::setPageSize( int pageSize ) { if ( m_data->pageSize == pageSize ) return; m_data->pageSize = pageSize; Q_EMIT pageSizeChanged( pageSize ); update(); } int QskBoundedValueControl::pageSize() const { return m_data->pageSize; } void QskBoundedValueControl::setSnap( bool snap ) { if ( m_data->snap == snap ) return; m_data->snap = snap; Q_EMIT snapChanged( snap ); if ( snap ) { // Re-align value } } bool QskBoundedValueControl::snap() const { return m_data->snap; } void QskBoundedValueControl::setReadOnly( bool readOnly ) { if ( readOnly == isReadOnly() ) return; setSkinStateFlag( ReadOnly, readOnly ); // we are killing user settings here !! setFocusPolicy( readOnly ? Qt::NoFocus : Qt::StrongFocus ); setAcceptedMouseButtons( readOnly ? Qt::NoButton : Qt::LeftButton ); setWheelEnabled( !readOnly ); Q_EMIT readOnlyChanged( readOnly ); } bool QskBoundedValueControl::isReadOnly() const { return skinState() & ReadOnly; } void QskBoundedValueControl::stepUp() { setValue( m_data->value + m_data->stepSize ); } void QskBoundedValueControl::stepDown() { setValue( m_data->value - m_data->stepSize ); } void QskBoundedValueControl::pageUp() { setValue( m_data->value + m_data->stepSize * m_data->pageSize ); } void QskBoundedValueControl::pageDown() { setValue( m_data->value - m_data->stepSize * m_data->pageSize ); } void QskBoundedValueControl::keyPressEvent( QKeyEvent* event ) { if ( !isReadOnly() ) { if ( event->key() == Qt::Key_Up || event->matches( QKeySequence::MoveToNextChar ) ) { stepUp(); return; } if ( event->key() == Qt::Key_Down || event->matches( QKeySequence::MoveToPreviousChar ) ) { stepDown(); return; } } Inherited::keyPressEvent( event ); } #ifndef QT_NO_WHEELEVENT void QskBoundedValueControl::wheelEvent( QWheelEvent* event ) { if ( isReadOnly() ) return; #if QT_VERSION < 0x050e00 const int wheelDelta = event->delta(); #else const auto delta = event->angleDelta(); const int wheelDelta = ( qAbs( delta.x() ) > qAbs( delta.y() ) ) ? delta.x() : delta.y(); #endif const int steps = wheelDelta / QWheelEvent::DefaultDeltasPerStep; setValue( m_data->value + steps * m_data->stepSize ); } #endif void QskBoundedValueControl::componentComplete() { Inherited::componentComplete(); adjustBoundariesAndValue( true ); } #include "moc_QskBoundedValueControl.cpp"