From 9e4e31f34942ff42d6481bcf77e51143633945a4 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Sat, 13 May 2023 10:15:02 +0200 Subject: [PATCH] Windows style: Style spin box and add some use cases in skinlet --- skins/material3/QskMaterial3Skin.cpp | 2 +- skins/windows/QskWindowsSkin.cpp | 59 ++++++++++++++++++ skins/windows/icons.qrc | 2 + .../windows/icons/qvg/spin-box-arrow-down.qvg | Bin 0 -> 1135 bytes skins/windows/icons/qvg/spin-box-arrow-up.qvg | Bin 0 -> 1135 bytes skins/windows/icons/spin-box-arrow-down.svg | 4 ++ skins/windows/icons/spin-box-arrow-up.svg | 4 ++ src/controls/QskSpinBox.cpp | 2 +- src/controls/QskSpinBox.h | 3 +- src/controls/QskSpinBoxSkinlet.cpp | 58 ++++++++++++++--- src/controls/QskSpinBoxSkinlet.h | 13 ++-- 11 files changed, 130 insertions(+), 17 deletions(-) create mode 100644 skins/windows/icons/qvg/spin-box-arrow-down.qvg create mode 100644 skins/windows/icons/qvg/spin-box-arrow-up.qvg create mode 100644 skins/windows/icons/spin-box-arrow-down.svg create mode 100644 skins/windows/icons/spin-box-arrow-up.svg diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index fdbfdc8e..d0113d65 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -861,7 +861,7 @@ void Editor::setupSpinBox() { using Q = QskSpinBox; - setHint( Q::Panel | QskAspect::Style, Q::Buttons ); + setHint( Q::Panel | QskAspect::Style, Q::ButtonsLeftAndRight ); setSpacing( Q::Panel, 4_dp ); setStrutSize( Q::TextPanel, 80_dp, 40_dp ); diff --git a/skins/windows/QskWindowsSkin.cpp b/skins/windows/QskWindowsSkin.cpp index d6169122..a171fe79 100644 --- a/skins/windows/QskWindowsSkin.cpp +++ b/skins/windows/QskWindowsSkin.cpp @@ -500,6 +500,65 @@ void Editor::setupSlider() void Editor::setupSpinBox() { + using Q = QskSpinBox; + + setHint( Q::Panel | QskAspect::Style, Q::ButtonsRight ); + setStrutSize( Q::Panel, { -1, 32 } ); + setBoxBorderMetrics( Q::Panel, 1 ); + setBoxShape( Q::Panel, 3 ); + setPadding( Q::Panel, { 11, 0, 11, 0 } ); + + setGradient( Q::Panel, theme.palette.fillColor.control.defaultColor ); + setBoxBorderGradient( Q::Panel, theme.palette.elevation.control.border, + theme.palette.fillColor.control.defaultColor ); + + setAlignment( Q::Text, Qt::AlignLeft ); + setFontRole( Q::Text, QskWindowsSkin::Body ); + setColor( Q::Text, theme.palette.fillColor.text.primary ); + + setPadding( Q::TextPanel, { 11, 5, 0, 0 } ); + + setStrutSize( Q::UpPanel, 16, 16 ); + setStrutSize( Q::DownPanel, 16, 16 ); + + setStrutSize( Q::UpPanel, 32, 20 ); + setPadding( Q::UpPanel, { 11, 7, 11, 7 } ); + setStrutSize( Q::DownPanel, 34, 20 ); + setPadding( Q::DownPanel, { 11, 7, 13, 7 } ); + + setSymbol( Q::UpIndicator, symbol( "spin-box-arrow-up" ) ); + setSymbol( Q::DownIndicator, symbol( "spin-box-arrow-down" ) ); + + setGraphicRole( Q::UpIndicator, QskWindowsSkin::GraphicRoleFillColorTextSecondary ); + setGraphicRole( Q::DownIndicator, QskWindowsSkin::GraphicRoleFillColorTextSecondary ); + + // Hovered: + + setGradient( Q::Panel | Q::Hovered, theme.palette.fillColor.control.secondary ); + setBoxBorderGradient( Q::Panel | Q::Hovered, theme.palette.elevation.textControl.border, + theme.palette.fillColor.control.secondary ); + + + // Focused (Pressed doesn't exist yet): + + setBoxBorderMetrics( Q::Panel | Q::Focused, { 1, 1, 1, 2 } ); + + setGradient( Q::Panel | Q::Focused, theme.palette.fillColor.control.inputActive ); + + auto gradient = theme.palette.elevation.textControl.border; + gradient.at( 1 ) = theme.palette.fillColor.accent.defaultColor; + + setBoxBorderGradient( Q::Panel | Q::Focused, gradient, theme.palette.fillColor.control.inputActive ); + + // Disabled: + + setGradient( Q::Panel | Q::Disabled, theme.palette.fillColor.control.disabled ); + setBoxBorderColors( Q::Panel | Q::Disabled, theme.palette.strokeColor.controlStroke.defaultColor ); + + setColor( Q::Text | Q::Disabled, theme.palette.fillColor.text.disabled ); + + setGraphicRole( Q::UpIndicator | Q::Disabled, QskWindowsSkin::GraphicRoleFillColorTextDisabled ); + setGraphicRole( Q::DownIndicator | Q::Disabled, QskWindowsSkin::GraphicRoleFillColorTextDisabled ); } void Editor::setupTabBar() diff --git a/skins/windows/icons.qrc b/skins/windows/icons.qrc index b84bca05..97c702ce 100644 --- a/skins/windows/icons.qrc +++ b/skins/windows/icons.qrc @@ -4,5 +4,7 @@ icons/qvg/combo-box-arrow-closed.qvg icons/qvg/combo-box-arrow-open.qvg icons/qvg/segmented-button-check.qvg + icons/qvg/spin-box-arrow-down.qvg + icons/qvg/spin-box-arrow-up.qvg diff --git a/skins/windows/icons/qvg/spin-box-arrow-down.qvg b/skins/windows/icons/qvg/spin-box-arrow-down.qvg new file mode 100644 index 0000000000000000000000000000000000000000..2825e1fbbd0b7fd4dd919b2c0f377d7e6811a94d GIT binary patch literal 1135 zcmWFx_I77rU|?ouVrB?nu>SyL0|6uB|Njsc16&NoN2g(W(8XbVn7ji_0EuR#g+)N~ z*+F(Fg9!TvAQDJ_g3v&c2`=^_foZi z6UAEl*AN=4_bEi){v|{`Slx>Qj6C^O-1aYkJP2U6e*O{)G;|I-e<_T z-Mt3cJO?EnhTuonRFLg;P;vkph$P13pj7;SjjZM!Br#?Or3L?|tCWPGns@B~LDBoE zDE2D7`Tv^T3nlyn>o&X&Nv=?gLS4j9k#Gv+mgM<%I zjL|`q_kWZ2zS9n35E>}PIJOgS5yl4&cB*B^ViKPyhg}U;+Tz{On!; literal 0 HcmV?d00001 diff --git a/skins/windows/icons/qvg/spin-box-arrow-up.qvg b/skins/windows/icons/qvg/spin-box-arrow-up.qvg new file mode 100644 index 0000000000000000000000000000000000000000..3ae75f325009d6b145bd2ea1483a625bd41e0a35 GIT binary patch literal 1135 zcmWFx_I77rU|?ouVrB?nu>SyL0|6uB|Njsc16&NoN2g(W(8XbVn7ji_0EuR#g+)N~ z*+F(Fg9!TvAd-Q>LAU`-0|_RCm;}S}qiewaw|}Vr-)v1vxr5L?hKt+9BZ2Ce?H~95 z-}6MV)f8`0MUm)`wgzdn3>~F>Y%Z)hk9;DYncm~*P z`x`(W1TZ^@Kp043Ob#OH|0Aq|cOr=a)gAn==ka1Wig}{E|C_Y;okp^k(Lw3h|AV6U zQ<2=qEC|7&(H6n{8?Ljn{A2>&9)8lcW&U_yvJ2fGOWcrbk=4B8APVF`0MI-KFbhcxsF#N!_|Y{LBr#?O z#rq5yx4YM%n5Vdt!S0p9YzKtBjPNl1(*9?s@}fCF!x`;Ang8Qh_gfoD9h3b>cCb9M zdG_z^|9zg&`W4w;`!`_cF(8RC*}piz$dg~ijU>iw|MUZcv-G`Y6!T!|1>rs>c)CIg oKScUNgfl{{0pb7%$q34qf$%&?i|pcnY#)@($UuVv0BAN70Ooe#I{*Lx literal 0 HcmV?d00001 diff --git a/skins/windows/icons/spin-box-arrow-down.svg b/skins/windows/icons/spin-box-arrow-down.svg new file mode 100644 index 00000000..a3ffcd48 --- /dev/null +++ b/skins/windows/icons/spin-box-arrow-down.svg @@ -0,0 +1,4 @@ + + + + diff --git a/skins/windows/icons/spin-box-arrow-up.svg b/skins/windows/icons/spin-box-arrow-up.svg new file mode 100644 index 00000000..34301711 --- /dev/null +++ b/skins/windows/icons/spin-box-arrow-up.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/controls/QskSpinBox.cpp b/src/controls/QskSpinBox.cpp index 693d6b76..9959cac7 100644 --- a/src/controls/QskSpinBox.cpp +++ b/src/controls/QskSpinBox.cpp @@ -173,7 +173,7 @@ void QskSpinBox::resetDecoration() QskSpinBox::Decoration QskSpinBox::decoration() const { - return flagHint< QskSpinBox::Decoration >( aspectDecoration(), Buttons ); + return flagHint< QskSpinBox::Decoration >( aspectDecoration(), ButtonsLeftAndRight ); } void QskSpinBox::setTextAlignment( Qt::Alignment alignment ) diff --git a/src/controls/QskSpinBox.h b/src/controls/QskSpinBox.h index d1066109..5837e951 100644 --- a/src/controls/QskSpinBox.h +++ b/src/controls/QskSpinBox.h @@ -37,7 +37,8 @@ class QSK_EXPORT QskSpinBox : public QskBoundedValueInput { NoDecoration, - Buttons, + ButtonsLeftAndRight, + ButtonsRight, UpDownControl }; Q_ENUM( Decoration ) diff --git a/src/controls/QskSpinBoxSkinlet.cpp b/src/controls/QskSpinBoxSkinlet.cpp index f8a5df08..b0394f30 100644 --- a/src/controls/QskSpinBoxSkinlet.cpp +++ b/src/controls/QskSpinBoxSkinlet.cpp @@ -38,8 +38,8 @@ static inline QskAspect::States qskButtonStates( QskSpinBoxSkinlet::QskSpinBoxSkinlet( QskSkin* ) { - setNodeRoles( { UpPanel, DownPanel, TextPanel, - UpIndicator, DownIndicator, Text } ); + setNodeRoles( { PanelRole, UpPanelRole, DownPanelRole, TextPanelRole, + UpIndicatorRole, DownIndicatorRole, TextRole } ); } QRectF QskSpinBoxSkinlet::subControlRect( const QskSkinnable* skinnable, @@ -50,6 +50,9 @@ QRectF QskSpinBoxSkinlet::subControlRect( const QskSkinnable* skinnable, QskSkinStateChanger stateChanger( skinnable ); stateChanger.setStates( qskButtonStates( skinnable, subControl ) ); + if ( subControl == Q::Panel ) + return contentsRect; + if ( subControl == Q::DownIndicator ) return skinnable->subControlContentsRect( contentsRect, Q::DownPanel ); @@ -77,36 +80,41 @@ QSGNode* QskSpinBoxSkinlet::updateSubNode( switch( nodeRole ) { - case UpPanel: + case PanelRole: + { + return updateBoxNode( skinnable, node, Q::Panel ); + } + + case UpPanelRole: { stateChanger.setStates( qskButtonStates( skinnable, Q::UpPanel ) ); return updateBoxNode( skinnable, node, Q::UpPanel ); } - case DownPanel: + case DownPanelRole: { stateChanger.setStates( qskButtonStates( skinnable, Q::DownPanel ) ); return updateBoxNode( skinnable, node, Q::DownPanel ); } - case UpIndicator: + case UpIndicatorRole: { stateChanger.setStates( qskButtonStates( skinnable, Q::UpIndicator ) ); return updateSymbolNode( skinnable, node, Q::UpIndicator ); } - case DownIndicator: + case DownIndicatorRole: { stateChanger.setStates( qskButtonStates( skinnable, Q::DownIndicator ) ); return updateSymbolNode( skinnable, node, Q::DownIndicator ); } - case TextPanel: + case TextPanelRole: { return updateBoxNode( skinnable, node, Q::TextPanel ); } - case Text: + case TextRole: { auto spinBox = static_cast< const QskSpinBox* >( skinnable ); @@ -141,6 +149,16 @@ QRectF QskSpinBoxSkinlet::textPanelRect( if ( w > 0.0 ) r.setRight( r.right() - spacing - w ); } + else if ( decoration == Q::ButtonsRight ) + { + const auto w1 = subControlRect( skinnable, rect, Q::DownPanel ).width(); + if ( w1 > 0.0 ) + r.setRight( r.right() - w1 - spacing ); + + const auto w2 = subControlRect( skinnable, rect, Q::UpPanel ).width(); + if ( w2 > 0.0 ) + r.setRight( r.right() - w2 - spacing ); + } else { const auto w1 = subControlRect( skinnable, rect, Q::DownPanel ).width(); @@ -180,6 +198,30 @@ QRectF QskSpinBoxSkinlet::buttonRect( const QskSkinnable* skinnable, x = rect.right() - w; y = ( subControl == Q::UpPanel ) ? rect.top() : rect.bottom() - h; } + else if ( decoration == Q::ButtonsRight ) + { + const auto hint = spinBox->strutSizeHint( subControl ); + + h = hint.height(); + if ( h <= 0.0 ) + h = rect.height(); + + w = hint.width(); + if ( w <= 0.0 ) + w = h; + + if( subControl == Q::UpPanel ) + { + const auto downRect = buttonRect( skinnable, rect, Q::DownPanel ); + x = downRect.left() - w; + } + else + { + x = rect.right() - w; + } + + y = 0.5 * ( rect.height() - h ); + } else { const auto hint = spinBox->strutSizeHint( subControl ); diff --git a/src/controls/QskSpinBoxSkinlet.h b/src/controls/QskSpinBoxSkinlet.h index 72eb8840..81fc3fdb 100644 --- a/src/controls/QskSpinBoxSkinlet.h +++ b/src/controls/QskSpinBoxSkinlet.h @@ -18,14 +18,15 @@ class QSK_EXPORT QskSpinBoxSkinlet : public QskSkinlet enum NodeRole { - TextPanel, - Text, + PanelRole, + TextPanelRole, + TextRole, - UpPanel, - UpIndicator, + UpPanelRole, + UpIndicatorRole, - DownPanel, - DownIndicator, + DownPanelRole, + DownIndicatorRole, RoleCount };