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 );
#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 );
}

View File

@ -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;

View File

@ -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;
};

View File

@ -6,9 +6,36 @@
#include "QskSpinBoxSkinlet.h"
#include "QskSpinBox.h"
#include "QskFunctions.h"
#include "QskSkinStateChanger.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* )
{
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:
{