From 01ea49fe02b25417d81cdf6d859ca68440998885 Mon Sep 17 00:00:00 2001 From: Clemens Manert Date: Fri, 27 Aug 2021 09:09:10 +0200 Subject: [PATCH] Add ripple to SwitchButton (#123) --- skins/material/QskMaterialSkin.cpp | 18 ++++++++ src/controls/QskSwitchButton.cpp | 1 + src/controls/QskSwitchButton.h | 2 +- src/controls/QskSwitchButtonSkinlet.cpp | 59 +++++++++++++++++++++++-- src/controls/QskSwitchButtonSkinlet.h | 4 +- 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/skins/material/QskMaterialSkin.cpp b/skins/material/QskMaterialSkin.cpp index eac89e85..94a8a1d0 100644 --- a/skins/material/QskMaterialSkin.cpp +++ b/skins/material/QskMaterialSkin.cpp @@ -520,6 +520,24 @@ void Editor::setupSwitchButton() setBoxBorderColors( Q::Handle, m_pal.darker200 ); setBoxBorderColors( Q::Handle | Q::Disabled, m_pal.darker125 ); + setBoxShape( Q::Ripple, 100, Qt::RelativeSize ); + setStrutSize( Q::Ripple, 2 * handleSize, 2 * handleSize ); + setGradient( Q::Ripple, QColor(0,0,0,0) ); + + setGradient( Q::Ripple | Q::Checked | Q::Hovered, + QColor(m_pal.accentColor.red(), m_pal.accentColor.green(), m_pal.accentColor.blue(), 50) ); + setGradient( Q::Ripple | Q::Checked | Q::Focused, + QColor(m_pal.accentColor.red(), m_pal.accentColor.green(), m_pal.accentColor.blue(), 100) ); + setGradient( Q::Ripple | Q::Checked | Q::Pressed, + QColor(m_pal.accentColor.red(), m_pal.accentColor.green(), m_pal.accentColor.blue(), 150) ); + + setGradient( Q::Ripple | Q::Hovered, + QColor(m_pal.darker125.red(), m_pal.darker125.green(), m_pal.darker125.blue(), 100 ) ); + setGradient( Q::Ripple | Q::Focused, + QColor(m_pal.darker125.red(), m_pal.darker125.green(), m_pal.darker125.blue(), 150 ) ); + setGradient( Q::Ripple | Q::Pressed, + QColor(m_pal.darker125.red(), m_pal.darker125.green(), m_pal.darker125.blue(), 200) ); + for( auto state : { A::NoState, Q::Disabled } ) { auto aspect = Q::Handle | state | A::Position; diff --git a/src/controls/QskSwitchButton.cpp b/src/controls/QskSwitchButton.cpp index a30079d6..78700579 100644 --- a/src/controls/QskSwitchButton.cpp +++ b/src/controls/QskSwitchButton.cpp @@ -2,6 +2,7 @@ QSK_SUBCONTROL( QskSwitchButton, Handle ) QSK_SUBCONTROL( QskSwitchButton, Groove ) +QSK_SUBCONTROL( QskSwitchButton, Ripple ) struct QskSwitchButton::PrivateData { diff --git a/src/controls/QskSwitchButton.h b/src/controls/QskSwitchButton.h index ad23c0a8..c88da791 100644 --- a/src/controls/QskSwitchButton.h +++ b/src/controls/QskSwitchButton.h @@ -17,7 +17,7 @@ class QSK_EXPORT QskSwitchButton : public QskAbstractButton WRITE setInverted NOTIFY invertedChanged FINAL ) public: - QSK_SUBCONTROLS( Groove, Handle ) + QSK_SUBCONTROLS( Groove, Handle, Ripple ) QskSwitchButton( Qt::Orientation, QQuickItem* parent = nullptr ); QskSwitchButton( QQuickItem* parent = nullptr ); diff --git a/src/controls/QskSwitchButtonSkinlet.cpp b/src/controls/QskSwitchButtonSkinlet.cpp index 1a31b35a..e5dfe7d0 100644 --- a/src/controls/QskSwitchButtonSkinlet.cpp +++ b/src/controls/QskSwitchButtonSkinlet.cpp @@ -27,7 +27,7 @@ static inline qreal qskEffectivePosition( const QskSwitchButton* switchButton ) QskSwitchButtonSkinlet::QskSwitchButtonSkinlet( QskSkin* skin ) : Inherited( skin ) { - setNodeRoles( { GrooveRole, HandleRole } ); + setNodeRoles( { GrooveRole, HandleRole, RippleRole } ); } QskSwitchButtonSkinlet::~QskSwitchButtonSkinlet() @@ -39,7 +39,6 @@ QRectF QskSwitchButtonSkinlet::subControlRect( const QskSkinnable* skinnable, { using Q = QskSwitchButton; - if ( subControl == Q::Handle ) { return handleRect( skinnable, contentsRect ); @@ -50,6 +49,12 @@ QRectF QskSwitchButtonSkinlet::subControlRect( const QskSkinnable* skinnable, return grooveRect( skinnable, contentsRect ); } + if ( subControl == Q::Ripple ) + { + return rippleRect( skinnable, contentsRect ); + } + + return Inherited::subControlRect( skinnable, contentsRect, subControl ); } @@ -59,8 +64,13 @@ QSizeF QskSwitchButtonSkinlet::sizeHint( const QskSkinnable* skinnable, if ( which != Qt::PreferredSize ) return QSizeF(); - auto hint = skinnable->strutSizeHint( QskSwitchButton::Groove ); - hint = hint.expandedTo( skinnable->strutSizeHint( QskSwitchButton::Handle ) ); + auto groovehint = skinnable->strutSizeHint( QskSwitchButton::Groove ); + auto handleHint = skinnable->strutSizeHint( QskSwitchButton::Handle ); + auto rippleHint = skinnable->strutSizeHint( QskSwitchButton::Ripple ); + + auto hint = groovehint.expandedTo( groovehint + rippleHint - handleHint ); + hint = hint.expandedTo( rippleHint ); + hint = hint.expandedTo( handleHint ); return hint; } @@ -72,6 +82,9 @@ QSGNode* QskSwitchButtonSkinlet::updateSubNode( const QskSkinnable* skinnable, switch ( nodeRole ) { + case RippleRole: + return updateBoxNode( skinnable, node, Q::Ripple ); + case HandleRole: return updateBoxNode( skinnable, node, Q::Handle ); @@ -154,4 +167,42 @@ QRectF QskSwitchButtonSkinlet::handleRect( return r; } +QRectF QskSwitchButtonSkinlet::rippleRect( + const QskSkinnable* skinnable, const QRectF& contentsRect ) const +{ + using Q = QskSwitchButton; + + const auto switchButton = static_cast< const Q* >( skinnable ); + + const auto grooveRect = subControlRect( skinnable, contentsRect, Q::Groove ); + const auto pos = qskEffectivePosition( switchButton ); + const auto sizeHandle = skinnable->strutSizeHint( Q::Handle ); + const auto sizeRipple = skinnable->strutSizeHint( Q::Ripple ); + + qreal cx, cy; + + if( switchButton->orientation() == Qt::Vertical ) + { + const qreal y0 = grooveRect.y() + 0.5 * sizeHandle.height(); + const qreal h = grooveRect.height() - sizeHandle.height(); + + cx = grooveRect.x() + 0.5 * grooveRect.width(); + cy = y0 + pos * h; + } + else + { + const qreal x0 = grooveRect.x() + 0.5 * sizeHandle.width(); + const qreal w = grooveRect.width() - sizeHandle.width(); + + cx = x0 + pos * w; + cy = grooveRect.y() + 0.5 * grooveRect.height(); + } + + QRectF r; + r.setSize( sizeRipple ); + r.moveCenter( QPointF( cx, cy ) ); + + return r; +} + #include "moc_QskSwitchButtonSkinlet.cpp" diff --git a/src/controls/QskSwitchButtonSkinlet.h b/src/controls/QskSwitchButtonSkinlet.h index e4cbe4fb..188ad763 100644 --- a/src/controls/QskSwitchButtonSkinlet.h +++ b/src/controls/QskSwitchButtonSkinlet.h @@ -18,7 +18,8 @@ class QSK_EXPORT QskSwitchButtonSkinlet : public QskSkinlet enum NodeRole { GrooveRole, - HandleRole + HandleRole, + RippleRole, }; Q_INVOKABLE QskSwitchButtonSkinlet( QskSkin* = nullptr ); @@ -37,6 +38,7 @@ class QSK_EXPORT QskSwitchButtonSkinlet : public QskSkinlet private: QRectF grooveRect( const QskSkinnable*, const QRectF& ) const; QRectF handleRect( const QskSkinnable*, const QRectF& ) const; + QRectF rippleRect( const QskSkinnable*, const QRectF& ) const; }; #endif