disable QskSpinBox buttons when reaching minimum/maximum

This commit is contained in:
Uwe Rathmann 2023-03-01 16:09:17 +01:00
parent a4b2bcde16
commit 99079a666e
4 changed files with 83 additions and 6 deletions

View File

@ -1059,6 +1059,8 @@ void Editor::setupSpinBox()
setAlignment( subControl, Qt::AlignCenter ); setAlignment( subControl, Qt::AlignCenter );
#if 1 #if 1
setFontRole( subControl, QskSkin::TinyFont ); // until it is no graphic setFontRole( subControl, QskSkin::TinyFont ); // until it is no graphic
setColor( subControl, m_pal.themeForeground );
setColor( subControl | Q::Disabled, m_pal.darker200 );
#endif #endif
setAnimation( subControl | A::Color, 100 ); setAnimation( subControl | A::Color, 100 );
} }

View File

@ -65,6 +65,19 @@ class QskSpinBox::PrivateData
return this->repeatTimer.isActive() && ( this->key == Qt::Key_unknown ); 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 ) inline void setAutoRepeat( QskSpinBox* spinBox, qreal offset )
{ {
this->autoRepeatIncrement = offset; this->autoRepeatIncrement = offset;
@ -278,7 +291,17 @@ void QskSpinBox::mousePressEvent( QMouseEvent* event )
{ {
if ( auto subcontrol = buttonAt( this, qskMousePosition( 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(); auto offset = stepSize();
if ( event->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier ) ) if ( event->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier ) )
@ -288,7 +311,9 @@ void QskSpinBox::mousePressEvent( QMouseEvent* event )
offset = -offset; offset = -offset;
increment( offset ); increment( offset );
m_data->setAutoRepeat( this, offset );
if ( !m_data->isTimerBlocked( this, offset ) )
m_data->setAutoRepeat( this, offset );
} }
return; return;
} }
@ -339,8 +364,11 @@ void QskSpinBox::keyPressEvent( QKeyEvent* event )
{ {
increment( offset ); increment( offset );
m_data->setAutoRepeat( this, offset ); if ( !m_data->isTimerBlocked( this, offset ) )
m_data->key = event->key(); {
m_data->setAutoRepeat( this, offset );
m_data->key = event->key();
}
} }
return; return;
} }
@ -367,7 +395,11 @@ void QskSpinBox::timerEvent( QTimerEvent* event )
if ( skinStates() & ( QskSpinBox::Increasing | QskSpinBox::Decreasing ) ) if ( skinStates() & ( QskSpinBox::Increasing | QskSpinBox::Decreasing ) )
{ {
increment( m_data->autoRepeatIncrement ); 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; return;

View File

@ -91,7 +91,7 @@ class QSK_EXPORT QskSpinBox : public QskBoundedValueInput
void decimalsChanged( int ); void decimalsChanged( int );
void textChanged(); void textChanged();
private: protected:
void timerEvent( QTimerEvent* ) override; void timerEvent( QTimerEvent* ) override;
void mouseReleaseEvent( QMouseEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override;
@ -102,6 +102,7 @@ class QSK_EXPORT QskSpinBox : public QskBoundedValueInput
void keyPressEvent( QKeyEvent* ) override; void keyPressEvent( QKeyEvent* ) override;
void keyReleaseEvent( QKeyEvent* ) override; void keyReleaseEvent( QKeyEvent* ) override;
private:
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };

View File

@ -6,9 +6,36 @@
#include "QskSpinBoxSkinlet.h" #include "QskSpinBoxSkinlet.h"
#include "QskSpinBox.h" #include "QskSpinBox.h"
#include "QskFunctions.h" #include "QskFunctions.h"
#include "QskSkinStateChanger.h"
#include <qfontmetrics.h> #include <qfontmetrics.h>
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* ) QskSpinBoxSkinlet::QskSpinBoxSkinlet( QskSkin* )
{ {
setNodeRoles( { UpPanel, DownPanel, TextPanel, setNodeRoles( { UpPanel, DownPanel, TextPanel,
@ -20,6 +47,9 @@ QRectF QskSpinBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
{ {
using Q = QskSpinBox; using Q = QskSpinBox;
QskSkinStateChanger stateChanger( skinnable );
stateChanger.setStates( qskButtonStates( skinnable, subControl ) );
if ( subControl == Q::DownIndicator ) if ( subControl == Q::DownIndicator )
return skinnable->subControlContentsRect( contentsRect, Q::DownPanel ); return skinnable->subControlContentsRect( contentsRect, Q::DownPanel );
@ -43,28 +73,40 @@ QSGNode* QskSpinBoxSkinlet::updateSubNode(
{ {
using Q = QskSpinBox; using Q = QskSpinBox;
QskSkinStateChanger stateChanger( skinnable );
switch( nodeRole ) switch( nodeRole )
{ {
case UpPanel: case UpPanel:
{
stateChanger.setStates( qskButtonStates( skinnable, Q::UpPanel ) );
return updateBoxNode( skinnable, node, Q::UpPanel ); return updateBoxNode( skinnable, node, Q::UpPanel );
}
case DownPanel: case DownPanel:
{
stateChanger.setStates( qskButtonStates( skinnable, Q::DownPanel ) );
return updateBoxNode( skinnable, node, Q::DownPanel ); return updateBoxNode( skinnable, node, Q::DownPanel );
}
case UpIndicator: case UpIndicator:
{ {
stateChanger.setStates( qskButtonStates( skinnable, Q::UpIndicator ) );
return updateTextNode( skinnable, node, return updateTextNode( skinnable, node,
QStringLiteral( "+" ), Q::UpIndicator ); QStringLiteral( "+" ), Q::UpIndicator );
} }
case DownIndicator: case DownIndicator:
{ {
stateChanger.setStates( qskButtonStates( skinnable, Q::DownIndicator ) );
return updateTextNode( skinnable, node, return updateTextNode( skinnable, node,
QStringLiteral( "-" ), Q::DownIndicator ); QStringLiteral( "-" ), Q::DownIndicator );
} }
case TextPanel: case TextPanel:
{
return updateBoxNode( skinnable, node, Q::TextPanel ); return updateBoxNode( skinnable, node, Q::TextPanel );
}
case Text: case Text:
{ {