From b414afdded2e4d625224cfb43de2425cd776878f Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 15 Oct 2024 17:33:26 +0200 Subject: [PATCH] spin box: Improve for M3 Resolves #398 --- designsystems/material3/QskMaterial3Skin.cpp | 11 +++++-- src/controls/QskSpinBox.cpp | 32 ++++++++++++++++++++ src/controls/QskSpinBox.h | 4 +++ src/controls/QskSpinBoxSkinlet.cpp | 26 ++++++++++++---- 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/designsystems/material3/QskMaterial3Skin.cpp b/designsystems/material3/QskMaterial3Skin.cpp index a5f4c4955..4240f2199 100644 --- a/designsystems/material3/QskMaterial3Skin.cpp +++ b/designsystems/material3/QskMaterial3Skin.cpp @@ -898,6 +898,7 @@ void Editor::setupSpinBox() setHint( Q::Panel | QskAspect::Style, Q::ButtonsLeftAndRight ); + setStrutSize( Q::Panel, -1.0, 48_dp ); setBoxShape( Q::Panel, 4_dp ); setBoxBorderMetrics( Q::Panel, 1_dp ); @@ -909,21 +910,25 @@ void Editor::setupSpinBox() setSpacing( Q::Panel, 4_dp ); setStrutSize( Q::TextPanel, 80_dp, 40_dp ); - setStrutSize( Q::UpPanel, 40_dp,40_dp ); + setStrutSize( Q::UpPanel, 40_dp, 40_dp ); setStrutSize( Q::DownPanel, 40_dp, 40_dp ); setAlignment( Q::Text, Qt::AlignCenter ); for( const auto subControl : { Q::DownPanel, Q::UpPanel, Q::TextPanel } ) { - setBoxShape( subControl, 4_dp ); setBoxBorderMetrics( subControl, 1_dp ); } + setBoxShape( Q::TextPanel, 4_dp ); + + setBoxShape( Q::DownPanel, 100, Qt::RelativeSize ); + setBoxShape( Q::UpPanel, 100, Qt::RelativeSize ); + for( const auto subControl : { Q::DownPanel, Q::UpPanel } ) { setGradient( subControl | Q::Hovered, m_pal.primary8 ); - setPadding( subControl, 10 ); + setPadding( subControl, 11_dp ); } { diff --git a/src/controls/QskSpinBox.cpp b/src/controls/QskSpinBox.cpp index 6195062f0..fe38450ae 100644 --- a/src/controls/QskSpinBox.cpp +++ b/src/controls/QskSpinBox.cpp @@ -139,6 +139,8 @@ QskSpinBox::QskSpinBox( qreal min, qreal max, qreal stepSize, QQuickItem* parent setBoundaries( min, max ); setStepSize( stepSize ); + setAcceptHoverEvents( true ); + setAcceptedMouseButtons( Qt::LeftButton ); setFocusPolicy( Qt::StrongFocus ); @@ -302,6 +304,36 @@ void QskSpinBox::mouseUngrabEvent() m_data->setAutoRepeat( this, 0.0 ); } +void QskSpinBox::hoverEnterEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( UpPanel | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); + setSkinHint( DownPanel | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); + + update(); +} + +void QskSpinBox::hoverMoveEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( UpPanel | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); + setSkinHint( DownPanel | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); + + update(); +} + +void QskSpinBox::hoverLeaveEvent( QHoverEvent* ) +{ + using A = QskAspect; + + setSkinHint( UpPanel | Hovered | A::Metric | A::Position, QPointF() ); + setSkinHint( DownPanel | Hovered | A::Metric | A::Position, QPointF() ); + + update(); +} + void QskSpinBox::keyPressEvent( QKeyEvent* event ) { if ( !isReadOnly() && !m_data->repeatTimer.isActive() ) diff --git a/src/controls/QskSpinBox.h b/src/controls/QskSpinBox.h index 38f62c35a..7d2d8b438 100644 --- a/src/controls/QskSpinBox.h +++ b/src/controls/QskSpinBox.h @@ -75,6 +75,10 @@ class QSK_EXPORT QskSpinBox : public QskBoundedValueInput void mousePressEvent( QMouseEvent* ) override; void mouseUngrabEvent() override; + void hoverEnterEvent( QHoverEvent* ) override; + void hoverMoveEvent( QHoverEvent* ) override; + void hoverLeaveEvent( QHoverEvent* ) override; + void keyPressEvent( QKeyEvent* ) override; void keyReleaseEvent( QKeyEvent* ) override; diff --git a/src/controls/QskSpinBoxSkinlet.cpp b/src/controls/QskSpinBoxSkinlet.cpp index 3af7272cb..581cbc166 100644 --- a/src/controls/QskSpinBoxSkinlet.cpp +++ b/src/controls/QskSpinBoxSkinlet.cpp @@ -14,22 +14,39 @@ static inline QskAspect::States qskButtonStates( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) { using Q = QskSpinBox; + using A = QskAspect; auto spinBox = static_cast< const QskSpinBox* >( skinnable ); auto states = spinBox->skinStates(); - if ( spinBox->isEnabled() && !spinBox->isWrapping() ) + if ( spinBox->isEnabled() ) { if ( subControl == Q::DownIndicator || subControl == Q::DownPanel ) { - if ( spinBox->value() <= spinBox->minimum() ) + if ( !spinBox->isWrapping() && spinBox->value() <= spinBox->minimum() ) states |= QskControl::Disabled; + + const auto cursorPos = spinBox->effectiveSkinHint( + Q::DownPanel | Q::Hovered | A::Metric | A::Position ).toPointF(); + + if( !cursorPos.isNull() && spinBox->subControlRect( Q::DownPanel ).contains( cursorPos ) ) + { + states |= Q::Hovered; + } } else if ( subControl == Q::UpIndicator || subControl == Q::UpPanel ) { - if ( spinBox->value() >= spinBox->maximum() ) + if ( !spinBox->isWrapping() && spinBox->value() >= spinBox->maximum() ) states |= QskControl::Disabled; + + const auto cursorPos = spinBox->effectiveSkinHint( + Q::UpPanel | Q::Hovered | A::Metric | A::Position ).toPointF(); + + if( !cursorPos.isNull() && spinBox->subControlRect( Q::UpPanel ).contains( cursorPos ) ) + { + states |= Q::Hovered; + } } } @@ -47,9 +64,6 @@ QRectF QskSpinBoxSkinlet::subControlRect( const QskSkinnable* skinnable, { using Q = QskSpinBox; - QskSkinStateChanger stateChanger( skinnable ); - stateChanger.setStates( qskButtonStates( skinnable, subControl ) ); - if ( subControl == Q::Panel ) return contentsRect;