diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 13ddaa20..1facfb60 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -1059,6 +1059,8 @@ void Editor::setupSpinBox() setAlignment( subControl, Qt::AlignCenter ); #if 1 setFontRole( subControl, QskSkin::TinyFont ); // until it is no graphic + setColor( subControl, m_pal.themeForeground ); + setColor( subControl | Q::Disabled, m_pal.darker200 ); #endif setAnimation( subControl | A::Color, 100 ); } diff --git a/src/controls/QskSpinBox.cpp b/src/controls/QskSpinBox.cpp index 46bd240c..34fd4fbe 100644 --- a/src/controls/QskSpinBox.cpp +++ b/src/controls/QskSpinBox.cpp @@ -65,6 +65,19 @@ class QskSpinBox::PrivateData return this->repeatTimer.isActive() && ( this->key == Qt::Key_unknown ); } + inline bool isTimerBlocked( QskSpinBox* spinBox, qreal offset ) const + { + if ( !this->wrapping ) + { + if ( offset >= 0.0 ) + return spinBox->value() >= spinBox->maximum(); + else + return spinBox->value() <= spinBox->minimum(); + } + + return false; + } + inline void setAutoRepeat( QskSpinBox* spinBox, qreal offset ) { this->autoRepeatIncrement = offset; @@ -278,7 +291,17 @@ void QskSpinBox::mousePressEvent( QMouseEvent* event ) { if ( auto subcontrol = buttonAt( this, qskMousePosition( event ) ) ) { - if ( !m_data->repeatTimer.isActive() ) + bool acceptPress = !m_data->repeatTimer.isActive(); + + if ( acceptPress && !m_data->wrapping ) + { + if ( subcontrol == QskSpinBox::DownPanel ) + acceptPress = value() > minimum(); + else + acceptPress = value() < maximum(); + } + + if ( acceptPress ) { auto offset = stepSize(); if ( event->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier ) ) @@ -288,7 +311,9 @@ void QskSpinBox::mousePressEvent( QMouseEvent* event ) offset = -offset; increment( offset ); - m_data->setAutoRepeat( this, offset ); + + if ( !m_data->isTimerBlocked( this, offset ) ) + m_data->setAutoRepeat( this, offset ); } return; } @@ -339,8 +364,11 @@ void QskSpinBox::keyPressEvent( QKeyEvent* event ) { increment( offset ); - m_data->setAutoRepeat( this, offset ); - m_data->key = event->key(); + if ( !m_data->isTimerBlocked( this, offset ) ) + { + m_data->setAutoRepeat( this, offset ); + m_data->key = event->key(); + } } return; } @@ -367,7 +395,11 @@ void QskSpinBox::timerEvent( QTimerEvent* event ) if ( skinStates() & ( QskSpinBox::Increasing | QskSpinBox::Decreasing ) ) { increment( m_data->autoRepeatIncrement ); - m_data->repeatTimer.start( m_data->autoRepeatInterval, this ); + + if ( m_data->isTimerBlocked( this, m_data->autoRepeatIncrement ) ) + m_data->setAutoRepeat( this, 0.0 ); + else + m_data->repeatTimer.start( m_data->autoRepeatInterval, this ); } return; diff --git a/src/controls/QskSpinBox.h b/src/controls/QskSpinBox.h index 6876c80b..c6d54683 100644 --- a/src/controls/QskSpinBox.h +++ b/src/controls/QskSpinBox.h @@ -91,7 +91,7 @@ class QSK_EXPORT QskSpinBox : public QskBoundedValueInput void decimalsChanged( int ); void textChanged(); - private: + protected: void timerEvent( QTimerEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override; @@ -102,6 +102,7 @@ class QSK_EXPORT QskSpinBox : public QskBoundedValueInput void keyPressEvent( QKeyEvent* ) override; void keyReleaseEvent( QKeyEvent* ) override; + private: class PrivateData; std::unique_ptr< PrivateData > m_data; }; diff --git a/src/controls/QskSpinBoxSkinlet.cpp b/src/controls/QskSpinBoxSkinlet.cpp index 00dfcb84..162f18ad 100644 --- a/src/controls/QskSpinBoxSkinlet.cpp +++ b/src/controls/QskSpinBoxSkinlet.cpp @@ -6,9 +6,36 @@ #include "QskSpinBoxSkinlet.h" #include "QskSpinBox.h" #include "QskFunctions.h" +#include "QskSkinStateChanger.h" #include +static inline QskAspect::States qskButtonStates( + const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) +{ + using Q = QskSpinBox; + + auto spinBox = static_cast< const QskSpinBox* >( skinnable ); + + auto states = spinBox->skinStates(); + + if ( spinBox->isEnabled() && !spinBox->isWrapping() ) + { + if ( subControl == Q::DownIndicator || subControl == Q::DownPanel ) + { + if ( spinBox->value() <= spinBox->minimum() ) + states |= QskControl::Disabled; + } + else if ( subControl == Q::UpIndicator || subControl == Q::UpPanel ) + { + if ( spinBox->value() >= spinBox->maximum() ) + states |= QskControl::Disabled; + } + } + + return states; +} + QskSpinBoxSkinlet::QskSpinBoxSkinlet( QskSkin* ) { setNodeRoles( { UpPanel, DownPanel, TextPanel, @@ -20,6 +47,9 @@ QRectF QskSpinBoxSkinlet::subControlRect( const QskSkinnable* skinnable, { using Q = QskSpinBox; + QskSkinStateChanger stateChanger( skinnable ); + stateChanger.setStates( qskButtonStates( skinnable, subControl ) ); + if ( subControl == Q::DownIndicator ) return skinnable->subControlContentsRect( contentsRect, Q::DownPanel ); @@ -43,28 +73,40 @@ QSGNode* QskSpinBoxSkinlet::updateSubNode( { using Q = QskSpinBox; + QskSkinStateChanger stateChanger( skinnable ); + switch( nodeRole ) { case UpPanel: + { + stateChanger.setStates( qskButtonStates( skinnable, Q::UpPanel ) ); return updateBoxNode( skinnable, node, Q::UpPanel ); + } case DownPanel: + { + stateChanger.setStates( qskButtonStates( skinnable, Q::DownPanel ) ); return updateBoxNode( skinnable, node, Q::DownPanel ); + } case UpIndicator: { + stateChanger.setStates( qskButtonStates( skinnable, Q::UpIndicator ) ); return updateTextNode( skinnable, node, QStringLiteral( "+" ), Q::UpIndicator ); } case DownIndicator: { + stateChanger.setStates( qskButtonStates( skinnable, Q::DownIndicator ) ); return updateTextNode( skinnable, node, QStringLiteral( "-" ), Q::DownIndicator ); } case TextPanel: + { return updateBoxNode( skinnable, node, Q::TextPanel ); + } case Text: {