From d27a19ba579d20ee17340c9341526627365593b4 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 09:45:07 +0200 Subject: [PATCH 01/60] unblocking the fluent2 skins --- src/controls/QskSkinManager.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/controls/QskSkinManager.cpp b/src/controls/QskSkinManager.cpp index 5100c05c..048a4757 100644 --- a/src/controls/QskSkinManager.cpp +++ b/src/controls/QskSkinManager.cpp @@ -83,10 +83,6 @@ namespace const auto factoryData = pluginData.value( TokenData ).toObject(); m_factoryId = factoryData.value( TokenFactoryId ).toString().toLower(); -#if 1 - if ( m_factoryId == "fluent2factory" ) - return false; // we need to solve a couple of problems first -#endif if ( m_factoryId.isEmpty() ) { // Creating a dummy factory id From ee34ea6194238cdf25c838932d4572b1178fbda0 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 16:43:30 +0200 Subject: [PATCH 02/60] broken progressBar settings fixed --- skins/squiek/QskSquiekSkin.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 907d50a5..dc006a89 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -521,13 +521,15 @@ void Editor::setupProgressBar() using A = QskAspect; using Q = QskProgressBar; - setMetric( Q::Groove | A::Size, 8 ); - setPadding( Q::Groove, 0 ); - setGradient( Q::Groove, m_pal.darker200 ); - setBoxShape( Q::Groove, 4 ); + for ( auto subControl : { Q::Groove, Q::Bar } ) + { + setMetric( subControl | A::Size, 6 ); + setPadding( subControl, 0 ); + setBoxShape( subControl, 4 ); + } + setGradient( Q::Groove, m_pal.darker200 ); setGradient( Q::Bar, m_pal.highlighted ); - setBoxShape( Q::Bar, 4 ); } void Editor::setupFocusIndicator() From b7f02b558eb052519b5a4eaf2cc19f0ac595920d Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 16:52:42 +0200 Subject: [PATCH 03/60] expressions shortened --- skins/fluent2/QskFluent2Skin.cpp | 446 +++++++++++++++++-------------- 1 file changed, 242 insertions(+), 204 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index e72ff49a..70b9ba99 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -170,15 +170,19 @@ void Editor::setupBox() using Q = QskBox; using A = QskAspect; - setGradient( Q::Panel, theme.palette.background.fillColor.solidBackground.base ); - setGradient( Q::Panel | A::Header, theme.palette.background.fillColor.solidBackground.tertiary ); - setGradient( Q::Panel | A::Footer, theme.palette.background.fillColor.solidBackground.tertiary ); + const auto& pal = theme.palette; + + setGradient( Q::Panel, pal.background.fillColor.solidBackground.base ); + setGradient( Q::Panel | A::Header, pal.background.fillColor.solidBackground.tertiary ); + setGradient( Q::Panel | A::Footer, pal.background.fillColor.solidBackground.tertiary ); } void Editor::setupCheckBox() { using Q = QskCheckBox; + const auto& pal = theme.palette; + setStrutSize( Q::Panel, 126, 38 ); setSpacing( Q::Panel, 8 ); @@ -187,52 +191,54 @@ void Editor::setupCheckBox() setBoxBorderMetrics( Q::Box, 1 ); setPadding( Q::Box, 5 ); // "icon size" - setGradient( Q::Box, theme.palette.fillColor.controlAlt.secondary ); - setBoxBorderColors( Q::Box, theme.palette.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Box, pal.fillColor.controlAlt.secondary ); + setBoxBorderColors( Q::Box, pal.strokeColor.controlStrongStroke.defaultColor ); - setGradient( Q::Box | Q::Checked, theme.palette.fillColor.accent.defaultColor ); - setBoxBorderColors( Q::Box | Q::Checked, theme.palette.fillColor.accent.defaultColor ); + setGradient( Q::Box | Q::Checked, pal.fillColor.accent.defaultColor ); + setBoxBorderColors( Q::Box | Q::Checked, pal.fillColor.accent.defaultColor ); const auto checkMark = symbol( "checkmark" ); setSymbol( Q::Indicator | Q::Checked, checkMark, { QskStateCombination::CombinationNoState, Q::Disabled } ); setGraphicRole( Q::Indicator, QskFluent2Skin::GraphicRoleFillColorTextOnAccentPrimary ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.primary ); + setColor( Q::Text, pal.fillColor.text.primary ); - setGradient( Q::Box | Q::Hovered, theme.palette.fillColor.controlAlt.tertiary ); - setBoxBorderColors( Q::Box | Q::Hovered, theme.palette.strokeColor.controlStrongStroke.defaultColor ); - setGradient( Q::Box | Q::Hovered | Q::Checked, theme.palette.fillColor.accent.secondary ); - setBoxBorderColors( Q::Box | Q::Hovered | Q::Checked, theme.palette.fillColor.accent.secondary ); + setGradient( Q::Box | Q::Hovered, pal.fillColor.controlAlt.tertiary ); + setBoxBorderColors( Q::Box | Q::Hovered, pal.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Box | Q::Hovered | Q::Checked, pal.fillColor.accent.secondary ); + setBoxBorderColors( Q::Box | Q::Hovered | Q::Checked, pal.fillColor.accent.secondary ); // indicator the same as in Rest state - setGradient( Q::Box | Q::Pressed, theme.palette.fillColor.controlAlt.quaternary ); - setBoxBorderColors( Q::Box | Q::Pressed, theme.palette.strokeColor.controlStrongStroke.disabled ); - setGradient( Q::Box | Q::Pressed | Q::Checked, theme.palette.fillColor.accent.tertiary ); - setBoxBorderColors( Q::Box | Q::Pressed | Q::Checked, theme.palette.fillColor.accent.tertiary ); + setGradient( Q::Box | Q::Pressed, pal.fillColor.controlAlt.quaternary ); + setBoxBorderColors( Q::Box | Q::Pressed, pal.strokeColor.controlStrongStroke.disabled ); + setGradient( Q::Box | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); + setBoxBorderColors( Q::Box | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); setGraphicRole( Q::Indicator | Q::Pressed | Q::Checked, QskFluent2Skin::GraphicRoleFillColorTextOnAccentSecondary ); - setGradient( Q::Box | Q::Disabled, theme.palette.fillColor.controlAlt.disabled ); - setBoxBorderColors( Q::Box | Q::Disabled, theme.palette.strokeColor.controlStrongStroke.disabled ); - setGradient( Q::Box | Q::Disabled | Q::Checked, theme.palette.fillColor.accent.disabled ); - setBoxBorderColors( Q::Box | Q::Disabled | Q::Checked, theme.palette.fillColor.accent.disabled ); + setGradient( Q::Box | Q::Disabled, pal.fillColor.controlAlt.disabled ); + setBoxBorderColors( Q::Box | Q::Disabled, pal.strokeColor.controlStrongStroke.disabled ); + setGradient( Q::Box | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); + setBoxBorderColors( Q::Box | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); setGraphicRole( Q::Indicator | Q::Disabled | Q::Checked, QskFluent2Skin::GraphicRoleFillColorTextOnAccentDisabled ); - setColor( Q::Text | Q::Disabled, theme.palette.fillColor.text.disabled ); + setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); } void Editor::setupComboBox() { using Q = QskComboBox; + const auto& pal = theme.palette; + 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 ); + setGradient( Q::Panel, pal.fillColor.control.defaultColor ); + setBoxBorderGradient( Q::Panel, pal.elevation.control.border, + pal.fillColor.control.defaultColor ); setStrutSize( Q::Icon, 12, 12 ); setPadding( Q::Icon, { 0, 0, 8, 0 } ); @@ -240,7 +246,7 @@ void Editor::setupComboBox() setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.primary ); + setColor( Q::Text, pal.fillColor.text.primary ); setStrutSize( Q::StatusIndicator, 12, 12 ); setSymbol( Q::StatusIndicator, symbol( "spin-box-arrow-down" ) ); @@ -250,28 +256,28 @@ void Editor::setupComboBox() // 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 ); + setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); + setBoxBorderGradient( Q::Panel | Q::Hovered, pal.elevation.textControl.border, + pal.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 ); + setGradient( Q::Panel | Q::Focused, pal.fillColor.control.inputActive ); - auto gradient = theme.palette.elevation.textControl.border; - gradient.at( 1 ) = theme.palette.fillColor.accent.defaultColor; + auto gradient = pal.elevation.textControl.border; + gradient.at( 1 ) = pal.fillColor.accent.defaultColor; - setBoxBorderGradient( Q::Panel | Q::Focused, gradient, theme.palette.fillColor.control.inputActive ); + setBoxBorderGradient( Q::Panel | Q::Focused, gradient, pal.fillColor.control.inputActive ); // Disabled: - setGradient( Q::Panel | Q::Disabled, theme.palette.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, theme.palette.strokeColor.controlStroke.defaultColor ); + setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); + setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.controlStroke.defaultColor ); - setColor( Q::Text | Q::Disabled, theme.palette.fillColor.text.disabled ); + setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); setGraphicRole( Q::Icon | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); setGraphicRole( Q::StatusIndicator | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); @@ -280,20 +286,22 @@ void Editor::setupComboBox() void Editor::setupDialogButtonBox() { using Q = QskDialogButtonBox; + const auto& pal = theme.palette; setPadding( Q::Panel, 24 ); - setGradient( Q::Panel, theme.palette.background.fillColor.solidBackground.base ); + setGradient( Q::Panel, pal.background.fillColor.solidBackground.base ); setPadding(Q::Panel, 20 ); } void Editor::setupFocusIndicator() { using Q = QskFocusIndicator; + const auto& pal = theme.palette; setBoxBorderMetrics( Q::Panel, 2 ); setPadding( Q::Panel, 3 ); setBoxShape( Q::Panel, 4 ); - setBoxBorderColors( Q::Panel, theme.palette.strokeColor.focusStroke.outer ); + setBoxBorderColors( Q::Panel, pal.strokeColor.focusStroke.outer ); } void Editor::setupInputPanel() @@ -307,31 +315,32 @@ void Editor::setupListView() void Editor::setupMenu() { using Q = QskMenu; + const auto& pal = theme.palette; setPadding( Q::Panel, { 4, 6, 4, 6 } ); setBoxBorderMetrics( Q::Panel, 1 ); - setBoxBorderColors( Q::Panel, theme.palette.strokeColor.surfaceStroke.flyout ); + setBoxBorderColors( Q::Panel, pal.strokeColor.surfaceStroke.flyout ); setBoxShape( Q::Panel, 7 ); - setGradient( Q::Panel, theme.palette.background.fillColor.acrylicBackground.defaultColor ); + setGradient( Q::Panel, pal.background.fillColor.acrylicBackground.defaultColor ); setShadowMetrics( Q::Panel, theme.shadow.flyout.first ); // ### metrics should be the same, just color differs setShadowColor( Q::Panel, theme.shadow.flyout.second ); setPadding( Q::Segment, { 0, 10, 0, 10 } ); setSpacing( Q::Segment, 15 ); - setGradient( Q::Segment | Q::Selected, theme.palette.fillColor.subtle.secondary ); + setGradient( Q::Segment | Q::Selected, pal.fillColor.subtle.secondary ); setBoxBorderMetrics( Q::Segment | Q::Selected, { 3, 0, 0, 0 } ); - QskGradient selectedGradient( { { 0.0, theme.palette.fillColor.subtle.secondary }, - { 0.25, theme.palette.fillColor.subtle.secondary }, - { 0.25, theme.palette.fillColor.accent.defaultColor }, - { 0.75, theme.palette.fillColor.accent.defaultColor }, - { 0.75, theme.palette.fillColor.subtle.secondary }, - { 1.0, theme.palette.fillColor.subtle.secondary } } ); + QskGradient selectedGradient( { { 0.0, pal.fillColor.subtle.secondary }, + { 0.25, pal.fillColor.subtle.secondary }, + { 0.25, pal.fillColor.accent.defaultColor }, + { 0.75, pal.fillColor.accent.defaultColor }, + { 0.75, pal.fillColor.subtle.secondary }, + { 1.0, pal.fillColor.subtle.secondary } } ); setBoxBorderColors( Q::Segment | Q::Selected, selectedGradient ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.primary ); + setColor( Q::Text, pal.fillColor.text.primary ); setStrutSize( Q::Icon, 12, 12 ); setPadding( Q::Icon, { 8, 8, 0, 8 } ); @@ -345,28 +354,31 @@ void Editor::setupPageIndicator() void Editor::setupPopup() { using Q = QskPopup; + const auto& pal = theme.palette; - setGradient( Q::Overlay, theme.palette.background.fillColor.smoke.defaultColor ); + setGradient( Q::Overlay, pal.background.fillColor.smoke.defaultColor ); } void Editor::setupProgressBar() { using Q = QskProgressBar; using A = QskAspect; + const auto& pal = theme.palette; setMetric( Q::Groove | A::Size, 1 ); setBoxShape( Q::Groove, 100, Qt::RelativeSize ); - setGradient( Q::Groove, theme.palette.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Groove, pal.strokeColor.controlStrongStroke.defaultColor ); setMetric( Q::Bar| A::Size, 3 ); setBoxShape( Q::Bar, 100, Qt::RelativeSize ); - setGradient( Q::Bar, theme.palette.fillColor.accent.defaultColor ); + setGradient( Q::Bar, pal.fillColor.accent.defaultColor ); } void Editor::setupPushButton() { using Q = QskPushButton; using W = QskFluent2Skin; + const auto& pal = theme.palette; setStrutSize( Q::Panel, { 120, 32 } ); setBoxShape( Q::Panel, 4 ); @@ -382,78 +394,79 @@ void Editor::setupPushButton() // Accent buttons: - setBoxBorderGradient( Q::Panel | W::Accent, theme.palette.elevation.accentControl.border, - theme.palette.fillColor.accent.defaultColor ); + setBoxBorderGradient( Q::Panel | W::Accent, pal.elevation.accentControl.border, + pal.fillColor.accent.defaultColor ); - setGradient( Q::Panel | W::Accent, theme.palette.fillColor.accent.defaultColor ); - setColor( Q::Text | W::Accent, theme.palette.fillColor.textOnAccent.primary ); + setGradient( Q::Panel | W::Accent, pal.fillColor.accent.defaultColor ); + setColor( Q::Text | W::Accent, pal.fillColor.textOnAccent.primary ); setGraphicRole( Q::Icon | W::Accent, QskFluent2Skin::GraphicRoleFillColorTextOnAccentPrimary ); - setBoxBorderGradient( Q::Panel | W::Accent | Q::Hovered, theme.palette.elevation.accentControl.border, - theme.palette.fillColor.accent.secondary ); + setBoxBorderGradient( Q::Panel | W::Accent | Q::Hovered, pal.elevation.accentControl.border, + pal.fillColor.accent.secondary ); - setGradient( Q::Panel | W::Accent | Q::Hovered, theme.palette.fillColor.accent.secondary ); + setGradient( Q::Panel | W::Accent | Q::Hovered, pal.fillColor.accent.secondary ); - setGradient( Q::Panel | W::Accent | Q::Pressed, theme.palette.fillColor.accent.tertiary ); - setColor( Q::Text | W::Accent | Q::Pressed, theme.palette.fillColor.textOnAccent.secondary ); + setGradient( Q::Panel | W::Accent | Q::Pressed, pal.fillColor.accent.tertiary ); + setColor( Q::Text | W::Accent | Q::Pressed, pal.fillColor.textOnAccent.secondary ); setGraphicRole( Q::Icon | W::Accent | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextOnAccentSecondary ); - const QRgb accentPressedBorderColor = flattenedColor( theme.palette.strokeColor.controlStroke.onAccentDefault, - theme.palette.fillColor.accent.tertiary ); + const QRgb accentPressedBorderColor = flattenedColor( pal.strokeColor.controlStroke.onAccentDefault, + pal.fillColor.accent.tertiary ); setBoxBorderColors( Q::Panel | W::Accent | Q::Pressed, accentPressedBorderColor ); - setGradient( Q::Panel | W::Accent | Q::Disabled, theme.palette.fillColor.accent.disabled ); - setColor( Q::Text | W::Accent | Q::Disabled, theme.palette.fillColor.textOnAccent.disabled ); + setGradient( Q::Panel | W::Accent | Q::Disabled, pal.fillColor.accent.disabled ); + setColor( Q::Text | W::Accent | Q::Disabled, pal.fillColor.textOnAccent.disabled ); setGraphicRole( Q::Icon | W::Accent | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextOnAccentDisabled ); setBoxBorderMetrics( Q::Panel | W::Accent | Q::Disabled, 0 ); // Standard buttons: - setBoxBorderGradient( Q::Panel, theme.palette.elevation.control.border, - theme.palette.fillColor.control.defaultColor ); + setBoxBorderGradient( Q::Panel, pal.elevation.control.border, + pal.fillColor.control.defaultColor ); - setGradient( Q::Panel, theme.palette.fillColor.control.defaultColor ); - setColor( Q::Text, theme.palette.fillColor.text.primary ); + setGradient( Q::Panel, pal.fillColor.control.defaultColor ); + setColor( Q::Text, pal.fillColor.text.primary ); setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary ); - setBoxBorderGradient( Q::Panel | Q::Hovered, theme.palette.elevation.control.border, - theme.palette.fillColor.control.secondary ); + setBoxBorderGradient( Q::Panel | Q::Hovered, pal.elevation.control.border, + pal.fillColor.control.secondary ); - setGradient( Q::Panel | Q::Hovered, theme.palette.fillColor.control.secondary ); + setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); - const QRgb standardPressedBorderColor = flattenedColor( theme.palette.strokeColor.controlStroke.defaultColor, - theme.palette.fillColor.control.tertiary ); + const QRgb standardPressedBorderColor = flattenedColor( pal.strokeColor.controlStroke.defaultColor, + pal.fillColor.control.tertiary ); setBoxBorderColors( Q::Panel | Q::Pressed, standardPressedBorderColor ); - setGradient( Q::Panel | Q::Pressed, theme.palette.fillColor.control.tertiary ); - setColor( Q::Text | Q::Pressed, theme.palette.fillColor.text.secondary ); + setGradient( Q::Panel | Q::Pressed, pal.fillColor.control.tertiary ); + setColor( Q::Text | Q::Pressed, pal.fillColor.text.secondary ); setGraphicRole( Q::Icon | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextSecondary ); - const QRgb standardDisabledBorderColor = flattenedColor( theme.palette.strokeColor.controlStroke.defaultColor, - theme.palette.fillColor.control.disabled ); + const QRgb standardDisabledBorderColor = flattenedColor( pal.strokeColor.controlStroke.defaultColor, + pal.fillColor.control.disabled ); setBoxBorderColors( Q::Panel | Q::Disabled, standardDisabledBorderColor ); - setGradient( Q::Panel | Q::Disabled, theme.palette.fillColor.control.disabled ); - setColor( Q::Text | Q::Disabled, theme.palette.fillColor.text.disabled ); + setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); + setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); setGraphicRole( Q::Icon | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); } void Editor::setupRadioBox() { using Q = QskRadioBox; + const auto& pal = theme.palette; setSpacing( Q::Button, 8 ); setStrutSize( Q::Button, { 115, 38 } ); @@ -462,71 +475,71 @@ void Editor::setupRadioBox() setBoxShape( Q::CheckIndicatorPanel, 100, Qt::RelativeSize ); setBoxBorderMetrics( Q::CheckIndicatorPanel, 1 ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.primary ); + setColor( Q::Text, pal.fillColor.text.primary ); // Rest - setGradient( Q::CheckIndicatorPanel, theme.palette.fillColor.controlAlt.secondary ); - setBoxBorderColors( Q::CheckIndicatorPanel, theme.palette.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::CheckIndicatorPanel, pal.fillColor.controlAlt.secondary ); + setBoxBorderColors( Q::CheckIndicatorPanel, pal.strokeColor.controlStrongStroke.defaultColor ); - setGradient( Q::CheckIndicatorPanel | Q::Selected, theme.palette.fillColor.accent.defaultColor ); + setGradient( Q::CheckIndicatorPanel | Q::Selected, pal.fillColor.accent.defaultColor ); setBoxBorderMetrics( Q::CheckIndicatorPanel | Q::Selected, 0 ); setPadding( Q::CheckIndicatorPanel | Q::Selected, { 5, 5 } ); // indicator "strut size" setBoxShape( Q::CheckIndicator | Q::Selected, 100, Qt::RelativeSize ); setBoxBorderMetrics( Q::CheckIndicator | Q::Selected, 1 ); - setGradient( Q::CheckIndicator | Q::Selected, theme.palette.fillColor.textOnAccent.primary ); + setGradient( Q::CheckIndicator | Q::Selected, pal.fillColor.textOnAccent.primary ); - setBoxBorderGradient( Q::CheckIndicator | Q::Selected, theme.palette.elevation.circle.border, - theme.palette.fillColor.accent.defaultColor ); + setBoxBorderGradient( Q::CheckIndicator | Q::Selected, pal.elevation.circle.border, + pal.fillColor.accent.defaultColor ); // Hover - setGradient( Q::CheckIndicatorPanel | Q::Hovered, theme.palette.fillColor.controlAlt.tertiary ); + setGradient( Q::CheckIndicatorPanel | Q::Hovered, pal.fillColor.controlAlt.tertiary ); - setGradient( Q::CheckIndicatorPanel | Q::Hovered | Q::Selected, theme.palette.fillColor.accent.secondary ); + setGradient( Q::CheckIndicatorPanel | Q::Hovered | Q::Selected, pal.fillColor.accent.secondary ); setPadding( Q::CheckIndicatorPanel | Q::Hovered | Q::Selected, { 4, 4 } ); // indicator "strut size" - setBoxBorderGradient( Q::CheckIndicator | Q::Hovered, theme.palette.elevation.circle.border, - theme.palette.fillColor.accent.secondary ); + setBoxBorderGradient( Q::CheckIndicator | Q::Hovered, pal.elevation.circle.border, + pal.fillColor.accent.secondary ); // Pressed - setGradient( Q::CheckIndicatorPanel | Q::Pressed, theme.palette.fillColor.controlAlt.quaternary ); - setBoxBorderColors( Q::CheckIndicatorPanel | Q::Pressed, theme.palette.strokeColor.controlStrongStroke.disabled ); + setGradient( Q::CheckIndicatorPanel | Q::Pressed, pal.fillColor.controlAlt.quaternary ); + setBoxBorderColors( Q::CheckIndicatorPanel | Q::Pressed, pal.strokeColor.controlStrongStroke.disabled ); setPadding( Q::CheckIndicatorPanel | Q::Pressed, { 7, 7 } ); // indicator "strut size" setBoxShape( Q::CheckIndicator | Q::Pressed, 100, Qt::RelativeSize ); setBoxBorderMetrics( Q::CheckIndicator | Q::Pressed, 0 ); - setGradient( Q::CheckIndicator | Q::Pressed, theme.palette.fillColor.textOnAccent.primary ); + setGradient( Q::CheckIndicator | Q::Pressed, pal.fillColor.textOnAccent.primary ); - setGradient( Q::CheckIndicatorPanel | Q::Pressed | Q::Selected, theme.palette.fillColor.accent.tertiary ); + setGradient( Q::CheckIndicatorPanel | Q::Pressed | Q::Selected, pal.fillColor.accent.tertiary ); setBoxBorderMetrics( Q::CheckIndicatorPanel | Q::Pressed | Q::Selected, 0 ); setPadding( Q::CheckIndicatorPanel | Q::Pressed | Q::Selected, { 6, 6 } ); // indicator "strut size" setBoxBorderMetrics( Q::CheckIndicator | Q::Pressed, 1 ); - setBoxBorderGradient( Q::CheckIndicator | Q::Pressed | Q::Selected, theme.palette.elevation.circle.border, - theme.palette.fillColor.accent.tertiary ); + setBoxBorderGradient( Q::CheckIndicator | Q::Pressed | Q::Selected, pal.elevation.circle.border, + pal.fillColor.accent.tertiary ); // Disabled - setGradient( Q::CheckIndicatorPanel | Q::Disabled, theme.palette.fillColor.controlAlt.disabled ); - setBoxBorderColors( Q::CheckIndicatorPanel | Q::Disabled, theme.palette.strokeColor.controlStrongStroke.disabled ); + setGradient( Q::CheckIndicatorPanel | Q::Disabled, pal.fillColor.controlAlt.disabled ); + setBoxBorderColors( Q::CheckIndicatorPanel | Q::Disabled, pal.strokeColor.controlStrongStroke.disabled ); - setGradient( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, theme.palette.fillColor.accent.disabled ); + setGradient( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, pal.fillColor.accent.disabled ); setBoxBorderMetrics( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, 0 ); setPadding( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, { 6, 6 } ); // indicator "strut size" setBoxBorderMetrics( Q::CheckIndicator | Q::Disabled | Q::Selected, 0 ); - setGradient( Q::CheckIndicator | Q::Disabled | Q::Selected, theme.palette.fillColor.textOnAccent.primary ); + setGradient( Q::CheckIndicator | Q::Disabled | Q::Selected, pal.fillColor.textOnAccent.primary ); setBoxShape( Q::CheckIndicator | Q::Disabled | Q::Selected, 100, Qt::RelativeSize ); - setColor( Q::Text | Q::Disabled, theme.palette.fillColor.text.disabled ); + setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); } void Editor::setupScrollView() @@ -537,22 +550,23 @@ void Editor::setupSegmentedBar() { using Q = QskSegmentedBar; using A = QskAspect; + const auto& pal = theme.palette; const QSizeF segmentStrutSize( 120, 32 ); setBoxBorderMetrics( Q::Panel, 1 ); - setBoxBorderGradient( Q::Panel, theme.palette.elevation.control.border, - theme.palette.fillColor.control.defaultColor ); + setBoxBorderGradient( Q::Panel, pal.elevation.control.border, + pal.fillColor.control.defaultColor ); - setGradient( Q::Panel, theme.palette.fillColor.control.defaultColor ); + setGradient( Q::Panel, pal.fillColor.control.defaultColor ); setSpacing( Q::Panel, 8 ); setStrutSize( Q::Icon, { 12, 12 } ); setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.primary ); + setColor( Q::Text, pal.fillColor.text.primary ); setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize ); setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() ); @@ -560,29 +574,29 @@ void Editor::setupSegmentedBar() setPadding( Q::Segment, { 8, 0, 8, 0 } ); // Hovered: - setGradient( Q::Segment | Q::Hovered, theme.palette.fillColor.control.secondary ); + setGradient( Q::Segment | Q::Hovered, pal.fillColor.control.secondary ); - setBoxBorderGradient( Q::Segment | Q::Hovered, theme.palette.elevation.control.border, - theme.palette.fillColor.control.secondary ); + setBoxBorderGradient( Q::Segment | Q::Hovered, pal.elevation.control.border, + pal.fillColor.control.secondary ); // Selected: - setGradient( Q::Segment | Q::Selected, theme.palette.fillColor.accent.defaultColor ); + setGradient( Q::Segment | Q::Selected, pal.fillColor.accent.defaultColor ); setGraphicRole( Q::Icon | Q::Selected, QskFluent2Skin::GraphicRoleFillColorTextOnAccentPrimary ); - setColor( Q::Text | Q::Selected, theme.palette.fillColor.textOnAccent.primary ); + setColor( Q::Text | Q::Selected, pal.fillColor.textOnAccent.primary ); // Disabled: - const QRgb standardDisabledBorderColor = flattenedColor( theme.palette.strokeColor.controlStroke.defaultColor, - theme.palette.fillColor.control.disabled ); + const QRgb standardDisabledBorderColor = flattenedColor( pal.strokeColor.controlStroke.defaultColor, + pal.fillColor.control.disabled ); setBoxBorderColors( Q::Segment | Q::Disabled, standardDisabledBorderColor ); - setGradient( Q::Segment | Q::Disabled, theme.palette.fillColor.control.disabled ); - setColor( Q::Text | Q::Disabled, theme.palette.fillColor.text.disabled ); + setGradient( Q::Segment | Q::Disabled, pal.fillColor.control.disabled ); + setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); setGraphicRole( Q::Icon | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); - setGradient( Q::Segment | Q::Selected | Q::Disabled, theme.palette.fillColor.accent.disabled ); - setColor( Q::Text | Q::Selected | Q::Disabled, theme.palette.fillColor.textOnAccent.disabled ); + setGradient( Q::Segment | Q::Selected | Q::Disabled, pal.fillColor.accent.disabled ); + setColor( Q::Text | Q::Selected | Q::Disabled, pal.fillColor.textOnAccent.disabled ); setGraphicRole( Q::Icon | Q::Selected | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextOnAccentDisabled ); setBoxBorderMetrics( Q::Panel | Q::Selected | Q::Disabled, 0 ); @@ -590,12 +604,27 @@ void Editor::setupSegmentedBar() void Editor::setupSeparator() { + using A = QskAspect; + using Q = QskSeparator; + + const auto& pal = theme.palette; + + for ( auto variation : { A::Horizontal, A::Vertical } ) + { + const auto aspect = Q::Panel | variation; + + setMetric( aspect | A::Size, 1 ); + setBoxShape( Q::Panel, 0 ); + setBoxBorderMetrics( Q::Panel, 0 ); + setGradient( aspect, pal.strokeColor.dividerStroke.defaultColor ); + } } void Editor::setupSlider() { using Q = QskSlider; using A = QskAspect; + const auto& pal = theme.palette; const qreal extent = 22; setMetric( Q::Panel | A::Size, extent ); @@ -607,36 +636,37 @@ void Editor::setupSlider() setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) ); setMetric( Q::Groove | A::Size, 4 ); - setGradient( Q::Groove, theme.palette.fillColor.controlStrong.defaultColor ); + setGradient( Q::Groove, pal.fillColor.controlStrong.defaultColor ); setBoxShape( Q::Groove, 100, Qt::RelativeSize ); setMetric( Q::Fill | A::Size, 4 ); - setGradient( Q::Fill, theme.palette.fillColor.accent.defaultColor ); + setGradient( Q::Fill, pal.fillColor.accent.defaultColor ); setBoxShape( Q::Fill, 100, Qt::RelativeSize ); setStrutSize( Q::Handle, { 22, 22 } ); - setGradient( Q::Handle, theme.palette.fillColor.controlSolid.defaultColor ); + setGradient( Q::Handle, pal.fillColor.controlSolid.defaultColor ); setBoxShape( Q::Handle, 100, Qt::RelativeSize ); setBoxBorderMetrics( Q::Handle, 1 ); - setBoxBorderGradient( Q::Handle, theme.palette.elevation.circle.border, theme.palette.fillColor.controlSolid.defaultColor ); + setBoxBorderGradient( Q::Handle, pal.elevation.circle.border, pal.fillColor.controlSolid.defaultColor ); setStrutSize( Q::Ripple, { 12, 12 } ); - setGradient( Q::Ripple, theme.palette.fillColor.accent.defaultColor ); + setGradient( Q::Ripple, pal.fillColor.accent.defaultColor ); setBoxShape( Q::Ripple, 100, Qt::RelativeSize ); setStrutSize( Q::Ripple | Q::Hovered, { 14, 14 } ); setStrutSize( Q::Ripple | Q::Pressed, { 10, 10 } ); - setGradient( Q::Ripple | Q::Pressed, theme.palette.fillColor.accent.tertiary ); + setGradient( Q::Ripple | Q::Pressed, pal.fillColor.accent.tertiary ); - setGradient( Q::Groove | Q::Disabled, theme.palette.fillColor.controlStrong.disabled ); - setGradient( Q::Fill | Q::Disabled, theme.palette.fillColor.accent.disabled ); - setGradient( Q::Ripple | Q::Disabled, theme.palette.fillColor.controlStrong.disabled ); + setGradient( Q::Groove | Q::Disabled, pal.fillColor.controlStrong.disabled ); + setGradient( Q::Fill | Q::Disabled, pal.fillColor.accent.disabled ); + setGradient( Q::Ripple | Q::Disabled, pal.fillColor.controlStrong.disabled ); } void Editor::setupSpinBox() { using Q = QskSpinBox; + const auto& pal = theme.palette; setHint( Q::Panel | QskAspect::Style, Q::ButtonsRight ); setStrutSize( Q::Panel, { -1, 32 } ); @@ -644,13 +674,13 @@ void Editor::setupSpinBox() 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 ); + setGradient( Q::Panel, pal.fillColor.control.defaultColor ); + setBoxBorderGradient( Q::Panel, pal.elevation.control.border, + pal.fillColor.control.defaultColor ); setAlignment( Q::Text, Qt::AlignLeft ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.primary ); + setColor( Q::Text, pal.fillColor.text.primary ); setPadding( Q::TextPanel, { 11, 5, 0, 0 } ); @@ -670,28 +700,28 @@ void Editor::setupSpinBox() // 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 ); + setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); + setBoxBorderGradient( Q::Panel | Q::Hovered, pal.elevation.textControl.border, + pal.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 ); + setGradient( Q::Panel | Q::Focused, pal.fillColor.control.inputActive ); - auto gradient = theme.palette.elevation.textControl.border; - gradient.at( 1 ) = theme.palette.fillColor.accent.defaultColor; + auto gradient = pal.elevation.textControl.border; + gradient.at( 1 ) = pal.fillColor.accent.defaultColor; - setBoxBorderGradient( Q::Panel | Q::Focused, gradient, theme.palette.fillColor.control.inputActive ); + setBoxBorderGradient( Q::Panel | Q::Focused, gradient, pal.fillColor.control.inputActive ); // Disabled: - setGradient( Q::Panel | Q::Disabled, theme.palette.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, theme.palette.strokeColor.controlStroke.defaultColor ); + setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); + setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.controlStroke.defaultColor ); - setColor( Q::Text | Q::Disabled, theme.palette.fillColor.text.disabled ); + setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); setGraphicRole( Q::UpIndicator | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); setGraphicRole( Q::DownIndicator | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); @@ -704,52 +734,56 @@ void Editor::setupTabBar() void Editor::setupTabButton() { using Q = QskTabButton; + const auto& pal = theme.palette; setStrutSize( Q::Panel, { -1, 31 } ); setPadding( Q::Panel, { 7, 0, 7, 0 } ); setBoxShape( Q::Panel, { 7, 7, 0, 0 } ); - setGradient( Q::Panel, theme.palette.fillColor.subtle.transparent ); + setGradient( Q::Panel, pal.fillColor.subtle.transparent ); setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1 } ); - setBoxBorderColors( Q::Panel, theme.palette.strokeColor.cardStroke.defaultColor ); + setBoxBorderColors( Q::Panel, pal.strokeColor.cardStroke.defaultColor ); - setGradient( Q::Panel | Q::Checked, theme.palette.background.fillColor.solidBackground.tertiary ); + setGradient( Q::Panel | Q::Checked, pal.background.fillColor.solidBackground.tertiary ); setBoxBorderMetrics( Q::Panel | Q::Checked, { 1, 1, 1, 0 } ); setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.secondary ); + setColor( Q::Text, pal.fillColor.text.secondary ); setFontRole( Q::Text | Q::Checked, QskFluent2Skin::BodyStrong ); - setColor( Q::Text | Q::Checked, theme.palette.fillColor.text.primary ); + setColor( Q::Text | Q::Checked, pal.fillColor.text.primary ); - setGradient( Q::Panel | Q::Hovered, theme.palette.fillColor.subtle.secondary ); + setGradient( Q::Panel | Q::Hovered, pal.fillColor.subtle.secondary ); - setGradient( Q::Panel | Q::Pressed, theme.palette.fillColor.subtle.tertiary ); + setGradient( Q::Panel | Q::Pressed, pal.fillColor.subtle.tertiary ); } void Editor::setupTabView() { using Q = QskTabView; + const auto& pal = theme.palette; - setGradient( Q::Page, theme.palette.background.fillColor.solidBackground.tertiary ); + setGradient( Q::Page, pal.background.fillColor.solidBackground.tertiary ); } void Editor::setupTextLabel() { using Q = QskTextLabel; + const auto& pal = theme.palette; setPadding( Q::Panel, 10 ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.primary ); + setColor( Q::Text, pal.fillColor.text.primary ); } void Editor::setupTextInput() { using Q = QskTextInput; + const auto& pal = theme.palette; setStrutSize( Q::Panel, { -1, 30 } ); setBoxBorderMetrics( Q::Panel, 1 ); @@ -758,20 +792,20 @@ void Editor::setupTextInput() setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, theme.palette.fillColor.text.secondary ); + setColor( Q::Text, pal.fillColor.text.secondary ); - setGradient( Q::Panel, theme.palette.fillColor.control.defaultColor ); - setBoxBorderGradient( Q::Panel, theme.palette.elevation.textControl.border, - theme.palette.fillColor.control.defaultColor ); + setGradient( Q::Panel, pal.fillColor.control.defaultColor ); + setBoxBorderGradient( Q::Panel, pal.elevation.textControl.border, + pal.fillColor.control.defaultColor ); - setColor( Q::PanelSelected, theme.palette.fillColor.accent.selectedTextBackground ); - setColor( Q::TextSelected, theme.palette.fillColor.textOnAccent.selectedText ); + setColor( Q::PanelSelected, pal.fillColor.accent.selectedTextBackground ); + setColor( Q::TextSelected, pal.fillColor.textOnAccent.selectedText ); // 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 ); + setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); + setBoxBorderGradient( Q::Panel | Q::Hovered, pal.elevation.textControl.border, + pal.fillColor.control.secondary ); // Pressed & Focused: @@ -780,26 +814,27 @@ void Editor::setupTextInput() { setBoxBorderMetrics( Q::Panel | state, { 1, 1, 1, 2 } ); - setGradient( Q::Panel | state, theme.palette.fillColor.control.inputActive ); + setGradient( Q::Panel | state, pal.fillColor.control.inputActive ); - auto gradient = theme.palette.elevation.textControl.border; - gradient.at( 1 ) = theme.palette.fillColor.accent.defaultColor; + auto gradient = pal.elevation.textControl.border; + gradient.at( 1 ) = pal.fillColor.accent.defaultColor; - setBoxBorderGradient( Q::Panel | state, gradient, theme.palette.fillColor.control.inputActive ); + setBoxBorderGradient( Q::Panel | state, gradient, pal.fillColor.control.inputActive ); } // Disabled: - setGradient( Q::Panel | Q::Disabled, theme.palette.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, theme.palette.strokeColor.controlStroke.defaultColor ); + setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); + setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.controlStroke.defaultColor ); - setColor( Q::Text | Q::Disabled, theme.palette.fillColor.text.disabled ); + setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); } void Editor::setupSwitchButton() { using Q = QskSwitchButton; using A = QskAspect; + const auto& pal = theme.palette; const QSizeF strutSize( 38, 18 ); setStrutSize( Q::Groove | A::Horizontal, strutSize ); @@ -817,64 +852,65 @@ void Editor::setupSwitchButton() // ### big size during animation - setGradient( Q::Groove, theme.palette.fillColor.controlAlt.secondary ); - setGradient( Q::Groove | Q::Checked, theme.palette.fillColor.accent.defaultColor ); - setBoxBorderColors( Q::Groove, theme.palette.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Groove, pal.fillColor.controlAlt.secondary ); + setGradient( Q::Groove | Q::Checked, pal.fillColor.accent.defaultColor ); + setBoxBorderColors( Q::Groove, pal.strokeColor.controlStrongStroke.defaultColor ); setStrutSize( Q::Handle, 12, 12 ); - setGradient( Q::Handle, theme.palette.strokeColor.controlStrongStroke.defaultColor ); - setGradient( Q::Handle | Q::Checked, theme.palette.fillColor.textOnAccent.primary ); + setGradient( Q::Handle, pal.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Handle | Q::Checked, pal.fillColor.textOnAccent.primary ); - setBoxBorderGradient( Q::Handle | Q::Checked, theme.palette.elevation.circle.border, - theme.palette.fillColor.accent.defaultColor ); + setBoxBorderGradient( Q::Handle | Q::Checked, pal.elevation.circle.border, + pal.fillColor.accent.defaultColor ); - setGradient( Q::Groove | Q::Hovered, theme.palette.fillColor.controlAlt.tertiary ); - setGradient( Q::Groove | Q::Hovered | Q::Checked, theme.palette.fillColor.accent.secondary ); - setBoxBorderColors( Q::Groove | Q::Hovered, theme.palette.fillColor.text.secondary ); + setGradient( Q::Groove | Q::Hovered, pal.fillColor.controlAlt.tertiary ); + setGradient( Q::Groove | Q::Hovered | Q::Checked, pal.fillColor.accent.secondary ); + setBoxBorderColors( Q::Groove | Q::Hovered, pal.fillColor.text.secondary ); setStrutSize( Q::Handle | Q::Hovered, 14, 14, { QskStateCombination::CombinationNoState, Q::Checked } ); - setGradient( Q::Handle | Q::Hovered, theme.palette.fillColor.text.secondary ); + setGradient( Q::Handle | Q::Hovered, pal.fillColor.text.secondary ); // Handle | Hovered | Checked is the same as in Rest state - setBoxBorderGradient( Q::Handle | Q::Hovered | Q::Checked, theme.palette.elevation.circle.border, - theme.palette.fillColor.accent.secondary ); + setBoxBorderGradient( Q::Handle | Q::Hovered | Q::Checked, pal.elevation.circle.border, + pal.fillColor.accent.secondary ); - setGradient( Q::Groove | Q::Pressed, theme.palette.fillColor.controlAlt.quaternary ); - setGradient( Q::Groove | Q::Pressed | Q::Checked, theme.palette.fillColor.accent.tertiary ); - setBoxBorderColors( Q::Groove | Q::Pressed, theme.palette.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Groove | Q::Pressed, pal.fillColor.controlAlt.quaternary ); + setGradient( Q::Groove | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); + setBoxBorderColors( Q::Groove | Q::Pressed, pal.strokeColor.controlStrongStroke.defaultColor ); const QSizeF pressedSize( 17, 14 ); setStrutSize( Q::Handle | Q::Pressed | A::Horizontal, pressedSize, { QskStateCombination::CombinationNoState, Q::Checked } ); setStrutSize( Q::Handle | Q::Pressed | A::Vertical, pressedSize.transposed(), { QskStateCombination::CombinationNoState, Q::Checked } ); - setGradient( Q::Handle | Q::Pressed, theme.palette.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Handle | Q::Pressed, pal.strokeColor.controlStrongStroke.defaultColor ); // Handle | Pressed | Checked is the same as in Rest state - setBoxBorderGradient( Q::Handle | Q::Pressed | Q::Checked, theme.palette.elevation.circle.border, - theme.palette.fillColor.accent.tertiary ); + setBoxBorderGradient( Q::Handle | Q::Pressed | Q::Checked, pal.elevation.circle.border, + pal.fillColor.accent.tertiary ); - setGradient( Q::Groove | Q::Disabled, theme.palette.fillColor.controlAlt.disabled ); - setBoxBorderColors( Q::Groove | Q::Disabled, theme.palette.fillColor.text.disabled ); - setGradient( Q::Groove | Q::Disabled | Q::Checked, theme.palette.fillColor.accent.disabled ); - setBoxBorderColors( Q::Groove | Q::Disabled | Q::Checked, theme.palette.fillColor.accent.disabled ); + setGradient( Q::Groove | Q::Disabled, pal.fillColor.controlAlt.disabled ); + setBoxBorderColors( Q::Groove | Q::Disabled, pal.fillColor.text.disabled ); + setGradient( Q::Groove | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); + setBoxBorderColors( Q::Groove | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); setStrutSize( Q::Handle | Q::Disabled, 12, 12, { QskStateCombination::CombinationNoState, Q::Checked } ); - setGradient( Q::Handle | Q::Disabled, theme.palette.fillColor.text.disabled ); - setGradient( Q::Handle | Q::Disabled | Q::Checked, theme.palette.fillColor.textOnAccent.disabled ); + setGradient( Q::Handle | Q::Disabled, pal.fillColor.text.disabled ); + setGradient( Q::Handle | Q::Disabled | Q::Checked, pal.fillColor.textOnAccent.disabled ); setBoxBorderMetrics( Q::Handle | Q::Disabled | Q::Checked, 1 ); } void Editor::setupSubWindow() { using Q = QskSubWindow; + const auto& pal = theme.palette; setPadding( Q::Panel, { 0, 31, 0, 0 } ); setBoxShape( Q::Panel, 7 ); setBoxBorderMetrics( Q::Panel, 1 ); - setBoxBorderColors( Q::Panel, theme.palette.strokeColor.surfaceStroke.defaultColor ); - setGradient( Q::Panel, theme.palette.background.fillColor.layer.alt ); + setBoxBorderColors( Q::Panel, pal.strokeColor.surfaceStroke.defaultColor ); + setGradient( Q::Panel, pal.background.fillColor.layer.alt ); setShadowMetrics( Q::Panel, theme.shadow.dialog.first ); setShadowColor( Q::Panel, theme.shadow.dialog.second ); @@ -882,7 +918,7 @@ void Editor::setupSubWindow() setPadding( Q::TitleBarPanel, { 24, 31, 24, 0 } ); setFontRole( Q::TitleBarText, QskFluent2Skin::Subtitle ); - setColor( Q::TitleBarText, theme.palette.fillColor.text.primary ); + setColor( Q::TitleBarText, pal.fillColor.text.primary ); setAlignment( Q::TitleBarText, Qt::AlignLeft ); setTextOptions( Q::TitleBarText, Qt::ElideRight, QskTextOptions::NoWrap ); } @@ -890,19 +926,19 @@ void Editor::setupSubWindow() void Editor::setupVirtualKeyboard() { using Q = QskVirtualKeyboard; + const auto& pal = theme.palette; setMargin( Q::ButtonPanel, 2 ); - setGradient( Q::ButtonPanel, theme.palette.fillColor.control.defaultColor ); - setGradient( Q::ButtonPanel | Q::Hovered, theme.palette.fillColor.control.secondary ); - setGradient( Q::ButtonPanel | QskPushButton::Pressed, theme.palette.fillColor.control.tertiary ); + setGradient( Q::ButtonPanel, pal.fillColor.control.defaultColor ); + setGradient( Q::ButtonPanel | Q::Hovered, pal.fillColor.control.secondary ); + setGradient( Q::ButtonPanel | QskPushButton::Pressed, pal.fillColor.control.tertiary ); - setColor( Q::ButtonText, theme.palette.fillColor.text.primary ); + setColor( Q::ButtonText, pal.fillColor.text.primary ); setFontRole( Q::ButtonText, QskFluent2Skin::BodyLarge ); - setColor( Q::ButtonText | QskPushButton::Pressed, theme.palette.fillColor.text.secondary ); + setColor( Q::ButtonText | QskPushButton::Pressed, pal.fillColor.text.secondary ); - setGradient( Q::Panel, theme.palette.background.fillColor.solidBackground.secondary ); + setGradient( Q::Panel, pal.background.fillColor.solidBackground.secondary ); setPadding( Q::Panel, 8 ); - } QskFluent2Theme::QskFluent2Theme( Theme lightness ) @@ -1246,12 +1282,14 @@ void QskFluent2Skin::setGraphicColor( GraphicRole role, QRgb rgb ) void QskFluent2Skin::setupGraphicFilters( const QskFluent2Theme& theme ) { - setGraphicColor( GraphicRoleFillColorTextDisabled, theme.palette.fillColor.text.disabled ); - setGraphicColor( GraphicRoleFillColorTextOnAccentDisabled, theme.palette.fillColor.textOnAccent.disabled ); - setGraphicColor( GraphicRoleFillColorTextOnAccentPrimary, theme.palette.fillColor.textOnAccent.primary ); - setGraphicColor( GraphicRoleFillColorTextOnAccentSecondary, theme.palette.fillColor.textOnAccent.secondary ); - setGraphicColor( GraphicRoleFillColorTextPrimary, theme.palette.fillColor.text.primary ); - setGraphicColor( GraphicRoleFillColorTextSecondary, theme.palette.fillColor.text.secondary ); + const auto& colors = theme.palette.fillColor; + + setGraphicColor( GraphicRoleFillColorTextDisabled, colors.text.disabled ); + setGraphicColor( GraphicRoleFillColorTextOnAccentDisabled, colors.textOnAccent.disabled ); + setGraphicColor( GraphicRoleFillColorTextOnAccentPrimary, colors.textOnAccent.primary ); + setGraphicColor( GraphicRoleFillColorTextOnAccentSecondary, colors.textOnAccent.secondary ); + setGraphicColor( GraphicRoleFillColorTextPrimary, colors.text.primary ); + setGraphicColor( GraphicRoleFillColorTextSecondary, colors.text.secondary ); } #include "moc_QskFluent2Skin.cpp" From 042523d9e3237cb1258747fd18b8bce32fc03827 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 17:41:08 +0200 Subject: [PATCH 04/60] making gray/color values more obvious --- skins/fluent2/QskFluent2Skin.cpp | 329 +++++++++++++++---------------- skins/fluent2/QskFluent2Skin.h | 2 +- 2 files changed, 160 insertions(+), 171 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 70b9ba99..b07391d3 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -56,6 +56,11 @@ namespace { + inline constexpr QRgb rgbGray( int value, qreal opacity = 1.0 ) + { + return qRgba( value, value, value, qRound( opacity * 255 ) ); + } + inline QRgb flattenedColor( QRgb foregroundColor, QRgb backgroundColor ) { const qreal alphaRatio = ( ( foregroundColor & QskRgb::AlphaMask ) >> 24 ) / 255.0; @@ -955,290 +960,274 @@ QskFluent2Theme::QskFluent2Theme( Theme lightness ) { } -QskFluent2Theme::QskFluent2Theme( Theme theme, std::array< QRgb, NumAccentColors > accentColors ) +QskFluent2Theme::QskFluent2Theme( Theme theme, + const std::array< QRgb, NumAccentColors >& accentColors ) { if( theme == Light ) { // Fill color: - palette.fillColor.text.primary = QskRgb::toTransparentF( 0xff000000, 0.8956 ); - palette.fillColor.text.secondary = QskRgb::toTransparentF( 0xff000000, 0.6063 ); - palette.fillColor.text.tertiary = QskRgb::toTransparentF( 0xff000000, 0.4458 ); - palette.fillColor.text.disabled = QskRgb::toTransparentF( 0xff000000, 0.3614 ); + palette.fillColor.text.primary = rgbGray( 0, 0.8956 ); + palette.fillColor.text.secondary = rgbGray( 0, 0.6063 ); + palette.fillColor.text.tertiary = rgbGray( 0, 0.4458 ); + palette.fillColor.text.disabled = rgbGray( 0, 0.3614 ); palette.fillColor.accentText.primary = accentColors[ AccentDark2 ]; palette.fillColor.accentText.secondary = accentColors[ AccentDark3 ]; palette.fillColor.accentText.tertiary = accentColors[ AccentDark1 ]; - palette.fillColor.accentText.disabled = QskRgb::toTransparentF( 0xff000000, 0.3614 ); + palette.fillColor.accentText.disabled = rgbGray( 0, 0.3614 ); - palette.fillColor.textOnAccent.primary = 0xffffffff; - palette.fillColor.textOnAccent.secondary = QskRgb::toTransparentF( 0xffffffff, 0.70 ); - palette.fillColor.textOnAccent.disabled = 0xffffffff; - palette.fillColor.textOnAccent.selectedText = 0xffffffff; + palette.fillColor.textOnAccent.primary = rgbGray( 255 ); + palette.fillColor.textOnAccent.secondary = rgbGray( 255, 0.70 ); + palette.fillColor.textOnAccent.disabled = rgbGray( 255 ); + palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); palette.fillColor.control.transparent = Qt::transparent; - palette.fillColor.control.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.70 ); - palette.fillColor.control.secondary = QskRgb::toTransparentF( 0xffF9F9F9, 0.50 ); - palette.fillColor.control.tertiary = QskRgb::toTransparentF( 0xffF9F9F9, 0.30 ); - palette.fillColor.control.inputActive = 0xffffffff; - palette.fillColor.control.disabled = QskRgb::toTransparentF( 0xffF9F9F9, 0.30 ); + palette.fillColor.control.defaultColor = rgbGray( 255, 0.70 ); + palette.fillColor.control.secondary = rgbGray( 249, 0.50 ); + palette.fillColor.control.tertiary = rgbGray( 249, 0.30 ); + palette.fillColor.control.inputActive = rgbGray( 255 ); + palette.fillColor.control.disabled = rgbGray( 249, 0.30 ); - palette.fillColor.controlStrong.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.4458 ); - palette.fillColor.controlStrong.disabled = QskRgb::toTransparentF( 0xff000000, 0.3173 ); + palette.fillColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); + palette.fillColor.controlStrong.disabled = rgbGray( 0, 0.3173 ); palette.fillColor.subtle.transparent = Qt::transparent; - palette.fillColor.subtle.secondary =QskRgb::toTransparentF( 0xff000000, 0.0373 ); - palette.fillColor.subtle.tertiary = QskRgb::toTransparentF( 0xff000000, 0.0241 ); + palette.fillColor.subtle.secondary = rgbGray( 0, 0.0373 ); + palette.fillColor.subtle.tertiary = rgbGray( 0, 0.0241 ); palette.fillColor.subtle.disabled = Qt::transparent; - palette.fillColor.controlSolid.defaultColor = 0xffffffff; + palette.fillColor.controlSolid.defaultColor = rgbGray( 255 ); palette.fillColor.controlAlt.transparent = Qt::transparent; - palette.fillColor.controlAlt.secondary = QskRgb::toTransparentF( 0xff000000, 0.0241 ); - palette.fillColor.controlAlt.tertiary = QskRgb::toTransparentF( 0xff000000, 0.0578 ); - palette.fillColor.controlAlt.quaternary = QskRgb::toTransparentF( 0xff000000, 0.0924 ); + palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.0241 ); + palette.fillColor.controlAlt.tertiary = rgbGray( 0, 0.0578 ); + palette.fillColor.controlAlt.quaternary = rgbGray( 0, 0.0924 ); palette.fillColor.controlAlt.disabled = Qt::transparent; palette.fillColor.accent.defaultColor = accentColors[ AccentDark1 ]; palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.90 ); palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.80 ); - palette.fillColor.accent.disabled = QskRgb::toTransparentF( 0xff000000, 0.2169 ); + palette.fillColor.accent.disabled = rgbGray( 0, 0.2169 ); palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; - palette.fillColor.system.critical = 0xffC42B1C; - palette.fillColor.system.success = 0xff0F7B0F; - palette.fillColor.system.attention = 0xff005FB7; - palette.fillColor.system.caution = 0xff9D5D00; - palette.fillColor.system.attentionBackground = QskRgb::toTransparentF( 0xffF6F6F6, 0.50 ); - palette.fillColor.system.successBackground = 0xffDFF6DD; - palette.fillColor.system.cautionBackground = 0xffFFF4CE; - palette.fillColor.system.criticalBackground = 0xffFDE7E9; - palette.fillColor.system.neutral = QskRgb::toTransparentF( 0xff000000, 0.4458 ); - palette.fillColor.system.neutralBackground = QskRgb::toTransparentF( 0xff000000, 0.0241 ); - palette.fillColor.system.solidNeutral = 0xff8A8A8A; - palette.fillColor.system.solidAttentionBackground = 0xffF7F7F7; - palette.fillColor.system.solidNeutralBackground = 0xffF3F3F3; + palette.fillColor.system.critical = 0xffc42b1c; + palette.fillColor.system.success = 0xff0f7b0f; + palette.fillColor.system.attention = 0xff005fb7; + palette.fillColor.system.caution = 0xff9d5d00; + palette.fillColor.system.attentionBackground = rgbGray( 246, 0.50 ); + palette.fillColor.system.successBackground = 0xffdff6dd; + palette.fillColor.system.cautionBackground = 0xfffff4ce; + palette.fillColor.system.criticalBackground = 0xfffde7e9; + palette.fillColor.system.neutral = rgbGray( 0, 0.4458 ); + palette.fillColor.system.neutralBackground = rgbGray( 0, 0.0241 ); + palette.fillColor.system.solidNeutral = rgbGray( 138 ); + palette.fillColor.system.solidAttentionBackground = rgbGray( 247 ); + palette.fillColor.system.solidNeutralBackground = rgbGray( 243 ); // Elevation: - palette.elevation.control.border = { QskRgb::toTransparentF( 0xff000000, 0.0578 ), - QskRgb::toTransparentF( 0xff000000, 0.1622 ) }; - - palette.elevation.circle.border = { QskRgb::toTransparentF( 0xff000000, 0.0578 ), - QskRgb::toTransparentF( 0xff000000, 0.1622 ) }; - - palette.elevation.textControl.border = { QskRgb::toTransparentF( 0xff000000, 0.0578 ), - palette.fillColor.text.secondary }; - - palette.elevation.textControl.borderFocused = { QskRgb::toTransparentF( 0xff000000, 0.0578 ), - QskRgb::toTransparentF( 0xff000000, 0.0578 ) }; - - palette.elevation.accentControl.border = { QskRgb::toTransparentF( 0xffffffff, 0.08 ), - QskRgb::toTransparentF( 0xff000000, 0.40 ) }; + palette.elevation.control.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; + palette.elevation.circle.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; + palette.elevation.textControl.border = { rgbGray( 0, 0.0578 ), palette.fillColor.text.secondary }; + palette.elevation.textControl.borderFocused = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.0578 ) }; + palette.elevation.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.40 ) }; // Stroke color: - palette.strokeColor.controlStroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.0578 ); - palette.strokeColor.controlStroke.secondary = QskRgb::toTransparentF( 0xff000000, 0.1622 ); - palette.strokeColor.controlStroke.onAccentDefault = QskRgb::toTransparentF( 0xffffffff, 0.08 ); - palette.strokeColor.controlStroke.onAccentSecondary = QskRgb::toTransparentF( 0xff000000, 0.40 ); - palette.strokeColor.controlStroke.onAccentTertiary = QskRgb::toTransparentF( 0xff000000, 0.2169 ); - palette.strokeColor.controlStroke.onAccentDisabled = QskRgb::toTransparentF( 0xff000000, 0.0578 ); - palette.strokeColor.controlStroke.forStrongFillWhenOnImage = QskRgb::toTransparentF( 0xffffffff, 0.35 ); + palette.strokeColor.controlStroke.defaultColor = rgbGray( 0, 0.0578 ); + palette.strokeColor.controlStroke.secondary = rgbGray( 0, 0.1622 ); + palette.strokeColor.controlStroke.onAccentDefault = rgbGray( 255.08 ); + palette.strokeColor.controlStroke.onAccentSecondary = rgbGray( 0, 0.40 ); + palette.strokeColor.controlStroke.onAccentTertiary = rgbGray( 0, 0.2169 ); + palette.strokeColor.controlStroke.onAccentDisabled = rgbGray( 0, 0.0578 ); + palette.strokeColor.controlStroke.forStrongFillWhenOnImage = rgbGray( 255, 0.35 ); - palette.strokeColor.controlStrongStroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.4458 ); - palette.strokeColor.controlStrongStroke.disabled = QskRgb::toTransparentF( 0xff000000, 0.2169 ); + palette.strokeColor.controlStrongStroke.defaultColor = rgbGray( 0, 0.4458 ); + palette.strokeColor.controlStrongStroke.disabled = rgbGray( 0, 0.2169 ); - palette.strokeColor.cardStroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.0578 ); - palette.strokeColor.cardStroke.defaultSolid = 0xffEBEBEB; + palette.strokeColor.cardStroke.defaultColor = rgbGray( 0, 0.0578 ); + palette.strokeColor.cardStroke.defaultSolid = rgbGray( 235 ); - palette.strokeColor.dividerStroke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.0803 ); + palette.strokeColor.dividerStroke.defaultColor = rgbGray( 0, 0.0803 ); - palette.strokeColor.surfaceStroke.defaultColor = QskRgb::toTransparentF( 0xff757575, 0.40 ); - palette.strokeColor.surfaceStroke.flyout = QskRgb::toTransparentF( 0xff000000, 0.0578 ); + palette.strokeColor.surfaceStroke.defaultColor = rgbGray( 117, 0.40 ); + palette.strokeColor.surfaceStroke.flyout = rgbGray( 0, 0.0578 ); - palette.strokeColor.focusStroke.outer = QskRgb::toTransparentF( 0xff000000, 0.8956 ); - palette.strokeColor.focusStroke.inner = 0xffffffff; + palette.strokeColor.focusStroke.outer = rgbGray( 0, 0.8956 ); + palette.strokeColor.focusStroke.inner = rgbGray( 255 ); // Background: - palette.background.fillColor.cardBackground.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.70 ); - palette.background.fillColor.cardBackground.secondary = QskRgb::toTransparentF( 0xffF6F6F6, 0.50 ); - palette.background.fillColor.cardBackground.tertiary = 0xffffffff; + palette.background.fillColor.cardBackground.defaultColor = rgbGray( 255, 0.70 ); + palette.background.fillColor.cardBackground.secondary = rgbGray( 246, 0.50 ); + palette.background.fillColor.cardBackground.tertiary = rgbGray( 255 ); - palette.background.fillColor.smoke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.30 ); + palette.background.fillColor.smoke.defaultColor = rgbGray( 0, 0.30 ); - palette.background.fillColor.layer.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.50 ); - palette.background.fillColor.layer.alt = 0xffffffff; + palette.background.fillColor.layer.defaultColor = rgbGray( 255, 0.50 ); + palette.background.fillColor.layer.alt = rgbGray( 255 ); - palette.background.fillColor.layerOnAcrylic.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.25 ); + palette.background.fillColor.layerOnAcrylic.defaultColor = rgbGray( 255, 0.25 ); - palette.background.fillColor.layerOnAccentAcrylic.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.25 ); + palette.background.fillColor.layerOnAccentAcrylic.defaultColor = rgbGray( 255, 0.25 ); - palette.background.fillColor.acrylicBackground.defaultColor = QskRgb::toTransparentF( 0xffFCFCFC, 0.85 ); - palette.background.fillColor.acrylicBackground.base = QskRgb::toTransparentF( 0xffF3F3F3, 0.90 ); + palette.background.fillColor.acrylicBackground.defaultColor = rgbGray( 252, 0.85 ); + palette.background.fillColor.acrylicBackground.base = rgbGray( 243, 0.90 ); palette.background.fillColor.accentAcrylicBackground.base = QskRgb::toTransparentF( accentColors[ AccentLight3 ], 0.90 ); palette.background.fillColor.accentAcrylicBackground.defaultColor = QskRgb::toTransparentF( accentColors[ AccentLight3 ], 0.90 ); - palette.background.fillColor.micaBackground.base = QskRgb::toTransparentF( 0xffffffff, 0.50 ); + palette.background.fillColor.micaBackground.base = rgbGray( 255, 0.50 ); - palette.background.fillColor.solidBackground.base = 0xffF3F3F3; - palette.background.fillColor.solidBackground.secondary = 0xffEEEEEE; - palette.background.fillColor.solidBackground.tertiary = 0xffF9F9F9; - palette.background.fillColor.solidBackground.quaternary = 0xffffffff; + palette.background.fillColor.solidBackground.base = rgbGray( 243 ); + palette.background.fillColor.solidBackground.secondary = rgbGray( 238 ); + palette.background.fillColor.solidBackground.tertiary = rgbGray( 249 ); + palette.background.fillColor.solidBackground.quaternary = rgbGray( 255 ); // Shadow: - shadow.cardRest = qMakePair( QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), QskRgb::toTransparentF( 0xff000000, 0.04 ) ); - shadow.cardHover = qMakePair( QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), QskRgb::toTransparentF( 0xff000000, 0.10 ) ); - shadow.tooltip = qMakePair( QskShadowMetrics( 0, 8, QPointF( 0, 4 ) ), QskRgb::toTransparentF( 0xff000000, 0.14 ) ); - shadow.flyout = qMakePair( QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), QskRgb::toTransparentF( 0xff000000, 0.14 ) ); + shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.04 ) }; + shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.10 ) }; + shadow.tooltip = { QskShadowMetrics( 0, 8, QPointF( 0, 4 ) ), rgbGray( 0, 0.14 ) }; + shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.14 ) }; // ### should actually be drawn twice with different values: - shadow.dialog = qMakePair( QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), QskRgb::toTransparentF( 0xff000000, 0.1474 ) ); + shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) }; } else if( theme == Dark ) { // Fill color: - palette.fillColor.text.primary = 0xffffffff; - palette.fillColor.text.secondary = QskRgb::toTransparentF( 0xffffffff, 0.786 ); - palette.fillColor.text.tertiary = QskRgb::toTransparentF( 0xffffffff, 0.5442 ); - palette.fillColor.text.disabled = QskRgb::toTransparentF( 0xffffffff, 0.3628 ); + palette.fillColor.text.primary = rgbGray( 255 ); + palette.fillColor.text.secondary = rgbGray( 255, 0.786 ); + palette.fillColor.text.tertiary = rgbGray( 255, 0.5442 ); + palette.fillColor.text.disabled = rgbGray( 255, 0.3628 ); palette.fillColor.accentText.primary = accentColors[ AccentLight3 ]; palette.fillColor.accentText.secondary = accentColors[ AccentLight3 ]; palette.fillColor.accentText.tertiary = accentColors[ AccentLight2 ]; - palette.fillColor.accentText.disabled = QskRgb::toTransparentF( 0xffffffff, 0.3628 ); + palette.fillColor.accentText.disabled = rgbGray( 255, 0.3628 ); - palette.fillColor.textOnAccent.primary = 0xff000000; - palette.fillColor.textOnAccent.secondary = QskRgb::toTransparentF( 0xff000000, 0.50 ); - palette.fillColor.textOnAccent.disabled = QskRgb::toTransparentF( 0xffffffff, 0.5302 ); - palette.fillColor.textOnAccent.selectedText = 0xffffffff; + palette.fillColor.textOnAccent.primary = rgbGray( 0 ); + palette.fillColor.textOnAccent.secondary = rgbGray( 0, 0.50 ); + palette.fillColor.textOnAccent.disabled = rgbGray( 255, 0.5302 ); + palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); palette.fillColor.control.transparent = Qt::transparent; - palette.fillColor.control.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.0605 ); - palette.fillColor.control.secondary = QskRgb::toTransparentF( 0xffffffff, 0.0837 ); - palette.fillColor.control.tertiary = QskRgb::toTransparentF( 0xffffffff, 0.0326 ); - palette.fillColor.control.inputActive = QskRgb::toTransparentF( 0xff1E1E1E, 0.70 ); - palette.fillColor.control.disabled = QskRgb::toTransparentF( 0xffffffff, 0.0419 ); + palette.fillColor.control.defaultColor = rgbGray( 255, 0.0605 ); + palette.fillColor.control.secondary = rgbGray( 255, 0.0837 ); + palette.fillColor.control.tertiary = rgbGray( 255, 0.0326 ); + palette.fillColor.control.inputActive = rgbGray( 30, 0.70 ); + palette.fillColor.control.disabled = rgbGray( 255, 0.0419 ); - palette.fillColor.controlStrong.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.5442 ); - palette.fillColor.controlStrong.disabled = QskRgb::toTransparentF( 0xffffffff, 0.2465 ); + palette.fillColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); + palette.fillColor.controlStrong.disabled = rgbGray( 255, 0.2465 ); palette.fillColor.subtle.transparent = Qt::transparent; - palette.fillColor.subtle.secondary =QskRgb::toTransparentF( 0xffffffff, 0.0605 ); - palette.fillColor.subtle.tertiary = QskRgb::toTransparentF( 0xffffffff, 0.0419 ); + palette.fillColor.subtle.secondary = rgbGray( 255, 0.0605 ); + palette.fillColor.subtle.tertiary = rgbGray( 255, 0.0419 ); palette.fillColor.subtle.disabled = Qt::transparent; - palette.fillColor.controlSolid.defaultColor = 0xff454545; + palette.fillColor.controlSolid.defaultColor = rgbGray( 69 ); palette.fillColor.controlAlt.transparent = Qt::transparent; - palette.fillColor.controlAlt.secondary = QskRgb::toTransparentF( 0xff000000, 0.10 ); - palette.fillColor.controlAlt.tertiary = QskRgb::toTransparentF( 0xffffffff, 0.0419 ); - palette.fillColor.controlAlt.quaternary = QskRgb::toTransparentF( 0xffffffff, 0.0698 ); + palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.10 ); + palette.fillColor.controlAlt.tertiary = rgbGray( 255, 0.0419 ); + palette.fillColor.controlAlt.quaternary = rgbGray( 255, 0.0698 ); palette.fillColor.controlAlt.disabled = Qt::transparent; palette.fillColor.accent.defaultColor = accentColors[ AccentLight2 ]; palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentLight2 ], 0.90 ); palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentLight2 ], 0.80 ); - palette.fillColor.accent.disabled = QskRgb::toTransparentF( 0xffffffff, 0.1581 ); + palette.fillColor.accent.disabled = rgbGray( 255, 0.1581 ); palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; - palette.fillColor.system.critical = 0xffFF99A4; - palette.fillColor.system.success = 0xff6CCB5F; - palette.fillColor.system.attention = 0xff60CDFF; - palette.fillColor.system.caution = 0xffFCE100; - palette.fillColor.system.attentionBackground = QskRgb::toTransparentF( 0xffffffff, 0.0326 ); - palette.fillColor.system.successBackground = 0xff393D1B; + palette.fillColor.system.critical = 0xffff99a4; + palette.fillColor.system.success = 0xff6ccb5f; + palette.fillColor.system.attention = 0xff60cdff; + palette.fillColor.system.caution = 0xfffce100; + palette.fillColor.system.attentionBackground = rgbGray( 255, 0.0326 ); + palette.fillColor.system.successBackground = 0xff393d1b; palette.fillColor.system.cautionBackground = 0xff433519; palette.fillColor.system.criticalBackground = 0xff442726; - palette.fillColor.system.neutral = QskRgb::toTransparentF( 0xffffffff, 0.5442 ); - palette.fillColor.system.neutralBackground = QskRgb::toTransparentF( 0xffffffff, 0.0326 ); - palette.fillColor.system.solidNeutral = 0xff9D9D9D; - palette.fillColor.system.solidAttentionBackground = 0xff2E2E2E; - palette.fillColor.system.solidNeutralBackground = 0xff2E2E2E; + palette.fillColor.system.neutral = rgbGray( 255, 0.5442 ); + palette.fillColor.system.neutralBackground = rgbGray( 255, 0.0326 ); + palette.fillColor.system.solidNeutral = rgbGray( 157 ); + palette.fillColor.system.solidAttentionBackground = rgbGray( 46 ); + palette.fillColor.system.solidNeutralBackground = rgbGray( 46 ); // Elevation: - palette.elevation.control.border = { QskRgb::toTransparentF( 0xffffffff, 0.093 ), - QskRgb::toTransparentF( 0xffffffff, 0.0698 ) }; + palette.elevation.control.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; + palette.elevation.circle.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; - palette.elevation.circle.border = { QskRgb::toTransparentF( 0xffffffff, 0.093 ), - QskRgb::toTransparentF( 0xffffffff, 0.0698 ) }; + palette.elevation.textControl.border = { rgbGray( 255, 0.08 ), palette.fillColor.text.secondary }; - palette.elevation.textControl.border = { QskRgb::toTransparentF( 0xffffffff, 0.08 ), - palette.fillColor.text.secondary }; - - - palette.elevation.textControl.borderFocused = { QskRgb::toTransparentF( 0xffffffff, 0.08 ), - QskRgb::toTransparentF( 0xffffffff, 0.08 ) }; - - palette.elevation.accentControl.border = { QskRgb::toTransparentF( 0xffffffff, 0.08 ), - QskRgb::toTransparentF( 0xff000000, 0.14 ) }; + palette.elevation.textControl.borderFocused = { rgbGray( 255, 0.08 ), rgbGray( 255, 0.08 ) }; + palette.elevation.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.14 ) }; // Stroke color: - palette.strokeColor.controlStroke.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.0698 ); - palette.strokeColor.controlStroke.secondary = QskRgb::toTransparentF( 0xffffffff, 0.093 ); - palette.strokeColor.controlStroke.onAccentDefault = QskRgb::toTransparentF( 0xffffffff, 0.08 ); - palette.strokeColor.controlStroke.onAccentSecondary = QskRgb::toTransparentF( 0xff000000, 0.14 ); - palette.strokeColor.controlStroke.onAccentTertiary = QskRgb::toTransparentF( 0xff000000, 0.2169 ); - palette.strokeColor.controlStroke.onAccentDisabled = QskRgb::toTransparentF( 0xff000000, 0.20 ); - palette.strokeColor.controlStroke.forStrongFillWhenOnImage = QskRgb::toTransparentF( 0xff000000, 0.42 ); + palette.strokeColor.controlStroke.defaultColor = rgbGray( 255, 0.0698 ); + palette.strokeColor.controlStroke.secondary = rgbGray( 255, 0.093 ); + palette.strokeColor.controlStroke.onAccentDefault = rgbGray( 255, 0.08 ); + palette.strokeColor.controlStroke.onAccentSecondary = rgbGray( 0, 0.14 ); + palette.strokeColor.controlStroke.onAccentTertiary = rgbGray( 0, 0.2169 ); + palette.strokeColor.controlStroke.onAccentDisabled = rgbGray( 0, 0.20 ); + palette.strokeColor.controlStroke.forStrongFillWhenOnImage = rgbGray( 0, 0.42 ); - palette.strokeColor.controlStrongStroke.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.5442 ); - palette.strokeColor.controlStrongStroke.disabled = QskRgb::toTransparentF( 0xffffffff, 0.1581 ); + palette.strokeColor.controlStrongStroke.defaultColor = rgbGray( 255, 0.5442 ); + palette.strokeColor.controlStrongStroke.disabled = rgbGray( 255, 0.1581 ); - palette.strokeColor.cardStroke.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.0578 ); - palette.strokeColor.cardStroke.defaultSolid = 0xffEBEBEB; + palette.strokeColor.cardStroke.defaultColor = rgbGray( 255, 0.0578 ); + palette.strokeColor.cardStroke.defaultSolid = rgbGray( 235 ); - palette.strokeColor.dividerStroke.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.0837 ); + palette.strokeColor.dividerStroke.defaultColor = rgbGray( 255, 0.0837 ); - palette.strokeColor.surfaceStroke.defaultColor = QskRgb::toTransparentF( 0xff757575, 0.40 ); - palette.strokeColor.surfaceStroke.flyout = QskRgb::toTransparentF( 0xff000000, 0.20 ); + palette.strokeColor.surfaceStroke.defaultColor = rgbGray( 117, 0.40 ); + palette.strokeColor.surfaceStroke.flyout = rgbGray( 0, 0.20 ); - palette.strokeColor.focusStroke.outer = 0xffffffff; - palette.strokeColor.focusStroke.inner = QskRgb::toTransparentF( 0xff000000, 0.70 ); + palette.strokeColor.focusStroke.outer = rgbGray( 255 ); + palette.strokeColor.focusStroke.inner = rgbGray( 0, 0.70 ); // Background: - palette.background.fillColor.cardBackground.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.0512 ); - palette.background.fillColor.cardBackground.secondary = QskRgb::toTransparentF( 0xffffffff, 0.0326 ); - palette.background.fillColor.cardBackground.tertiary = 0xffffffff; // not set in Figma + palette.background.fillColor.cardBackground.defaultColor = rgbGray( 255, 0.0512 ); + palette.background.fillColor.cardBackground.secondary = rgbGray( 255, 0.0326 ); + palette.background.fillColor.cardBackground.tertiary = rgbGray( 255 ); // not set in Figma - palette.background.fillColor.smoke.defaultColor = QskRgb::toTransparentF( 0xff000000, 0.30 ); + palette.background.fillColor.smoke.defaultColor = rgbGray( 0, 0.30 ); - palette.background.fillColor.layer.defaultColor = QskRgb::toTransparentF( 0xff3A3A3A, 0.30 ); - palette.background.fillColor.layer.alt = QskRgb::toTransparentF( 0xffffffff, 0.0538 ); + palette.background.fillColor.layer.defaultColor = rgbGray( 58, 0.30 ); + palette.background.fillColor.layer.alt = rgbGray( 255, 0.0538 ); - palette.background.fillColor.layerOnAcrylic.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.0359 ); + palette.background.fillColor.layerOnAcrylic.defaultColor = rgbGray( 255, 0.0359 ); - palette.background.fillColor.layerOnAccentAcrylic.defaultColor = QskRgb::toTransparentF( 0xffffffff, 0.0359 ); + palette.background.fillColor.layerOnAccentAcrylic.defaultColor = rgbGray( 255, 0.0359 ); - palette.background.fillColor.acrylicBackground.defaultColor = QskRgb::toTransparentF( 0xff2C2C2C, 0.96 ); - palette.background.fillColor.acrylicBackground.base = QskRgb::toTransparentF( 0xff202020, 0.90 ); + palette.background.fillColor.acrylicBackground.defaultColor = rgbGray( 44, 0.96 ); + palette.background.fillColor.acrylicBackground.base = rgbGray( 32, 0.90 ); palette.background.fillColor.accentAcrylicBackground.base = QskRgb::toTransparentF( accentColors[ AccentDark2 ], 0.80 ); palette.background.fillColor.accentAcrylicBackground.defaultColor = QskRgb::toTransparentF( accentColors[ AccentBase ], 0.80 ); - palette.background.fillColor.micaBackground.base = QskRgb::toTransparentF( 0xffffffff, 0.50 ); + palette.background.fillColor.micaBackground.base = rgbGray( 255, 0.50 ); - palette.background.fillColor.solidBackground.base = 0xff202020; - palette.background.fillColor.solidBackground.secondary = 0xff1C1C1C; - palette.background.fillColor.solidBackground.tertiary = 0xff282828; - palette.background.fillColor.solidBackground.quaternary = 0xff2C2C2C; + palette.background.fillColor.solidBackground.base = rgbGray( 32 ); + palette.background.fillColor.solidBackground.secondary = rgbGray( 28 ); + palette.background.fillColor.solidBackground.tertiary = rgbGray( 40 ); + palette.background.fillColor.solidBackground.quaternary = rgbGray( 44 ); // Shadow: - shadow.cardRest = qMakePair( QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), QskRgb::toTransparentF( 0xff000000, 0.13 ) ); - shadow.cardHover = qMakePair( QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), QskRgb::toTransparentF( 0xff000000, 0.26 ) ); - shadow.tooltip = qMakePair( QskShadowMetrics( 0, 8, QPointF( 0, 4 ) ), QskRgb::toTransparentF( 0xff000000, 0.26 ) ); - shadow.flyout = qMakePair( QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), QskRgb::toTransparentF( 0xff000000, 0.26 ) ); + shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.13 ) }; + shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.26 ) }; + shadow.tooltip = { QskShadowMetrics( 0, 8, QPointF( 0, 4 ) ), rgbGray( 0, 0.26 ) }; + shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.26 ) }; // ### should actually be drawn twice with different values: - shadow.dialog = qMakePair( QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), QskRgb::toTransparentF( 0xff000000, 0.37 ) ); + shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.37 ) }; } } diff --git a/skins/fluent2/QskFluent2Skin.h b/skins/fluent2/QskFluent2Skin.h index 0f02cc95..458b6940 100644 --- a/skins/fluent2/QskFluent2Skin.h +++ b/skins/fluent2/QskFluent2Skin.h @@ -38,7 +38,7 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme }; QskFluent2Theme( Theme ); - QskFluent2Theme( Theme, std::array< QRgb, NumAccentColors > ); + QskFluent2Theme( Theme, const std::array< QRgb, NumAccentColors >& ); typedef std::array< QRgb, 2 > BorderGradient; From c65141a1b88a7c1482b45473ea3ab6aa8f6f82d6 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 17:51:54 +0200 Subject: [PATCH 05/60] unused definitions removed --- skins/fluent2/QskFluent2Skin.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.h b/skins/fluent2/QskFluent2Skin.h index 458b6940..d6d76f41 100644 --- a/skins/fluent2/QskFluent2Skin.h +++ b/skins/fluent2/QskFluent2Skin.h @@ -133,14 +133,6 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme QRgb solidNeutralBackground; }; - struct ControlOnImage - { - QRgb defaultColor; - QRgb secondary; - QRgb tertiary; - QRgb disabled; - }; - Text text; AccentText accentText; TextOnAccent textOnAccent; @@ -151,7 +143,6 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme ControlAlt controlAlt; Accent accent; System system; - ControlOnImage controlOnImage; }; struct Elevation From 886a250015a5ffb11f062352b06050f1da006c00 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 19:10:44 +0200 Subject: [PATCH 06/60] defiitions removed, that are very unlikely to become relevant for the first QSkinny release --- skins/fluent2/QskFluent2Skin.cpp | 238 ++++++++++++------------------- skins/fluent2/QskFluent2Skin.h | 226 +++++++++-------------------- 2 files changed, 160 insertions(+), 304 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index b07391d3..cb960022 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -177,9 +177,9 @@ void Editor::setupBox() const auto& pal = theme.palette; - setGradient( Q::Panel, pal.background.fillColor.solidBackground.base ); - setGradient( Q::Panel | A::Header, pal.background.fillColor.solidBackground.tertiary ); - setGradient( Q::Panel | A::Footer, pal.background.fillColor.solidBackground.tertiary ); + setGradient( Q::Panel, pal.background.solid.base ); + setGradient( Q::Panel | A::Header, pal.background.solid.tertiary ); + setGradient( Q::Panel | A::Footer, pal.background.solid.tertiary ); } void Editor::setupCheckBox() @@ -197,7 +197,7 @@ void Editor::setupCheckBox() setPadding( Q::Box, 5 ); // "icon size" setGradient( Q::Box, pal.fillColor.controlAlt.secondary ); - setBoxBorderColors( Q::Box, pal.strokeColor.controlStrongStroke.defaultColor ); + setBoxBorderColors( Q::Box, pal.strokeColor.controlStrong.defaultColor ); setGradient( Q::Box | Q::Checked, pal.fillColor.accent.defaultColor ); setBoxBorderColors( Q::Box | Q::Checked, pal.fillColor.accent.defaultColor ); @@ -211,19 +211,19 @@ void Editor::setupCheckBox() setGradient( Q::Box | Q::Hovered, pal.fillColor.controlAlt.tertiary ); - setBoxBorderColors( Q::Box | Q::Hovered, pal.strokeColor.controlStrongStroke.defaultColor ); + setBoxBorderColors( Q::Box | Q::Hovered, pal.strokeColor.controlStrong.defaultColor ); setGradient( Q::Box | Q::Hovered | Q::Checked, pal.fillColor.accent.secondary ); setBoxBorderColors( Q::Box | Q::Hovered | Q::Checked, pal.fillColor.accent.secondary ); // indicator the same as in Rest state setGradient( Q::Box | Q::Pressed, pal.fillColor.controlAlt.quaternary ); - setBoxBorderColors( Q::Box | Q::Pressed, pal.strokeColor.controlStrongStroke.disabled ); + setBoxBorderColors( Q::Box | Q::Pressed, pal.strokeColor.controlStrong.disabled ); setGradient( Q::Box | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); setBoxBorderColors( Q::Box | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); setGraphicRole( Q::Indicator | Q::Pressed | Q::Checked, QskFluent2Skin::GraphicRoleFillColorTextOnAccentSecondary ); setGradient( Q::Box | Q::Disabled, pal.fillColor.controlAlt.disabled ); - setBoxBorderColors( Q::Box | Q::Disabled, pal.strokeColor.controlStrongStroke.disabled ); + setBoxBorderColors( Q::Box | Q::Disabled, pal.strokeColor.controlStrong.disabled ); setGradient( Q::Box | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); setBoxBorderColors( Q::Box | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); setGraphicRole( Q::Indicator | Q::Disabled | Q::Checked, QskFluent2Skin::GraphicRoleFillColorTextOnAccentDisabled ); @@ -280,7 +280,7 @@ void Editor::setupComboBox() // Disabled: setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.controlStroke.defaultColor ); + setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.control.defaultColor ); setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); setGraphicRole( Q::Icon | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); @@ -294,7 +294,7 @@ void Editor::setupDialogButtonBox() const auto& pal = theme.palette; setPadding( Q::Panel, 24 ); - setGradient( Q::Panel, pal.background.fillColor.solidBackground.base ); + setGradient( Q::Panel, pal.background.solid.base ); setPadding(Q::Panel, 20 ); } @@ -306,7 +306,7 @@ void Editor::setupFocusIndicator() setBoxBorderMetrics( Q::Panel, 2 ); setPadding( Q::Panel, 3 ); setBoxShape( Q::Panel, 4 ); - setBoxBorderColors( Q::Panel, pal.strokeColor.focusStroke.outer ); + setBoxBorderColors( Q::Panel, pal.strokeColor.focus.outer ); } void Editor::setupInputPanel() @@ -324,11 +324,11 @@ void Editor::setupMenu() setPadding( Q::Panel, { 4, 6, 4, 6 } ); setBoxBorderMetrics( Q::Panel, 1 ); - setBoxBorderColors( Q::Panel, pal.strokeColor.surfaceStroke.flyout ); + setBoxBorderColors( Q::Panel, pal.strokeColor.surface.flyout ); setBoxShape( Q::Panel, 7 ); - setGradient( Q::Panel, pal.background.fillColor.acrylicBackground.defaultColor ); - setShadowMetrics( Q::Panel, theme.shadow.flyout.first ); // ### metrics should be the same, just color differs - setShadowColor( Q::Panel, theme.shadow.flyout.second ); + setGradient( Q::Panel, pal.background.flyout.defaultColor ); + setShadowMetrics( Q::Panel, theme.shadow.flyout.metrics ); + setShadowColor( Q::Panel, theme.shadow.flyout.color ); setPadding( Q::Segment, { 0, 10, 0, 10 } ); setSpacing( Q::Segment, 15 ); @@ -361,7 +361,7 @@ void Editor::setupPopup() using Q = QskPopup; const auto& pal = theme.palette; - setGradient( Q::Overlay, pal.background.fillColor.smoke.defaultColor ); + setGradient( Q::Overlay, pal.background.overlay.defaultColor ); } void Editor::setupProgressBar() @@ -372,7 +372,7 @@ void Editor::setupProgressBar() setMetric( Q::Groove | A::Size, 1 ); setBoxShape( Q::Groove, 100, Qt::RelativeSize ); - setGradient( Q::Groove, pal.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Groove, pal.strokeColor.controlStrong.defaultColor ); setMetric( Q::Bar| A::Size, 3 ); setBoxShape( Q::Bar, 100, Qt::RelativeSize ); @@ -418,7 +418,7 @@ void Editor::setupPushButton() setColor( Q::Text | W::Accent | Q::Pressed, pal.fillColor.textOnAccent.secondary ); setGraphicRole( Q::Icon | W::Accent | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextOnAccentSecondary ); - const QRgb accentPressedBorderColor = flattenedColor( pal.strokeColor.controlStroke.onAccentDefault, + const QRgb accentPressedBorderColor = flattenedColor( pal.strokeColor.control.onAccentDefault, pal.fillColor.accent.tertiary ); setBoxBorderColors( Q::Panel | W::Accent | Q::Pressed, accentPressedBorderColor ); @@ -448,7 +448,7 @@ void Editor::setupPushButton() setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); - const QRgb standardPressedBorderColor = flattenedColor( pal.strokeColor.controlStroke.defaultColor, + const QRgb standardPressedBorderColor = flattenedColor( pal.strokeColor.control.defaultColor, pal.fillColor.control.tertiary ); setBoxBorderColors( Q::Panel | Q::Pressed, standardPressedBorderColor ); @@ -458,7 +458,7 @@ void Editor::setupPushButton() setGraphicRole( Q::Icon | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextSecondary ); - const QRgb standardDisabledBorderColor = flattenedColor( pal.strokeColor.controlStroke.defaultColor, + const QRgb standardDisabledBorderColor = flattenedColor( pal.strokeColor.control.defaultColor, pal.fillColor.control.disabled ); setBoxBorderColors( Q::Panel | Q::Disabled, standardDisabledBorderColor ); @@ -485,7 +485,7 @@ void Editor::setupRadioBox() // Rest setGradient( Q::CheckIndicatorPanel, pal.fillColor.controlAlt.secondary ); - setBoxBorderColors( Q::CheckIndicatorPanel, pal.strokeColor.controlStrongStroke.defaultColor ); + setBoxBorderColors( Q::CheckIndicatorPanel, pal.strokeColor.controlStrong.defaultColor ); setGradient( Q::CheckIndicatorPanel | Q::Selected, pal.fillColor.accent.defaultColor ); setBoxBorderMetrics( Q::CheckIndicatorPanel | Q::Selected, 0 ); @@ -513,7 +513,7 @@ void Editor::setupRadioBox() // Pressed setGradient( Q::CheckIndicatorPanel | Q::Pressed, pal.fillColor.controlAlt.quaternary ); - setBoxBorderColors( Q::CheckIndicatorPanel | Q::Pressed, pal.strokeColor.controlStrongStroke.disabled ); + setBoxBorderColors( Q::CheckIndicatorPanel | Q::Pressed, pal.strokeColor.controlStrong.disabled ); setPadding( Q::CheckIndicatorPanel | Q::Pressed, { 7, 7 } ); // indicator "strut size" @@ -533,7 +533,7 @@ void Editor::setupRadioBox() // Disabled setGradient( Q::CheckIndicatorPanel | Q::Disabled, pal.fillColor.controlAlt.disabled ); - setBoxBorderColors( Q::CheckIndicatorPanel | Q::Disabled, pal.strokeColor.controlStrongStroke.disabled ); + setBoxBorderColors( Q::CheckIndicatorPanel | Q::Disabled, pal.strokeColor.controlStrong.disabled ); setGradient( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, pal.fillColor.accent.disabled ); setBoxBorderMetrics( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, 0 ); @@ -590,7 +590,7 @@ void Editor::setupSegmentedBar() setColor( Q::Text | Q::Selected, pal.fillColor.textOnAccent.primary ); // Disabled: - const QRgb standardDisabledBorderColor = flattenedColor( pal.strokeColor.controlStroke.defaultColor, + const QRgb standardDisabledBorderColor = flattenedColor( pal.strokeColor.control.defaultColor, pal.fillColor.control.disabled ); setBoxBorderColors( Q::Segment | Q::Disabled, standardDisabledBorderColor ); @@ -621,7 +621,7 @@ void Editor::setupSeparator() setMetric( aspect | A::Size, 1 ); setBoxShape( Q::Panel, 0 ); setBoxBorderMetrics( Q::Panel, 0 ); - setGradient( aspect, pal.strokeColor.dividerStroke.defaultColor ); + setGradient( aspect, pal.strokeColor.divider.defaultColor ); } } @@ -724,7 +724,7 @@ void Editor::setupSpinBox() // Disabled: setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.controlStroke.defaultColor ); + setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.control.defaultColor ); setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); @@ -745,11 +745,11 @@ void Editor::setupTabButton() setPadding( Q::Panel, { 7, 0, 7, 0 } ); setBoxShape( Q::Panel, { 7, 7, 0, 0 } ); - setGradient( Q::Panel, pal.fillColor.subtle.transparent ); + setGradient( Q::Panel, Qt::transparent ); setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1 } ); - setBoxBorderColors( Q::Panel, pal.strokeColor.cardStroke.defaultColor ); + setBoxBorderColors( Q::Panel, pal.strokeColor.card.defaultColor ); - setGradient( Q::Panel | Q::Checked, pal.background.fillColor.solidBackground.tertiary ); + setGradient( Q::Panel | Q::Checked, pal.background.solid.tertiary ); setBoxBorderMetrics( Q::Panel | Q::Checked, { 1, 1, 1, 0 } ); setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter ); @@ -770,7 +770,7 @@ void Editor::setupTabView() using Q = QskTabView; const auto& pal = theme.palette; - setGradient( Q::Page, pal.background.fillColor.solidBackground.tertiary ); + setGradient( Q::Page, pal.background.solid.tertiary ); } void Editor::setupTextLabel() @@ -830,7 +830,7 @@ void Editor::setupTextInput() // Disabled: setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.controlStroke.defaultColor ); + setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.control.defaultColor ); setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); } @@ -859,10 +859,10 @@ void Editor::setupSwitchButton() setGradient( Q::Groove, pal.fillColor.controlAlt.secondary ); setGradient( Q::Groove | Q::Checked, pal.fillColor.accent.defaultColor ); - setBoxBorderColors( Q::Groove, pal.strokeColor.controlStrongStroke.defaultColor ); + setBoxBorderColors( Q::Groove, pal.strokeColor.controlStrong.defaultColor ); setStrutSize( Q::Handle, 12, 12 ); - setGradient( Q::Handle, pal.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Handle, pal.strokeColor.controlStrong.defaultColor ); setGradient( Q::Handle | Q::Checked, pal.fillColor.textOnAccent.primary ); setBoxBorderGradient( Q::Handle | Q::Checked, pal.elevation.circle.border, @@ -883,12 +883,12 @@ void Editor::setupSwitchButton() setGradient( Q::Groove | Q::Pressed, pal.fillColor.controlAlt.quaternary ); setGradient( Q::Groove | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); - setBoxBorderColors( Q::Groove | Q::Pressed, pal.strokeColor.controlStrongStroke.defaultColor ); + setBoxBorderColors( Q::Groove | Q::Pressed, pal.strokeColor.controlStrong.defaultColor ); const QSizeF pressedSize( 17, 14 ); setStrutSize( Q::Handle | Q::Pressed | A::Horizontal, pressedSize, { QskStateCombination::CombinationNoState, Q::Checked } ); setStrutSize( Q::Handle | Q::Pressed | A::Vertical, pressedSize.transposed(), { QskStateCombination::CombinationNoState, Q::Checked } ); - setGradient( Q::Handle | Q::Pressed, pal.strokeColor.controlStrongStroke.defaultColor ); + setGradient( Q::Handle | Q::Pressed, pal.strokeColor.controlStrong.defaultColor ); // Handle | Pressed | Checked is the same as in Rest state setBoxBorderGradient( Q::Handle | Q::Pressed | Q::Checked, pal.elevation.circle.border, @@ -914,10 +914,10 @@ void Editor::setupSubWindow() setPadding( Q::Panel, { 0, 31, 0, 0 } ); setBoxShape( Q::Panel, 7 ); setBoxBorderMetrics( Q::Panel, 1 ); - setBoxBorderColors( Q::Panel, pal.strokeColor.surfaceStroke.defaultColor ); - setGradient( Q::Panel, pal.background.fillColor.layer.alt ); - setShadowMetrics( Q::Panel, theme.shadow.dialog.first ); - setShadowColor( Q::Panel, theme.shadow.dialog.second ); + setBoxBorderColors( Q::Panel, pal.strokeColor.surface.defaultColor ); + setGradient( Q::Panel, pal.background.layer.alt ); + setShadowMetrics( Q::Panel, theme.shadow.dialog.metrics ); + setShadowColor( Q::Panel, theme.shadow.dialog.color ); setHint( Q::TitleBarPanel | QskAspect::Style, Q::TitleBar | Q::Title ); setPadding( Q::TitleBarPanel, { 24, 31, 24, 0 } ); @@ -942,7 +942,7 @@ void Editor::setupVirtualKeyboard() setFontRole( Q::ButtonText, QskFluent2Skin::BodyLarge ); setColor( Q::ButtonText | QskPushButton::Pressed, pal.fillColor.text.secondary ); - setGradient( Q::Panel, pal.background.fillColor.solidBackground.secondary ); + setGradient( Q::Panel, pal.background.solid.secondary ); setPadding( Q::Panel, 8 ); } @@ -982,7 +982,6 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, palette.fillColor.textOnAccent.disabled = rgbGray( 255 ); palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); - palette.fillColor.control.transparent = Qt::transparent; palette.fillColor.control.defaultColor = rgbGray( 255, 0.70 ); palette.fillColor.control.secondary = rgbGray( 249, 0.50 ); palette.fillColor.control.tertiary = rgbGray( 249, 0.30 ); @@ -992,14 +991,12 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, palette.fillColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); palette.fillColor.controlStrong.disabled = rgbGray( 0, 0.3173 ); - palette.fillColor.subtle.transparent = Qt::transparent; palette.fillColor.subtle.secondary = rgbGray( 0, 0.0373 ); palette.fillColor.subtle.tertiary = rgbGray( 0, 0.0241 ); palette.fillColor.subtle.disabled = Qt::transparent; palette.fillColor.controlSolid.defaultColor = rgbGray( 255 ); - palette.fillColor.controlAlt.transparent = Qt::transparent; palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.0241 ); palette.fillColor.controlAlt.tertiary = rgbGray( 0, 0.0578 ); palette.fillColor.controlAlt.quaternary = rgbGray( 0, 0.0924 ); @@ -1011,20 +1008,6 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, palette.fillColor.accent.disabled = rgbGray( 0, 0.2169 ); palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; - palette.fillColor.system.critical = 0xffc42b1c; - palette.fillColor.system.success = 0xff0f7b0f; - palette.fillColor.system.attention = 0xff005fb7; - palette.fillColor.system.caution = 0xff9d5d00; - palette.fillColor.system.attentionBackground = rgbGray( 246, 0.50 ); - palette.fillColor.system.successBackground = 0xffdff6dd; - palette.fillColor.system.cautionBackground = 0xfffff4ce; - palette.fillColor.system.criticalBackground = 0xfffde7e9; - palette.fillColor.system.neutral = rgbGray( 0, 0.4458 ); - palette.fillColor.system.neutralBackground = rgbGray( 0, 0.0241 ); - palette.fillColor.system.solidNeutral = rgbGray( 138 ); - palette.fillColor.system.solidAttentionBackground = rgbGray( 247 ); - palette.fillColor.system.solidNeutralBackground = rgbGray( 243 ); - // Elevation: palette.elevation.control.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; @@ -1035,62 +1018,49 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, // Stroke color: - palette.strokeColor.controlStroke.defaultColor = rgbGray( 0, 0.0578 ); - palette.strokeColor.controlStroke.secondary = rgbGray( 0, 0.1622 ); - palette.strokeColor.controlStroke.onAccentDefault = rgbGray( 255.08 ); - palette.strokeColor.controlStroke.onAccentSecondary = rgbGray( 0, 0.40 ); - palette.strokeColor.controlStroke.onAccentTertiary = rgbGray( 0, 0.2169 ); - palette.strokeColor.controlStroke.onAccentDisabled = rgbGray( 0, 0.0578 ); - palette.strokeColor.controlStroke.forStrongFillWhenOnImage = rgbGray( 255, 0.35 ); + palette.strokeColor.control.defaultColor = rgbGray( 0, 0.0578 ); + palette.strokeColor.control.secondary = rgbGray( 0, 0.1622 ); + palette.strokeColor.control.onAccentDefault = rgbGray( 255.08 ); + palette.strokeColor.control.onAccentSecondary = rgbGray( 0, 0.40 ); + palette.strokeColor.control.onAccentTertiary = rgbGray( 0, 0.2169 ); + palette.strokeColor.control.onAccentDisabled = rgbGray( 0, 0.0578 ); - palette.strokeColor.controlStrongStroke.defaultColor = rgbGray( 0, 0.4458 ); - palette.strokeColor.controlStrongStroke.disabled = rgbGray( 0, 0.2169 ); + palette.strokeColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); + palette.strokeColor.controlStrong.disabled = rgbGray( 0, 0.2169 ); - palette.strokeColor.cardStroke.defaultColor = rgbGray( 0, 0.0578 ); - palette.strokeColor.cardStroke.defaultSolid = rgbGray( 235 ); + palette.strokeColor.card.defaultColor = rgbGray( 0, 0.0578 ); + palette.strokeColor.card.defaultSolid = rgbGray( 235 ); - palette.strokeColor.dividerStroke.defaultColor = rgbGray( 0, 0.0803 ); + palette.strokeColor.divider.defaultColor = rgbGray( 0, 0.0803 ); - palette.strokeColor.surfaceStroke.defaultColor = rgbGray( 117, 0.40 ); - palette.strokeColor.surfaceStroke.flyout = rgbGray( 0, 0.0578 ); + palette.strokeColor.surface.defaultColor = rgbGray( 117, 0.40 ); + palette.strokeColor.surface.flyout = rgbGray( 0, 0.0578 ); - palette.strokeColor.focusStroke.outer = rgbGray( 0, 0.8956 ); - palette.strokeColor.focusStroke.inner = rgbGray( 255 ); + palette.strokeColor.focus.outer = rgbGray( 0, 0.8956 ); + palette.strokeColor.focus.inner = rgbGray( 255 ); // Background: - palette.background.fillColor.cardBackground.defaultColor = rgbGray( 255, 0.70 ); - palette.background.fillColor.cardBackground.secondary = rgbGray( 246, 0.50 ); - palette.background.fillColor.cardBackground.tertiary = rgbGray( 255 ); + palette.background.card.defaultColor = rgbGray( 255, 0.70 ); + palette.background.card.secondary = rgbGray( 246, 0.50 ); + palette.background.card.tertiary = rgbGray( 255 ); - palette.background.fillColor.smoke.defaultColor = rgbGray( 0, 0.30 ); + palette.background.overlay.defaultColor = rgbGray( 0, 0.30 ); - palette.background.fillColor.layer.defaultColor = rgbGray( 255, 0.50 ); - palette.background.fillColor.layer.alt = rgbGray( 255 ); + palette.background.layer.alt = rgbGray( 255 ); - palette.background.fillColor.layerOnAcrylic.defaultColor = rgbGray( 255, 0.25 ); + palette.background.flyout.defaultColor = rgbGray( 252, 0.85 ); - palette.background.fillColor.layerOnAccentAcrylic.defaultColor = rgbGray( 255, 0.25 ); - - palette.background.fillColor.acrylicBackground.defaultColor = rgbGray( 252, 0.85 ); - palette.background.fillColor.acrylicBackground.base = rgbGray( 243, 0.90 ); - - palette.background.fillColor.accentAcrylicBackground.base = QskRgb::toTransparentF( accentColors[ AccentLight3 ], 0.90 ); - palette.background.fillColor.accentAcrylicBackground.defaultColor = QskRgb::toTransparentF( accentColors[ AccentLight3 ], 0.90 ); - - palette.background.fillColor.micaBackground.base = rgbGray( 255, 0.50 ); - - palette.background.fillColor.solidBackground.base = rgbGray( 243 ); - palette.background.fillColor.solidBackground.secondary = rgbGray( 238 ); - palette.background.fillColor.solidBackground.tertiary = rgbGray( 249 ); - palette.background.fillColor.solidBackground.quaternary = rgbGray( 255 ); + palette.background.solid.base = rgbGray( 243 ); + palette.background.solid.secondary = rgbGray( 238 ); + palette.background.solid.tertiary = rgbGray( 249 ); + palette.background.solid.quaternary = rgbGray( 255 ); // Shadow: shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.04 ) }; shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.10 ) }; - shadow.tooltip = { QskShadowMetrics( 0, 8, QPointF( 0, 4 ) ), rgbGray( 0, 0.14 ) }; shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.14 ) }; // ### should actually be drawn twice with different values: shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) }; @@ -1114,7 +1084,6 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, palette.fillColor.textOnAccent.disabled = rgbGray( 255, 0.5302 ); palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); - palette.fillColor.control.transparent = Qt::transparent; palette.fillColor.control.defaultColor = rgbGray( 255, 0.0605 ); palette.fillColor.control.secondary = rgbGray( 255, 0.0837 ); palette.fillColor.control.tertiary = rgbGray( 255, 0.0326 ); @@ -1124,14 +1093,12 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, palette.fillColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); palette.fillColor.controlStrong.disabled = rgbGray( 255, 0.2465 ); - palette.fillColor.subtle.transparent = Qt::transparent; palette.fillColor.subtle.secondary = rgbGray( 255, 0.0605 ); palette.fillColor.subtle.tertiary = rgbGray( 255, 0.0419 ); palette.fillColor.subtle.disabled = Qt::transparent; palette.fillColor.controlSolid.defaultColor = rgbGray( 69 ); - palette.fillColor.controlAlt.transparent = Qt::transparent; palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.10 ); palette.fillColor.controlAlt.tertiary = rgbGray( 255, 0.0419 ); palette.fillColor.controlAlt.quaternary = rgbGray( 255, 0.0698 ); @@ -1143,20 +1110,6 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, palette.fillColor.accent.disabled = rgbGray( 255, 0.1581 ); palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; - palette.fillColor.system.critical = 0xffff99a4; - palette.fillColor.system.success = 0xff6ccb5f; - palette.fillColor.system.attention = 0xff60cdff; - palette.fillColor.system.caution = 0xfffce100; - palette.fillColor.system.attentionBackground = rgbGray( 255, 0.0326 ); - palette.fillColor.system.successBackground = 0xff393d1b; - palette.fillColor.system.cautionBackground = 0xff433519; - palette.fillColor.system.criticalBackground = 0xff442726; - palette.fillColor.system.neutral = rgbGray( 255, 0.5442 ); - palette.fillColor.system.neutralBackground = rgbGray( 255, 0.0326 ); - palette.fillColor.system.solidNeutral = rgbGray( 157 ); - palette.fillColor.system.solidAttentionBackground = rgbGray( 46 ); - palette.fillColor.system.solidNeutralBackground = rgbGray( 46 ); - // Elevation: palette.elevation.control.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; @@ -1169,62 +1122,49 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, // Stroke color: - palette.strokeColor.controlStroke.defaultColor = rgbGray( 255, 0.0698 ); - palette.strokeColor.controlStroke.secondary = rgbGray( 255, 0.093 ); - palette.strokeColor.controlStroke.onAccentDefault = rgbGray( 255, 0.08 ); - palette.strokeColor.controlStroke.onAccentSecondary = rgbGray( 0, 0.14 ); - palette.strokeColor.controlStroke.onAccentTertiary = rgbGray( 0, 0.2169 ); - palette.strokeColor.controlStroke.onAccentDisabled = rgbGray( 0, 0.20 ); - palette.strokeColor.controlStroke.forStrongFillWhenOnImage = rgbGray( 0, 0.42 ); + palette.strokeColor.control.defaultColor = rgbGray( 255, 0.0698 ); + palette.strokeColor.control.secondary = rgbGray( 255, 0.093 ); + palette.strokeColor.control.onAccentDefault = rgbGray( 255, 0.08 ); + palette.strokeColor.control.onAccentSecondary = rgbGray( 0, 0.14 ); + palette.strokeColor.control.onAccentTertiary = rgbGray( 0, 0.2169 ); + palette.strokeColor.control.onAccentDisabled = rgbGray( 0, 0.20 ); - palette.strokeColor.controlStrongStroke.defaultColor = rgbGray( 255, 0.5442 ); - palette.strokeColor.controlStrongStroke.disabled = rgbGray( 255, 0.1581 ); + palette.strokeColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); + palette.strokeColor.controlStrong.disabled = rgbGray( 255, 0.1581 ); - palette.strokeColor.cardStroke.defaultColor = rgbGray( 255, 0.0578 ); - palette.strokeColor.cardStroke.defaultSolid = rgbGray( 235 ); + palette.strokeColor.card.defaultColor = rgbGray( 255, 0.0578 ); + palette.strokeColor.card.defaultSolid = rgbGray( 235 ); - palette.strokeColor.dividerStroke.defaultColor = rgbGray( 255, 0.0837 ); + palette.strokeColor.divider.defaultColor = rgbGray( 255, 0.0837 ); - palette.strokeColor.surfaceStroke.defaultColor = rgbGray( 117, 0.40 ); - palette.strokeColor.surfaceStroke.flyout = rgbGray( 0, 0.20 ); + palette.strokeColor.surface.defaultColor = rgbGray( 117, 0.40 ); + palette.strokeColor.surface.flyout = rgbGray( 0, 0.20 ); - palette.strokeColor.focusStroke.outer = rgbGray( 255 ); - palette.strokeColor.focusStroke.inner = rgbGray( 0, 0.70 ); + palette.strokeColor.focus.outer = rgbGray( 255 ); + palette.strokeColor.focus.inner = rgbGray( 0, 0.70 ); // Background: - palette.background.fillColor.cardBackground.defaultColor = rgbGray( 255, 0.0512 ); - palette.background.fillColor.cardBackground.secondary = rgbGray( 255, 0.0326 ); - palette.background.fillColor.cardBackground.tertiary = rgbGray( 255 ); // not set in Figma + palette.background.card.defaultColor = rgbGray( 255, 0.0512 ); + palette.background.card.secondary = rgbGray( 255, 0.0326 ); + palette.background.card.tertiary = rgbGray( 255 ); // not set in Figma - palette.background.fillColor.smoke.defaultColor = rgbGray( 0, 0.30 ); + palette.background.overlay.defaultColor = rgbGray( 0, 0.30 ); - palette.background.fillColor.layer.defaultColor = rgbGray( 58, 0.30 ); - palette.background.fillColor.layer.alt = rgbGray( 255, 0.0538 ); + palette.background.layer.alt = rgbGray( 255, 0.0538 ); - palette.background.fillColor.layerOnAcrylic.defaultColor = rgbGray( 255, 0.0359 ); + palette.background.flyout.defaultColor = rgbGray( 44, 0.96 ); - palette.background.fillColor.layerOnAccentAcrylic.defaultColor = rgbGray( 255, 0.0359 ); - - palette.background.fillColor.acrylicBackground.defaultColor = rgbGray( 44, 0.96 ); - palette.background.fillColor.acrylicBackground.base = rgbGray( 32, 0.90 ); - - palette.background.fillColor.accentAcrylicBackground.base = QskRgb::toTransparentF( accentColors[ AccentDark2 ], 0.80 ); - palette.background.fillColor.accentAcrylicBackground.defaultColor = QskRgb::toTransparentF( accentColors[ AccentBase ], 0.80 ); - - palette.background.fillColor.micaBackground.base = rgbGray( 255, 0.50 ); - - palette.background.fillColor.solidBackground.base = rgbGray( 32 ); - palette.background.fillColor.solidBackground.secondary = rgbGray( 28 ); - palette.background.fillColor.solidBackground.tertiary = rgbGray( 40 ); - palette.background.fillColor.solidBackground.quaternary = rgbGray( 44 ); + palette.background.solid.base = rgbGray( 32 ); + palette.background.solid.secondary = rgbGray( 28 ); + palette.background.solid.tertiary = rgbGray( 40 ); + palette.background.solid.quaternary = rgbGray( 44 ); // Shadow: shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.13 ) }; shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.26 ) }; - shadow.tooltip = { QskShadowMetrics( 0, 8, QPointF( 0, 4 ) ), rgbGray( 0, 0.26 ) }; shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.26 ) }; // ### should actually be drawn twice with different values: shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.37 ) }; diff --git a/skins/fluent2/QskFluent2Skin.h b/skins/fluent2/QskFluent2Skin.h index d6d76f41..034f0751 100644 --- a/skins/fluent2/QskFluent2Skin.h +++ b/skins/fluent2/QskFluent2Skin.h @@ -44,139 +44,103 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme struct FillColor { - struct Text + struct { QRgb primary; QRgb secondary; QRgb tertiary; QRgb disabled; - }; + } text; - struct AccentText + struct { QRgb primary; QRgb secondary; QRgb tertiary; QRgb disabled; - }; + } accentText; - struct TextOnAccent + struct { QRgb primary; QRgb secondary; QRgb tertiary; QRgb disabled; QRgb selectedText; - }; + } textOnAccent; - struct Control + struct { - QRgb transparent; QRgb defaultColor; QRgb secondary; QRgb tertiary; QRgb inputActive; QRgb disabled; - }; + } control; - struct ControlStrong + struct { QRgb defaultColor; QRgb disabled; - }; + } controlStrong; - struct Subtle + struct { - QRgb transparent; QRgb secondary; QRgb tertiary; QRgb disabled; - }; + } subtle; - struct ControlSolid + struct { QRgb defaultColor; - }; + } controlSolid; - struct ControlAlt + struct { - QRgb transparent; QRgb secondary; QRgb tertiary; QRgb quaternary; QRgb disabled; - }; + } controlAlt; - struct Accent + struct { QRgb defaultColor; QRgb secondary; QRgb tertiary; QRgb disabled; QRgb selectedTextBackground; - }; - - struct System - { - QRgb critical; - QRgb success; - QRgb attention; - QRgb caution; - QRgb attentionBackground; - QRgb successBackground; - QRgb cautionBackground; - QRgb criticalBackground; - QRgb neutral; - QRgb neutralBackground; - QRgb solidNeutral; - QRgb solidAttentionBackground; - QRgb solidNeutralBackground; - }; - - Text text; - AccentText accentText; - TextOnAccent textOnAccent; - Control control; - ControlStrong controlStrong; - Subtle subtle; - ControlSolid controlSolid; - ControlAlt controlAlt; - Accent accent; - System system; + } accent; }; struct Elevation { - struct Control + struct { BorderGradient border; - }; + } control; - struct Circle + struct { BorderGradient border; - }; + } circle; - struct TextControl + struct { BorderGradient border; BorderGradient borderFocused; - }; + } textControl; - struct AccentControl + struct { BorderGradient border; - }; - - Control control; - Circle circle; - TextControl textControl; - AccentControl accentControl; + } accentControl; }; struct StrokeColor { - struct ControlStroke + struct { QRgb defaultColor; QRgb secondary; @@ -184,140 +148,92 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme QRgb onAccentSecondary; QRgb onAccentTertiary; QRgb onAccentDisabled; - QRgb forStrongFillWhenOnImage; - }; + } control; - struct ControlStrongStroke + struct { QRgb defaultColor; QRgb disabled; - }; + } controlStrong; - struct CardStroke + struct { QRgb defaultColor; QRgb defaultSolid; - }; + } card; - struct DividerStroke + struct { QRgb defaultColor; - }; + } divider; - struct SurfaceStroke + struct { QRgb defaultColor; QRgb flyout; - }; + } surface; - struct FocusStroke + struct { QRgb outer; QRgb inner; - }; - - ControlStroke controlStroke; - ControlStrongStroke controlStrongStroke; - CardStroke cardStroke; - DividerStroke dividerStroke; - SurfaceStroke surfaceStroke; - FocusStroke focusStroke; + } focus; }; struct Background { - struct FillColor + struct { - struct CardBackground - { - QRgb defaultColor; - QRgb secondary; - QRgb tertiary; - }; + QRgb defaultColor; + QRgb secondary; + QRgb tertiary; + } card; - struct Smoke - { - QRgb defaultColor; - }; + struct + { + QRgb defaultColor; + } overlay; - struct Layer - { - QRgb defaultColor; - QRgb alt; - }; + struct + { + QRgb alt; + } layer; - struct LayerOnAcrylic - { - QRgb defaultColor; - }; + struct + { + QRgb defaultColor; + } flyout; - struct LayerOnAccentAcrylic - { - QRgb defaultColor; - }; - - struct AcrylicBackground - { - QRgb defaultColor; - QRgb base; - }; - - struct AccentAcrylicBackground - { - QRgb base; - QRgb defaultColor; - }; - - struct MicaBackground - { - QRgb base; - }; - - struct SolidBackground - { - QRgb base; - QRgb secondary; - QRgb tertiary; - QRgb quaternary; - }; - - CardBackground cardBackground; - Smoke smoke; - Layer layer; - LayerOnAcrylic layerOnAcrylic; - LayerOnAccentAcrylic layerOnAccentAcrylic; - AcrylicBackground acrylicBackground; - AccentAcrylicBackground accentAcrylicBackground; - MicaBackground micaBackground; - SolidBackground solidBackground; - }; - - FillColor fillColor; + struct + { + QRgb base; + QRgb secondary; + QRgb tertiary; + QRgb quaternary; + } solid; }; - - struct Palette + struct { FillColor fillColor; Elevation elevation; StrokeColor strokeColor; Background background; + } palette; + + struct ShadowSettings + { + QskShadowMetrics metrics; + QRgb color; }; - Palette palette; - - typedef QPair< QskShadowMetrics, QRgb > ShadowSettings; - - struct Shadow + struct { ShadowSettings cardRest; ShadowSettings cardHover; - ShadowSettings tooltip; ShadowSettings flyout; ShadowSettings dialog; - }; - - Shadow shadow; + } shadow; }; class QSK_FLUENT2_EXPORT QskFluent2Skin : public QskSkin From b74a741bd845d57bf9f38f7e43573e628e1bf68c Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 19:15:15 +0200 Subject: [PATCH 07/60] blocking fluent2 skins again --- src/controls/QskSkinManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/controls/QskSkinManager.cpp b/src/controls/QskSkinManager.cpp index 048a4757..5100c05c 100644 --- a/src/controls/QskSkinManager.cpp +++ b/src/controls/QskSkinManager.cpp @@ -83,6 +83,10 @@ namespace const auto factoryData = pluginData.value( TokenData ).toObject(); m_factoryId = factoryData.value( TokenFactoryId ).toString().toLower(); +#if 1 + if ( m_factoryId == "fluent2factory" ) + return false; // we need to solve a couple of problems first +#endif if ( m_factoryId.isEmpty() ) { // Creating a dummy factory id From 4775045b62c60d8ddf394f981cb6092fa7347972 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 19:16:40 +0200 Subject: [PATCH 08/60] QskAspect::Card introduced --- src/common/QskAspect.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/QskAspect.h b/src/common/QskAspect.h index 0b004215..8503627a 100644 --- a/src/common/QskAspect.h +++ b/src/common/QskAspect.h @@ -35,6 +35,8 @@ class QSK_EXPORT QskAspect Header, Footer, + Card, + Floating }; Q_ENUM( Section ) From 3e00ae4c2aa78baaee386632f227bdb3fa1e1647 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 20 Jun 2023 19:34:48 +0200 Subject: [PATCH 09/60] Padding for tab buttons added ( not covered by M3 specs ) --- skins/material3/QskMaterial3Skin.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index d0113d65..b2c9e1b2 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -985,6 +985,11 @@ void Editor::setupTabButton() using Q = QskTabButton; setStrutSize( Q::Panel, 48_dp, 64_dp ); +#if 1 + // couldn't find a value in the specs + setPadding( Q::Panel, 8, 0, 8, 0 ); +#endif + setGradient( Q::Panel, m_pal.surface ); setColor( Q::Text, m_pal.onSurfaceVariant ); From a12de7a200f72c8751115ff3a11f8d5c29a793cc Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 30 Jun 2023 14:24:31 +0200 Subject: [PATCH 10/60] QskSkinStateChanger::resetStates added --- src/controls/QskSkinStateChanger.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/controls/QskSkinStateChanger.h b/src/controls/QskSkinStateChanger.h index 68c4bb9e..f13d3145 100644 --- a/src/controls/QskSkinStateChanger.h +++ b/src/controls/QskSkinStateChanger.h @@ -16,6 +16,7 @@ class QskSkinStateChanger ~QskSkinStateChanger(); void setStates( QskAspect::States ); + void resetStates(); private: QskSkinnable* m_skinnable; @@ -30,8 +31,7 @@ inline QskSkinStateChanger::QskSkinStateChanger( const QskSkinnable* skinnable ) inline QskSkinStateChanger::~QskSkinStateChanger() { - if ( m_oldStates != m_skinnable->skinStates() ) - m_skinnable->replaceSkinStates( m_oldStates ); + resetStates(); } inline void QskSkinStateChanger::setStates( QskAspect::States states ) @@ -40,4 +40,10 @@ inline void QskSkinStateChanger::setStates( QskAspect::States states ) m_skinnable->replaceSkinStates( states ); } +inline void QskSkinStateChanger::resetStates() +{ + if ( m_oldStates != m_skinnable->skinStates() ) + m_skinnable->replaceSkinStates( m_oldStates ); +} + #endif From a88a1b7a509179df023c604bea868080429bb13a Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 30 Jun 2023 14:25:11 +0200 Subject: [PATCH 11/60] starting state transitions for specific subcontrols supported --- src/controls/QskSkinnable.cpp | 15 +++++++++++++-- src/controls/QskSkinnable.h | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/controls/QskSkinnable.cpp b/src/controls/QskSkinnable.cpp index beb63889..70b238a0 100644 --- a/src/controls/QskSkinnable.cpp +++ b/src/controls/QskSkinnable.cpp @@ -1382,7 +1382,19 @@ void QskSkinnable::setSkinStates( QskAspect::States newStates ) bool QskSkinnable::startHintTransitions( QskAspect::States oldStates, QskAspect::States newStates, int index ) { - if ( !isTransitionAccepted( QskAspect() ) ) + QVector< QskAspect::Subcontrol > subControls; + + if ( const auto control = qskControlCast( owningItem() ) ) + subControls = control->subControls(); + + return startHintTransitions( subControls, oldStates, newStates, index ); +} + +bool QskSkinnable::startHintTransitions( + const QVector< QskAspect::Subcontrol >& subControls, + QskAspect::States oldStates, QskAspect::States newStates, int index ) +{ + if ( !isTransitionAccepted( QskAspect() ) || subControls.isEmpty() ) { // the control does not like any animated transition at the moment return false; @@ -1401,7 +1413,6 @@ bool QskSkinnable::startHintTransitions( const auto primitiveCount = QskAspect::primitiveCount(); - const auto subControls = control->subControls(); for ( const auto subControl : subControls ) { aspect.setSubcontrol( subControl ); diff --git a/src/controls/QskSkinnable.h b/src/controls/QskSkinnable.h index 91c860b9..d8e455a2 100644 --- a/src/controls/QskSkinnable.h +++ b/src/controls/QskSkinnable.h @@ -260,6 +260,8 @@ class QSK_EXPORT QskSkinnable const QskSkinHintTable& hintTable() const; bool startHintTransitions( QskAspect::States, QskAspect::States, int index = -1 ); + bool startHintTransitions( const QVector< QskAspect::Subcontrol >&, + QskAspect::States, QskAspect::States, int index = -1 ); protected: virtual void updateNode( QSGNode* ); From 3d7afa533a8489fe96953820d9c06b2d4dcc4ca7 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 30 Jun 2023 14:38:48 +0200 Subject: [PATCH 12/60] alternating row colors as skin hint --- skins/squiek/QskSquiekSkin.cpp | 2 ++ src/controls/QskListView.cpp | 26 +++++++++++++++++--------- src/controls/QskListView.h | 8 ++++++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index dc006a89..1f99d354 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -1056,6 +1056,8 @@ void Editor::setupListView() setColor( Q::Cell | Q::Selected, m_pal.highlighted ); setColor( Q::Text | Q::Selected, m_pal.highlightedText ); + + setFlag( Q::Cell | QskAspect::Style, true ); // alternating colors } void Editor::setupSubWindow() diff --git a/src/controls/QskListView.cpp b/src/controls/QskListView.cpp index 0d6a0723..478b3716 100644 --- a/src/controls/QskListView.cpp +++ b/src/controls/QskListView.cpp @@ -23,14 +23,12 @@ class QskListView::PrivateData public: PrivateData() : preferredWidthFromColumns( false ) - , alternatingRowColors( false ) , selectionMode( QskListView::SingleSelection ) , selectedRow( -1 ) { } bool preferredWidthFromColumns : 1; - bool alternatingRowColors : 1; SelectionMode selectionMode : 4; int selectedRow; @@ -64,18 +62,19 @@ bool QskListView::preferredWidthFromColumns() const void QskListView::setAlternatingRowColors( bool on ) { - if ( on != m_data->alternatingRowColors ) - { - m_data->alternatingRowColors = on; - update(); - + if ( setFlagHint( Cell | QskAspect::Style, on ) ) Q_EMIT alternatingRowColorsChanged(); - } } bool QskListView::alternatingRowColors() const { - return m_data->alternatingRowColors; + return flagHint< bool >( Cell | QskAspect::Style, false ); +} + +void QskListView::resetAlternatingRowColors() +{ + if ( resetSkinHint( Cell | QskAspect::Style ) ) + Q_EMIT alternatingRowColorsChanged(); } void QskListView::setTextOptions( const QskTextOptions& textOptions ) @@ -92,6 +91,15 @@ QskTextOptions QskListView::textOptions() const return textOptionsHint( Text ); } +void QskListView::resetTextOptions() +{ + if ( resetTextOptionsHint( Text ) ) + { + updateScrollableSize(); + Q_EMIT textOptionsChanged(); + } +} + void QskListView::setSelectedRow( int row ) { if ( row < 0 ) diff --git a/src/controls/QskListView.h b/src/controls/QskListView.h index 6f9f01b7..169d31cc 100644 --- a/src/controls/QskListView.h +++ b/src/controls/QskListView.h @@ -14,7 +14,8 @@ class QSK_EXPORT QskListView : public QskScrollView Q_OBJECT Q_PROPERTY( bool alternatingRowColors READ alternatingRowColors - WRITE setAlternatingRowColors NOTIFY alternatingRowColorsChanged FINAL ) + WRITE setAlternatingRowColors RESET resetAlternatingRowColors + NOTIFY alternatingRowColorsChanged FINAL ) Q_PROPERTY( SelectionMode selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged FINAL ) @@ -23,7 +24,8 @@ class QSK_EXPORT QskListView : public QskScrollView WRITE setSelectedRow NOTIFY selectedRowChanged FINAL ) Q_PROPERTY( QskTextOptions textOptions READ textOptions - WRITE setTextOptions NOTIFY textOptionsChanged FINAL ) + WRITE setTextOptions RESET resetTextOptions + NOTIFY textOptionsChanged FINAL ) Q_PROPERTY( bool preferredWidthFromColumns READ preferredWidthFromColumns WRITE setPreferredWidthFromColumns NOTIFY preferredWidthFromColumnsChanged() ) @@ -49,12 +51,14 @@ class QSK_EXPORT QskListView : public QskScrollView bool preferredWidthFromColumns() const; void setAlternatingRowColors( bool ); + void resetAlternatingRowColors(); bool alternatingRowColors() const; void setSelectionMode( SelectionMode ); SelectionMode selectionMode() const; void setTextOptions( const QskTextOptions& textOptions ); + void resetTextOptions(); QskTextOptions textOptions() const; Q_INVOKABLE int selectedRow() const; From 4a92bc7c12bfca614b132143efd97d1c897090ff Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 30 Jun 2023 14:40:19 +0200 Subject: [PATCH 13/60] listbox example moved into the gallery --- examples/CMakeLists.txt | 1 - examples/gallery/CMakeLists.txt | 1 + examples/gallery/listbox/ListBoxPage.cpp | 60 ++++++++++++++++++ examples/gallery/listbox/ListBoxPage.h | 14 +++++ examples/gallery/main.cpp | 2 + examples/listbox/CMakeLists.txt | 6 -- examples/listbox/main.cpp | 77 ------------------------ 7 files changed, 77 insertions(+), 84 deletions(-) create mode 100644 examples/gallery/listbox/ListBoxPage.cpp create mode 100644 examples/gallery/listbox/ListBoxPage.h delete mode 100644 examples/listbox/CMakeLists.txt delete mode 100644 examples/listbox/main.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index cd9c7b8f..5a00d0a7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -6,7 +6,6 @@ add_subdirectory(desktop) add_subdirectory(gallery) add_subdirectory(layouts) -add_subdirectory(listbox) add_subdirectory(messagebox) add_subdirectory(mycontrols) add_subdirectory(qvgviewer) diff --git a/examples/gallery/CMakeLists.txt b/examples/gallery/CMakeLists.txt index 1608492a..e229a560 100644 --- a/examples/gallery/CMakeLists.txt +++ b/examples/gallery/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES button/ButtonPage.h button/ButtonPage.cpp selector/SelectorPage.h selector/SelectorPage.cpp dialog/DialogPage.h dialog/DialogPage.cpp + listbox/ListBoxPage.h listbox/ListBoxPage.cpp Page.h Page.cpp main.cpp ) diff --git a/examples/gallery/listbox/ListBoxPage.cpp b/examples/gallery/listbox/ListBoxPage.cpp new file mode 100644 index 00000000..e0650d87 --- /dev/null +++ b/examples/gallery/listbox/ListBoxPage.cpp @@ -0,0 +1,60 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "ListBoxPage.h" +#include +#include + +namespace +{ + class ListBox : public QskSimpleListBox + { + public: + ListBox( QQuickItem* parent = nullptr ) + : QskSimpleListBox( parent ) + { + setMargins( QMarginsF( 15, 10, 10, 10 ) ); + + // increasing the padding of each row: usually the job of the skin ! + setPaddingHint( Cell, QMargins( 10, 20, 10, 20 ) ); + + populate(); + + setSelectedRow( 5 ); + } + + private: + void populate() + { + const int count = 10000; + + const QString format( "Row %1: The quick brown fox jumps over the lazy dog" ); + + QStringList entries; + entries.reserve( count ); + + for ( int i = 0; i < count; i++ ) + { + entries += format.arg( i + 1 ); + } + + // we know, that the last entry is the longest one and + // can prevent the list box from having to find it out + // the expensive way. + + const qreal maxWidth = qskHorizontalAdvance( effectiveFont( Cell ), entries.last() ); + setColumnWidthHint( 0, maxWidth ); + + append( entries ); + } + }; +} + +ListBoxPage::ListBoxPage( QQuickItem* parent ) + : Page( Qt::Horizontal, parent ) +{ + setMargins( 5 ); + (void) new ListBox( this ); +} diff --git a/examples/gallery/listbox/ListBoxPage.h b/examples/gallery/listbox/ListBoxPage.h new file mode 100644 index 00000000..0fc44927 --- /dev/null +++ b/examples/gallery/listbox/ListBoxPage.h @@ -0,0 +1,14 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2016 Uwe Rathmann + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#pragma once + +#include "Page.h" + +class ListBoxPage : public Page +{ + public: + ListBoxPage( QQuickItem* = nullptr ); +}; diff --git a/examples/gallery/main.cpp b/examples/gallery/main.cpp index 6d09297a..42e8b280 100644 --- a/examples/gallery/main.cpp +++ b/examples/gallery/main.cpp @@ -10,6 +10,7 @@ #include "button/ButtonPage.h" #include "selector/SelectorPage.h" #include "dialog/DialogPage.h" +#include "listbox/ListBoxPage.h" #include #include @@ -250,6 +251,7 @@ namespace tabView->addPage( "Progress\nBars", new ProgressBarPage() ); tabView->addPage( "Selectors", new SelectorPage() ); tabView->addPage( "Dialogs", new DialogPage() ); + tabView->addPage( "ListBox", new ListBoxPage() ); connect( header, &Header::enabledToggled, tabView, &TabView::setPagesEnabled ); diff --git a/examples/listbox/CMakeLists.txt b/examples/listbox/CMakeLists.txt deleted file mode 100644 index b0064b70..00000000 --- a/examples/listbox/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -############################################################################ -# QSkinny - Copyright (C) 2016 Uwe Rathmann -# SPDX-License-Identifier: BSD-3-Clause -############################################################################ - -qsk_add_example(listbox main.cpp) diff --git a/examples/listbox/main.cpp b/examples/listbox/main.cpp deleted file mode 100644 index 8f67688c..00000000 --- a/examples/listbox/main.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include - -#include -#include -#include -#include -#include - -#include -#include - -class ListBox : public QskSimpleListBox -{ - public: - ListBox() - { - setMargins( QMarginsF( 15, 10, 10, 10 ) ); - setAlternatingRowColors( true ); - - // increasing the padding of each row: usually the job of the skin ! - setPaddingHint( Cell, QMargins( 10, 20, 10, 20 ) ); - - populate(); - - setSelectedRow( 5 ); - } - - private: - void populate() - { - const int count = 10000; - - const QString format( "Row %1: The quick brown fox jumps over the lazy dog" ); - - QStringList entries; - entries.reserve( count ); - - for ( int i = 0; i < count; i++ ) - { - entries += format.arg( i + 1 ); - } - - // we know, that the last entry is the longest one and - // can prevent the list box from having to find it out - // the expensive way. - - const qreal maxWidth = qskHorizontalAdvance( effectiveFont( Cell ), entries.last() ); - setColumnWidthHint( 0, maxWidth ); - - append( entries ); - } -}; - -int main( int argc, char* argv[] ) -{ -#ifdef ITEM_STATISTICS - QskObjectCounter counter( true ); -#endif - - QGuiApplication app( argc, argv ); - - SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts ); - - QskWindow window; - window.setColor( "Silver" ); - - window.addItem( new ListBox() ); - window.resize( 400, 600 ); - window.show(); - - return app.exec(); -} From 1634335a49b4caf2651ed24d0f2132fb1b83dd26 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 30 Jun 2023 14:44:31 +0200 Subject: [PATCH 14/60] using QskBoxNode for the cell background --- src/controls/QskListViewSkinlet.cpp | 56 ++++++++++------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/src/controls/QskListViewSkinlet.cpp b/src/controls/QskListViewSkinlet.cpp index adcae1b7..0a26ccf4 100644 --- a/src/controls/QskListViewSkinlet.cpp +++ b/src/controls/QskListViewSkinlet.cpp @@ -13,7 +13,6 @@ #include #include -#include #include class QskListViewNode final : public QSGTransformNode @@ -113,10 +112,12 @@ QSGNode* QskListViewSkinlet::updateContentsNode( void QskListViewSkinlet::updateBackgroundNodes( const QskListView* listView, QskListViewNode* listViewNode ) const { + using Q = QskListView; + QSGNode* backgroundNode = listViewNode->backgroundNode(); const qreal cellHeight = listView->rowHeight(); - const QRectF viewRect = listView->viewContentsRect(); + const auto viewRect = listView->viewContentsRect(); const QPointF scrolledPos = listView->scrollPos(); const int rowMin = qFloor( scrolledPos.y() / cellHeight ); @@ -129,32 +130,25 @@ void QskListViewSkinlet::updateBackgroundNodes( const double x0 = viewRect.left() + scrolledPos.x(); const double y0 = viewRect.top(); - auto* rowNode = static_cast< QSGSimpleRectNode* >( backgroundNode->firstChild() ); + auto rowNode = backgroundNode->firstChild(); if ( listView->alternatingRowColors() ) { -#if 1 - /* - Cell might be better for regular cells, while ( Cell | AlternateColor ) - could be used for the alternate color TODO ... - */ -#endif - const auto color = listView->color( QskListView::Cell ); - for ( int row = rowMin; row <= rowMax; row++ ) { if ( row % 2 ) { - if ( rowNode == nullptr ) + const QRectF rect( x0, y0 + row * cellHeight, + viewRect.width(), cellHeight ); + + auto newNode = updateBoxNode( listView, rowNode, rect, Q::Cell ); + if ( newNode ) { - rowNode = new QSGSimpleRectNode(); - backgroundNode->appendChildNode( rowNode ); + if ( newNode->parent() != backgroundNode ) + backgroundNode->appendChildNode( newNode ); + else + rowNode = newNode->nextSibling(); } - - rowNode->setRect( x0, y0 + row * cellHeight, viewRect.width(), cellHeight ); - rowNode->setColor( color ); - - rowNode = static_cast< QSGSimpleRectNode* >( rowNode->nextSibling() ); } } } @@ -164,27 +158,15 @@ void QskListViewSkinlet::updateBackgroundNodes( QskSkinStateChanger stateChanger( listView ); stateChanger.setStates( listView->skinStates() | QskListView::Selected ); - const QColor color = listView->color( QskListView::Cell ); - - if ( rowNode == nullptr ) - { - rowNode = new QSGSimpleRectNode(); + const QRectF rect( x0, y0 + rowSelected * cellHeight, + viewRect.width(), cellHeight ); + + rowNode = updateBoxNode( listView, rowNode, rect, Q::Cell ); + if ( rowNode && rowNode->parent() != backgroundNode ) backgroundNode->appendChildNode( rowNode ); - } - - rowNode->setRect( x0, y0 + rowSelected * cellHeight, viewRect.width(), cellHeight ); - rowNode->setColor( color ); - - rowNode = static_cast< QSGSimpleRectNode* >( rowNode->nextSibling() ); } - QSGNode* nextNode = rowNode; - while ( nextNode != nullptr ) - { - QSGNode* tmpNode = nextNode; - nextNode = nextNode->nextSibling(); - delete tmpNode; - } + QskSGNode::removeAllChildNodesAfter( backgroundNode, rowNode ); } void QskListViewSkinlet::updateForegroundNodes( From 9a37a1ef9d8b91d65579b8f60bd2646bfb7f531e Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 30 Jun 2023 14:51:03 +0200 Subject: [PATCH 15/60] Fluent2/Material3 need specific settings for Hovered/Pressed states of scrollbar handles ( vertical/horizontal ) and list box cells. Having 2 * 3 different states is not working properly and we need to do some manual coding to limit the states. This first commit works with Pressed only - Hovered will be added. --- skins/squiek/QskSquiekSkin.cpp | 7 +-- src/controls/QskScrollView.cpp | 69 ++++++++++++++++------- src/controls/QskScrollView.h | 4 +- src/controls/QskScrollViewSkinlet.cpp | 81 +++++++++++++++------------ 4 files changed, 97 insertions(+), 64 deletions(-) diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 1f99d354..18fc6fe6 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -1023,19 +1023,14 @@ void Editor::setupScrollView() const qreal bw = 1.0; setButton( subControl, Raised, bw ); + setButton( subControl | Q::Pressed, Sunken, bw ); const auto extent = 40_dp; if ( subControl == Q::HorizontalScrollHandle ) - { setStrutSize( subControl, extent, 0.0 ); - setButton( subControl | Q::HorizontalHandlePressed, Sunken, bw ); - } else - { setStrutSize( subControl, 0.0, extent ); - setButton( subControl | Q::VerticalHandlePressed, Sunken, bw ); - } setAnimation( subControl | A::Color, qskDuration ); } diff --git a/src/controls/QskScrollView.cpp b/src/controls/QskScrollView.cpp index a61be872..8fd03456 100644 --- a/src/controls/QskScrollView.cpp +++ b/src/controls/QskScrollView.cpp @@ -15,24 +15,47 @@ QSK_SUBCONTROL( QskScrollView, HorizontalScrollHandle ) QSK_SUBCONTROL( QskScrollView, VerticalScrollBar ) QSK_SUBCONTROL( QskScrollView, VerticalScrollHandle ) -QSK_SYSTEM_STATE( QskScrollView, VerticalHandlePressed, QskAspect::FirstSystemState << 1 ) -QSK_SYSTEM_STATE( QskScrollView, HorizontalHandlePressed, QskAspect::FirstSystemState << 2 ) +QSK_SYSTEM_STATE( QskScrollView, Pressed, QskAspect::FirstSystemState << 1 ) class QskScrollView::PrivateData { public: - PrivateData() - : horizontalScrollBarPolicy( Qt::ScrollBarAsNeeded ) - , verticalScrollBarPolicy( Qt::ScrollBarAsNeeded ) - , isScrolling( 0 ) + inline void resetScrolling( QskScrollView* scrollView ) { + setScrolling( scrollView, 0, 0.0 ); } - Qt::ScrollBarPolicy horizontalScrollBarPolicy; - Qt::ScrollBarPolicy verticalScrollBarPolicy; + inline void setScrolling( QskScrollView* scrollView, int scrolling, qreal pos ) + { + if ( isScrolling == scrolling ) + return; + + QskAspect::Subcontrol subControl; + if ( ( isScrolling == Qt::Horizontal ) || ( scrolling == Qt::Horizontal ) ) + subControl = HorizontalScrollHandle; + else + subControl = VerticalScrollHandle; + + this->isScrolling = scrolling; + this->scrollPressPos = pos; + + scrollView->update(); + + auto oldStates = scrollView->skinStates(); + auto newStates = oldStates | QskScrollView::Pressed; + + if ( scrolling == 0 ) + qSwap( oldStates, newStates ); + + scrollView->startHintTransitions( { subControl }, oldStates, newStates ); + + } + + Qt::ScrollBarPolicy horizontalScrollBarPolicy = Qt::ScrollBarAsNeeded; + Qt::ScrollBarPolicy verticalScrollBarPolicy = Qt::ScrollBarAsNeeded; qreal scrollPressPos; - int isScrolling; + int isScrolling = 0; }; QskScrollView::QskScrollView( QQuickItem* parent ) @@ -88,6 +111,15 @@ bool QskScrollView::isScrolling( Qt::Orientation orientation ) const return m_data->isScrolling == orientation; } +QskAspect::States QskScrollView::scrollHandleStates( Qt::Orientation orientation ) const +{ + auto states = skinStates(); + if ( m_data->isScrolling == orientation ) + states |= Pressed; + + return states; +} + QRectF QskScrollView::viewContentsRect() const { // This code should be done in the skinlet. TODO ... @@ -107,10 +139,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event ) if ( handleRect.contains( mousePos ) ) { - m_data->isScrolling = Qt::Vertical; - m_data->scrollPressPos = mousePos.y(); - - setSkinStateFlag( VerticalHandlePressed, true ); + m_data->setScrolling( this, Qt::Vertical, mousePos.y() ); } else { @@ -135,10 +164,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event ) if ( handleRect.contains( mousePos ) ) { - m_data->isScrolling = Qt::Horizontal; - m_data->scrollPressPos = mousePos.x(); - - setSkinStateFlag( HorizontalHandlePressed, true ); + m_data->setScrolling( this, Qt::Horizontal, mousePos.x() ); } else { @@ -200,11 +226,12 @@ void QskScrollView::mouseReleaseEvent( QMouseEvent* event ) return; } - m_data->isScrolling = 0; - m_data->scrollPressPos = 0; + m_data->resetScrolling( this ); +} - setSkinStateFlag( HorizontalHandlePressed, false ); - setSkinStateFlag( VerticalHandlePressed, false ); +void QskScrollView::mouseUngrabEvent() +{ + m_data->resetScrolling( this ); } #ifndef QT_NO_WHEELEVENT diff --git a/src/controls/QskScrollView.h b/src/controls/QskScrollView.h index 15a47a3e..fe0dfa38 100644 --- a/src/controls/QskScrollView.h +++ b/src/controls/QskScrollView.h @@ -25,7 +25,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox HorizontalScrollBar, HorizontalScrollHandle, VerticalScrollBar, VerticalScrollHandle ) - QSK_STATES( VerticalHandlePressed, HorizontalHandlePressed ) + QSK_STATES( Pressed ) QskScrollView( QQuickItem* parent = nullptr ); ~QskScrollView() override; @@ -39,6 +39,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox Qt::Orientations scrollableOrientations() const; bool isScrolling( Qt::Orientation ) const; + QskAspect::States scrollHandleStates( Qt::Orientation ) const; QRectF viewContentsRect() const override; QskAnimationHint flickHint() const override; @@ -51,6 +52,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox void mouseMoveEvent( QMouseEvent* ) override; void mousePressEvent( QMouseEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override; + void mouseUngrabEvent() override; #ifndef QT_NO_WHEELEVENT QPointF scrollOffset( const QWheelEvent* ) const override; diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index a786c6a1..b1f2d7e5 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -9,6 +9,7 @@ #include "QskAspect.h" #include "QskQuick.h" #include "QskSGNode.h" +#include "QskSkinStateChanger.h" #include @@ -51,37 +52,27 @@ QskScrollViewSkinlet::~QskScrollViewSkinlet() = default; QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const { + using Q = QskScrollView; + const auto scrollView = static_cast< const QskScrollView* >( skinnable ); - if ( subControl == QskScrollView::Panel ) - { + if ( subControl == Q::Panel ) return contentsRect; - } - if ( subControl == QskScrollView::Viewport ) - { + if ( subControl == Q::Viewport ) return viewportRect( scrollView, contentsRect ); - } - if ( subControl == QskScrollView::HorizontalScrollBar ) - { + if ( subControl == Q::HorizontalScrollBar ) return scrollBarRect( scrollView, contentsRect, Qt::Horizontal ); - } - if ( subControl == QskScrollView::HorizontalScrollHandle ) - { + if ( subControl == Q::HorizontalScrollHandle ) return scrollHandleRect( scrollView, contentsRect, Qt::Horizontal ); - } - if ( subControl == QskScrollView::VerticalScrollBar ) - { + if ( subControl == Q::VerticalScrollBar ) return scrollBarRect( scrollView, contentsRect, Qt::Vertical ); - } - if ( subControl == QskScrollView::VerticalScrollHandle ) - { + if ( subControl == Q::VerticalScrollHandle ) return scrollHandleRect( scrollView, contentsRect, Qt::Vertical ); - } return Inherited::subControlRect( skinnable, contentsRect, subControl ); } @@ -89,27 +80,41 @@ QRectF QskScrollViewSkinlet::subControlRect( const QskSkinnable* skinnable, QSGNode* QskScrollViewSkinlet::updateSubNode( const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const { + using Q = QskScrollView; + const auto scrollView = static_cast< const QskScrollView* >( skinnable ); switch ( nodeRole ) { case PanelRole: { - return updateBoxNode( skinnable, node, QskScrollView::Panel ); + return updateBoxNode( skinnable, node, Q::Panel ); } case ViewportRole: { - return updateBoxNode( skinnable, node, QskScrollView::Viewport ); + return updateBoxNode( skinnable, node, Q::Viewport ); } case HorizontalScrollHandleRole: { - return updateBoxNode( skinnable, node, QskScrollView::HorizontalScrollHandle ); + const auto rect = subControlRect( skinnable, + scrollView->contentsRect(), Q::HorizontalScrollHandle ); + + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( Qt::Horizontal ) ); + + return updateBoxNode( skinnable, node, rect, Q::HorizontalScrollHandle ); } case VerticalScrollHandleRole: { - return updateBoxNode( skinnable, node, QskScrollView::VerticalScrollHandle ); + const auto rect = subControlRect( skinnable, + scrollView->contentsRect(), Q::VerticalScrollHandle ); + + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( Qt::Vertical ) ); + + return updateBoxNode( skinnable, node, rect, Q::VerticalScrollHandle ); } case ContentsRootRole: @@ -236,22 +241,23 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, const auto vRect = subControlRect( scrollView, contentsRect, QskScrollView::Viewport ); + const auto scrollableSize = scrollView->scrollableSize(); + QRectF handleRect; if ( orientation == Qt::Vertical ) { - const auto subControlBar = Q::VerticalScrollBar; + const auto sbRect = subControlRect( scrollView, contentsRect, Q::VerticalScrollBar ); - const auto sbRect = subControlRect( scrollView, contentsRect, subControlBar ); - const auto padding = scrollView->paddingHint( subControlBar ); - - const qreal h = scrollView->scrollableSize().height(); - - const qreal y1 = pos.y() / h; - const qreal y2 = ( pos.y() + vRect.height() ) / h; + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + const auto padding = scrollView->paddingHint( Q::VerticalScrollBar ); const auto strut = scrollView->strutSizeHint( Q::VerticalScrollHandle ); + const qreal y1 = pos.y() / scrollableSize.height(); + const qreal y2 = ( pos.y() + vRect.height() ) / scrollableSize.height(); + qreal top, bottom; qskAlignedHandle( y1, y2, sbRect.height(), strut.height(), top, bottom ); @@ -262,15 +268,15 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, } else { - const auto subControlBar = Q::HorizontalScrollBar; + const auto sbRect = subControlRect( scrollView, contentsRect, Q::HorizontalScrollBar ); - const auto sbRect = subControlRect( scrollView, contentsRect, subControlBar ); - const auto padding = scrollView->paddingHint( subControlBar ); + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); - const qreal w = scrollView->scrollableSize().width(); + const auto padding = scrollView->paddingHint( Q::HorizontalScrollBar ); - const qreal x1 = pos.x() / w; - const qreal x2 = ( pos.x() + vRect.width() ) / w; + const qreal x1 = pos.x() / scrollableSize.width(); + const qreal x2 = ( pos.x() + vRect.width() ) / scrollableSize.width(); const auto strut = scrollView->strutSizeHint( Q::HorizontalScrollHandle ); @@ -298,6 +304,9 @@ QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView, auto r = subControlRect( scrollView, contentsRect, Q::Panel ); + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + if ( orientation == Qt::Horizontal ) { const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size ); From b84593a6f4cfb058867cc1fed943d04720bb5290 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 27 Jun 2023 15:13:48 +0200 Subject: [PATCH 16/60] Skins: Order skins depending on system color scheme Resolves #320 --- skins/fluent2/metadata.json | 3 ++- skins/material3/metadata.json | 3 ++- skins/squiek/metadata.json | 2 +- src/controls/QskSkinManager.cpp | 45 ++++++++++++++++++++++++++++++--- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/skins/fluent2/metadata.json b/skins/fluent2/metadata.json index 9111091b..6eb6982c 100644 --- a/skins/fluent2/metadata.json +++ b/skins/fluent2/metadata.json @@ -1,4 +1,5 @@ { "FactoryId": "Fluent2Factory", - "Skins": [ "Fluent2 Light", "Fluent2 Dark" ] + "Skins": [ { "Name": "Fluent2 Light", "Scheme": "Light" }, + { "Name": "Fluent2 Dark", "Scheme": "Dark" } ] } diff --git a/skins/material3/metadata.json b/skins/material3/metadata.json index f4483d53..ef789842 100644 --- a/skins/material3/metadata.json +++ b/skins/material3/metadata.json @@ -1,4 +1,5 @@ { "FactoryId": "Material3Factory", - "Skins": [ "Material3 Light", "Material3 Dark" ] + "Skins": [ { "Name": "Material3 Light", "Scheme": "Light" }, + { "Name": "Material3 Dark", "Scheme": "Dark" } ] } diff --git a/skins/squiek/metadata.json b/skins/squiek/metadata.json index 1616d679..94786db2 100644 --- a/skins/squiek/metadata.json +++ b/skins/squiek/metadata.json @@ -1,4 +1,4 @@ { "FactoryId": "SquiekFactory", - "Skins": [ "Squiek" ] + "Skins": [ { "Name": "Squiek", "Scheme": "Unknown" } ] } diff --git a/src/controls/QskSkinManager.cpp b/src/controls/QskSkinManager.cpp index 5100c05c..45725cd3 100644 --- a/src/controls/QskSkinManager.cpp +++ b/src/controls/QskSkinManager.cpp @@ -8,12 +8,14 @@ #include #include +#include #include #include #include #include #include #include +#include static inline QStringList qskSplitPath( const QString& s ) { @@ -74,6 +76,8 @@ namespace const QLatin1String TokenData( "MetaData" ); const QLatin1String TokenFactoryId( "FactoryId" ); const QLatin1String TokenSkins( "Skins" ); + const QLatin1String TokenName( "Name" ); + const QLatin1String TokenScheme( "Scheme" ); const QLatin1String InterfaceId( QskSkinFactoryIID ); @@ -94,10 +98,45 @@ namespace m_factoryId = QStringLiteral( "skin_factory_" ) + QString::number( i++ ); } - const auto skinNames = factoryData.value( TokenSkins ).toArray(); + const auto skins = factoryData.value( TokenSkins ).toArray(); - for ( const auto& name : skinNames ) - m_skinNames += name.toString(); + for ( const auto& skin : skins ) + { + const auto& skinObject = skin.toObject(); + const auto& name = skinObject.value( TokenName ).toString(); + +#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 ) + const auto& schemeString = skinObject.value( TokenScheme ).toString(); + Qt::ColorScheme scheme; + + if( schemeString == QStringLiteral( "Light" ) ) + { + scheme = Qt::ColorScheme::Light; + } + else if( schemeString == QStringLiteral( "Dark" ) ) + { + scheme = Qt::ColorScheme::Dark; + } + else + { + scheme = Qt::ColorScheme::Unknown; + } + + const auto systemScheme = qGuiApp->styleHints()->colorScheme(); + + if( scheme == systemScheme ) + { + m_skinNames.prepend( name ); + } + else + { + m_skinNames.append( name ); + } +#else + Q_UNUSED( TokenScheme ) + m_skinNames += name; +#endif + } } return !m_skinNames.isEmpty(); From 98158b2a4b1988e44340aed8a0d9746c2954b01d Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 27 Jun 2023 15:15:27 +0200 Subject: [PATCH 17/60] Skins: Unify lightness enum --- skins/fluent2/QskFluent2Skin.cpp | 10 +++++----- skins/fluent2/QskFluent2Skin.h | 10 ++-------- skins/fluent2/QskFluent2SkinFactory.cpp | 4 ++-- skins/material3/QskMaterial3Skin.cpp | 11 ++++++----- skins/material3/QskMaterial3Skin.h | 10 ++-------- skins/material3/QskMaterial3SkinFactory.cpp | 4 ++-- src/controls/QskSkin.h | 10 ++++++++++ 7 files changed, 29 insertions(+), 30 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index cb960022..f589e83a 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -946,8 +946,8 @@ void Editor::setupVirtualKeyboard() setPadding( Q::Panel, 8 ); } -QskFluent2Theme::QskFluent2Theme( Theme lightness ) - : QskFluent2Theme( lightness, +QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme ) + : QskFluent2Theme( colorScheme, { // default Fluent accent colors: 0xff98ecfe, 0xff60ccfe, @@ -960,10 +960,10 @@ QskFluent2Theme::QskFluent2Theme( Theme lightness ) { } -QskFluent2Theme::QskFluent2Theme( Theme theme, +QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, const std::array< QRgb, NumAccentColors >& accentColors ) { - if( theme == Light ) + if( colorScheme == QskSkin::Light ) { // Fill color: @@ -1065,7 +1065,7 @@ QskFluent2Theme::QskFluent2Theme( Theme theme, // ### should actually be drawn twice with different values: shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) }; } - else if( theme == Dark ) + else if( colorScheme == QskSkin::Dark ) { // Fill color: diff --git a/skins/fluent2/QskFluent2Skin.h b/skins/fluent2/QskFluent2Skin.h index 034f0751..826eee34 100644 --- a/skins/fluent2/QskFluent2Skin.h +++ b/skins/fluent2/QskFluent2Skin.h @@ -18,12 +18,6 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme { public: - enum Theme - { - Light, - Dark - }; - enum AccentColors { AccentLight3, @@ -37,8 +31,8 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme NumAccentColors }; - QskFluent2Theme( Theme ); - QskFluent2Theme( Theme, const std::array< QRgb, NumAccentColors >& ); + QskFluent2Theme( QskSkin::ColorScheme ); + QskFluent2Theme( QskSkin::ColorScheme, const std::array< QRgb, NumAccentColors >& ); typedef std::array< QRgb, 2 > BorderGradient; diff --git a/skins/fluent2/QskFluent2SkinFactory.cpp b/skins/fluent2/QskFluent2SkinFactory.cpp index 99cfaf55..4d015c4b 100644 --- a/skins/fluent2/QskFluent2SkinFactory.cpp +++ b/skins/fluent2/QskFluent2SkinFactory.cpp @@ -27,12 +27,12 @@ QskSkin* QskFluent2SkinFactory::createSkin( const QString& skinName ) { if ( QString::compare( skinName, fluent2LightSkinName, Qt::CaseInsensitive ) == 0 ) { - QskFluent2Theme theme( QskFluent2Theme::Light ); + QskFluent2Theme theme( QskSkin::Light ); return new QskFluent2Skin( theme ); } else if ( QString::compare( skinName, fluent2DarkSkinName, Qt::CaseInsensitive ) == 0 ) { - QskFluent2Theme theme( QskFluent2Theme::Dark ); + QskFluent2Theme theme( QskSkin::Dark ); return new QskFluent2Skin( theme ); } diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index b2c9e1b2..8f456dcf 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -54,6 +54,7 @@ #include #include +#include static const int qskDuration = 150; @@ -1192,8 +1193,8 @@ void Editor::setupSubWindow() } -QskMaterial3Theme::QskMaterial3Theme( Lightness lightness ) - : QskMaterial3Theme( lightness, +QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme ) + : QskMaterial3Theme( colorScheme, { // default Material colors: 0xff6750A4, 0xff625B71, @@ -1205,11 +1206,11 @@ QskMaterial3Theme::QskMaterial3Theme( Lightness lightness ) { } -QskMaterial3Theme::QskMaterial3Theme( Lightness lightness, +QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme, std::array< QskHctColor, NumPaletteTypes > palettes ) : m_palettes( palettes ) { - if ( lightness == Light ) + if ( colorScheme == QskSkin::Light ) { primary = m_palettes[ Primary ].toned( 40 ).rgb(); onPrimary = m_palettes[ Primary ].toned( 100 ).rgb(); @@ -1243,7 +1244,7 @@ QskMaterial3Theme::QskMaterial3Theme( Lightness lightness, shadow = m_palettes[ Neutral ].toned( 0 ).rgb(); } - else if ( lightness == Dark ) + else if ( colorScheme == QskSkin::Dark ) { primary = m_palettes[ Primary ].toned( 80 ).rgb(); onPrimary = m_palettes[ Primary ].toned( 20 ).rgb(); diff --git a/skins/material3/QskMaterial3Skin.h b/skins/material3/QskMaterial3Skin.h index f6fda892..ce36e9bd 100644 --- a/skins/material3/QskMaterial3Skin.h +++ b/skins/material3/QskMaterial3Skin.h @@ -18,12 +18,6 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme { public: - enum Lightness - { - Light, - Dark - }; - enum PaletteType { Primary, @@ -36,8 +30,8 @@ class QSK_MATERIAL3_EXPORT QskMaterial3Theme NumPaletteTypes }; - QskMaterial3Theme( Lightness ); - QskMaterial3Theme( Lightness, std::array< QskHctColor, NumPaletteTypes > ); + QskMaterial3Theme( QskSkin::ColorScheme ); + QskMaterial3Theme( QskSkin::ColorScheme, std::array< QskHctColor, NumPaletteTypes > ); QRgb primary; QRgb primary8; // ### rename to primaryHovered or so? diff --git a/skins/material3/QskMaterial3SkinFactory.cpp b/skins/material3/QskMaterial3SkinFactory.cpp index cb08a5c6..f65f669c 100644 --- a/skins/material3/QskMaterial3SkinFactory.cpp +++ b/skins/material3/QskMaterial3SkinFactory.cpp @@ -27,12 +27,12 @@ QskSkin* QskMaterial3SkinFactory::createSkin( const QString& skinName ) { if ( QString::compare( skinName, materialLightSkinName, Qt::CaseInsensitive ) == 0 ) { - QskMaterial3Theme theme( QskMaterial3Theme::Light ); + QskMaterial3Theme theme( QskSkin::Light ); return new QskMaterial3Skin( theme ); } else if ( QString::compare( skinName, materialDarkSkinName, Qt::CaseInsensitive ) == 0 ) { - QskMaterial3Theme theme( QskMaterial3Theme::Dark ); + QskMaterial3Theme theme( QskSkin::Dark ); return new QskMaterial3Skin( theme ); } diff --git a/src/controls/QskSkin.h b/src/controls/QskSkin.h index 982ed2a3..b02facbb 100644 --- a/src/controls/QskSkin.h +++ b/src/controls/QskSkin.h @@ -46,6 +46,16 @@ class QSK_EXPORT QskSkin : public QObject Q_ENUM( SkinFontRole ) +#if 1 + // Use Qt::ColorScheme once minimum version is Qt 6.5 + enum ColorScheme + { + Unknown, + Light, + Dark + }; +#endif + QskSkin( QObject* parent = nullptr ); ~QskSkin() override; From 620fff1206c9642d3b4ed03082954aac060e4c62 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 2 Jul 2023 12:18:47 +0200 Subject: [PATCH 18/60] code moved to QskFluent2Theme.[h|cpp] --- skins/fluent2/CMakeLists.txt | 4 +- skins/fluent2/QskFluent2Global.h | 2 +- skins/fluent2/QskFluent2Skin.cpp | 268 +++--------------------- skins/fluent2/QskFluent2Skin.h | 225 +------------------- skins/fluent2/QskFluent2SkinFactory.cpp | 1 + skins/fluent2/QskFluent2SkinFactory.h | 2 +- skins/fluent2/QskFluent2Theme.cpp | 240 +++++++++++++++++++++ skins/fluent2/QskFluent2Theme.h | 232 ++++++++++++++++++++ 8 files changed, 505 insertions(+), 469 deletions(-) create mode 100644 skins/fluent2/QskFluent2Theme.cpp create mode 100644 skins/fluent2/QskFluent2Theme.h diff --git a/skins/fluent2/CMakeLists.txt b/skins/fluent2/CMakeLists.txt index 8ae6de16..2441647f 100644 --- a/skins/fluent2/CMakeLists.txt +++ b/skins/fluent2/CMakeLists.txt @@ -4,7 +4,9 @@ ############################################################################ set(SOURCES - QskFluent2Global.h QskFluent2Skin.h QskFluent2Skin.cpp + QskFluent2Global.h + QskFluent2Theme.h QskFluent2Theme.cpp + QskFluent2Skin.h QskFluent2Skin.cpp QskFluent2SkinFactory.h QskFluent2SkinFactory.cpp ) qt_add_resources(SOURCES icons.qrc) diff --git a/skins/fluent2/QskFluent2Global.h b/skins/fluent2/QskFluent2Global.h index 5c8a1aec..0a58068e 100644 --- a/skins/fluent2/QskFluent2Global.h +++ b/skins/fluent2/QskFluent2Global.h @@ -6,7 +6,7 @@ #ifndef QSK_FLUENT2_GLOBAL_H #define QSK_FLUENT2_GLOBAL_H -#include "QskGlobal.h" +#include #ifdef QSK_DLL diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index f589e83a..18559b93 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -3,20 +3,20 @@ * SPDX-License-Identifier: BSD-3-Clause *****************************************************************************/ +/* + Definitions ( where possible ) taken from + https://www.figma.com/file/NAWMapFlXnoOb86Q2H5GKr/Windows-UI-(Community) + */ #include "QskFluent2Skin.h" +#include "QskFluent2Theme.h" #include #include #include #include -#include #include #include -#include -#include -#include -#include #include #include #include @@ -45,6 +45,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -56,6 +60,20 @@ namespace { + inline QFont createFont( const QString& name, qreal lineHeight, + qreal size, qreal tracking, QFont::Weight weight ) + { + QFont font( name, qRound( size ) ); + font.setPixelSize( qRound( lineHeight ) ); + + if( !qskFuzzyCompare( tracking, 0.0 ) ) + font.setLetterSpacing( QFont::AbsoluteSpacing, tracking ); + + font.setWeight( weight ); + + return font; + } + inline constexpr QRgb rgbGray( int value, qreal opacity = 1.0 ) { return qRgba( value, value, value, qRound( opacity * 255 ) ); @@ -124,20 +142,6 @@ namespace const QskFluent2Theme& theme; }; - - QFont createFont( const QString& name, qreal lineHeight, - qreal size, qreal tracking, QFont::Weight weight ) - { - QFont font( name, qRound( size ) ); - font.setPixelSize( qRound( lineHeight ) ); - - if( !qskFuzzyCompare( tracking, 0.0 ) ) - font.setLetterSpacing( QFont::AbsoluteSpacing, tracking ); - - font.setWeight( weight ); - - return font; - } } void Editor::setup() @@ -694,6 +698,7 @@ void Editor::setupSpinBox() setStrutSize( Q::UpPanel, 32, 20 ); setPadding( Q::UpPanel, { 11, 7, 11, 7 } ); + setStrutSize( Q::DownPanel, 34, 20 ); setPadding( Q::DownPanel, { 11, 7, 13, 7 } ); @@ -946,231 +951,6 @@ void Editor::setupVirtualKeyboard() setPadding( Q::Panel, 8 ); } -QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme ) - : QskFluent2Theme( colorScheme, - { // default Fluent accent colors: - 0xff98ecfe, - 0xff60ccfe, - 0xff0093f9, - 0xff0078d4, - 0xff005eb7, - 0xff003d92, - 0xff001968 - } ) -{ -} - -QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, - const std::array< QRgb, NumAccentColors >& accentColors ) -{ - if( colorScheme == QskSkin::Light ) - { - // Fill color: - - palette.fillColor.text.primary = rgbGray( 0, 0.8956 ); - palette.fillColor.text.secondary = rgbGray( 0, 0.6063 ); - palette.fillColor.text.tertiary = rgbGray( 0, 0.4458 ); - palette.fillColor.text.disabled = rgbGray( 0, 0.3614 ); - - palette.fillColor.accentText.primary = accentColors[ AccentDark2 ]; - palette.fillColor.accentText.secondary = accentColors[ AccentDark3 ]; - palette.fillColor.accentText.tertiary = accentColors[ AccentDark1 ]; - palette.fillColor.accentText.disabled = rgbGray( 0, 0.3614 ); - - palette.fillColor.textOnAccent.primary = rgbGray( 255 ); - palette.fillColor.textOnAccent.secondary = rgbGray( 255, 0.70 ); - palette.fillColor.textOnAccent.disabled = rgbGray( 255 ); - palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); - - palette.fillColor.control.defaultColor = rgbGray( 255, 0.70 ); - palette.fillColor.control.secondary = rgbGray( 249, 0.50 ); - palette.fillColor.control.tertiary = rgbGray( 249, 0.30 ); - palette.fillColor.control.inputActive = rgbGray( 255 ); - palette.fillColor.control.disabled = rgbGray( 249, 0.30 ); - - palette.fillColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); - palette.fillColor.controlStrong.disabled = rgbGray( 0, 0.3173 ); - - palette.fillColor.subtle.secondary = rgbGray( 0, 0.0373 ); - palette.fillColor.subtle.tertiary = rgbGray( 0, 0.0241 ); - palette.fillColor.subtle.disabled = Qt::transparent; - - palette.fillColor.controlSolid.defaultColor = rgbGray( 255 ); - - palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.0241 ); - palette.fillColor.controlAlt.tertiary = rgbGray( 0, 0.0578 ); - palette.fillColor.controlAlt.quaternary = rgbGray( 0, 0.0924 ); - palette.fillColor.controlAlt.disabled = Qt::transparent; - - palette.fillColor.accent.defaultColor = accentColors[ AccentDark1 ]; - palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.90 ); - palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.80 ); - palette.fillColor.accent.disabled = rgbGray( 0, 0.2169 ); - palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; - - // Elevation: - - palette.elevation.control.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; - palette.elevation.circle.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; - palette.elevation.textControl.border = { rgbGray( 0, 0.0578 ), palette.fillColor.text.secondary }; - palette.elevation.textControl.borderFocused = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.0578 ) }; - palette.elevation.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.40 ) }; - - // Stroke color: - - palette.strokeColor.control.defaultColor = rgbGray( 0, 0.0578 ); - palette.strokeColor.control.secondary = rgbGray( 0, 0.1622 ); - palette.strokeColor.control.onAccentDefault = rgbGray( 255.08 ); - palette.strokeColor.control.onAccentSecondary = rgbGray( 0, 0.40 ); - palette.strokeColor.control.onAccentTertiary = rgbGray( 0, 0.2169 ); - palette.strokeColor.control.onAccentDisabled = rgbGray( 0, 0.0578 ); - - palette.strokeColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); - palette.strokeColor.controlStrong.disabled = rgbGray( 0, 0.2169 ); - - palette.strokeColor.card.defaultColor = rgbGray( 0, 0.0578 ); - palette.strokeColor.card.defaultSolid = rgbGray( 235 ); - - palette.strokeColor.divider.defaultColor = rgbGray( 0, 0.0803 ); - - palette.strokeColor.surface.defaultColor = rgbGray( 117, 0.40 ); - palette.strokeColor.surface.flyout = rgbGray( 0, 0.0578 ); - - palette.strokeColor.focus.outer = rgbGray( 0, 0.8956 ); - palette.strokeColor.focus.inner = rgbGray( 255 ); - - // Background: - - palette.background.card.defaultColor = rgbGray( 255, 0.70 ); - palette.background.card.secondary = rgbGray( 246, 0.50 ); - palette.background.card.tertiary = rgbGray( 255 ); - - palette.background.overlay.defaultColor = rgbGray( 0, 0.30 ); - - palette.background.layer.alt = rgbGray( 255 ); - - palette.background.flyout.defaultColor = rgbGray( 252, 0.85 ); - - palette.background.solid.base = rgbGray( 243 ); - palette.background.solid.secondary = rgbGray( 238 ); - palette.background.solid.tertiary = rgbGray( 249 ); - palette.background.solid.quaternary = rgbGray( 255 ); - - - // Shadow: - - shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.04 ) }; - shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.10 ) }; - shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.14 ) }; - // ### should actually be drawn twice with different values: - shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) }; - } - else if( colorScheme == QskSkin::Dark ) - { - // Fill color: - - palette.fillColor.text.primary = rgbGray( 255 ); - palette.fillColor.text.secondary = rgbGray( 255, 0.786 ); - palette.fillColor.text.tertiary = rgbGray( 255, 0.5442 ); - palette.fillColor.text.disabled = rgbGray( 255, 0.3628 ); - - palette.fillColor.accentText.primary = accentColors[ AccentLight3 ]; - palette.fillColor.accentText.secondary = accentColors[ AccentLight3 ]; - palette.fillColor.accentText.tertiary = accentColors[ AccentLight2 ]; - palette.fillColor.accentText.disabled = rgbGray( 255, 0.3628 ); - - palette.fillColor.textOnAccent.primary = rgbGray( 0 ); - palette.fillColor.textOnAccent.secondary = rgbGray( 0, 0.50 ); - palette.fillColor.textOnAccent.disabled = rgbGray( 255, 0.5302 ); - palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); - - palette.fillColor.control.defaultColor = rgbGray( 255, 0.0605 ); - palette.fillColor.control.secondary = rgbGray( 255, 0.0837 ); - palette.fillColor.control.tertiary = rgbGray( 255, 0.0326 ); - palette.fillColor.control.inputActive = rgbGray( 30, 0.70 ); - palette.fillColor.control.disabled = rgbGray( 255, 0.0419 ); - - palette.fillColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); - palette.fillColor.controlStrong.disabled = rgbGray( 255, 0.2465 ); - - palette.fillColor.subtle.secondary = rgbGray( 255, 0.0605 ); - palette.fillColor.subtle.tertiary = rgbGray( 255, 0.0419 ); - palette.fillColor.subtle.disabled = Qt::transparent; - - palette.fillColor.controlSolid.defaultColor = rgbGray( 69 ); - - palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.10 ); - palette.fillColor.controlAlt.tertiary = rgbGray( 255, 0.0419 ); - palette.fillColor.controlAlt.quaternary = rgbGray( 255, 0.0698 ); - palette.fillColor.controlAlt.disabled = Qt::transparent; - - palette.fillColor.accent.defaultColor = accentColors[ AccentLight2 ]; - palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentLight2 ], 0.90 ); - palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentLight2 ], 0.80 ); - palette.fillColor.accent.disabled = rgbGray( 255, 0.1581 ); - palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; - - // Elevation: - - palette.elevation.control.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; - palette.elevation.circle.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; - - palette.elevation.textControl.border = { rgbGray( 255, 0.08 ), palette.fillColor.text.secondary }; - - palette.elevation.textControl.borderFocused = { rgbGray( 255, 0.08 ), rgbGray( 255, 0.08 ) }; - palette.elevation.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.14 ) }; - - // Stroke color: - - palette.strokeColor.control.defaultColor = rgbGray( 255, 0.0698 ); - palette.strokeColor.control.secondary = rgbGray( 255, 0.093 ); - palette.strokeColor.control.onAccentDefault = rgbGray( 255, 0.08 ); - palette.strokeColor.control.onAccentSecondary = rgbGray( 0, 0.14 ); - palette.strokeColor.control.onAccentTertiary = rgbGray( 0, 0.2169 ); - palette.strokeColor.control.onAccentDisabled = rgbGray( 0, 0.20 ); - - palette.strokeColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); - palette.strokeColor.controlStrong.disabled = rgbGray( 255, 0.1581 ); - - palette.strokeColor.card.defaultColor = rgbGray( 255, 0.0578 ); - palette.strokeColor.card.defaultSolid = rgbGray( 235 ); - - palette.strokeColor.divider.defaultColor = rgbGray( 255, 0.0837 ); - - palette.strokeColor.surface.defaultColor = rgbGray( 117, 0.40 ); - palette.strokeColor.surface.flyout = rgbGray( 0, 0.20 ); - - palette.strokeColor.focus.outer = rgbGray( 255 ); - palette.strokeColor.focus.inner = rgbGray( 0, 0.70 ); - - // Background: - - palette.background.card.defaultColor = rgbGray( 255, 0.0512 ); - palette.background.card.secondary = rgbGray( 255, 0.0326 ); - palette.background.card.tertiary = rgbGray( 255 ); // not set in Figma - - palette.background.overlay.defaultColor = rgbGray( 0, 0.30 ); - - palette.background.layer.alt = rgbGray( 255, 0.0538 ); - - palette.background.flyout.defaultColor = rgbGray( 44, 0.96 ); - - palette.background.solid.base = rgbGray( 32 ); - palette.background.solid.secondary = rgbGray( 28 ); - palette.background.solid.tertiary = rgbGray( 40 ); - palette.background.solid.quaternary = rgbGray( 44 ); - - - // Shadow: - - shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.13 ) }; - shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.26 ) }; - shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.26 ) }; - // ### should actually be drawn twice with different values: - shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.37 ) }; - } -} - QskFluent2Skin::QskFluent2Skin( const QskFluent2Theme& palette, QObject* parent ) : Inherited( parent ) { diff --git a/skins/fluent2/QskFluent2Skin.h b/skins/fluent2/QskFluent2Skin.h index 826eee34..f731327f 100644 --- a/skins/fluent2/QskFluent2Skin.h +++ b/skins/fluent2/QskFluent2Skin.h @@ -7,228 +7,9 @@ #define QSK_FLUENT2_SKIN_H #include "QskFluent2Global.h" - -#include -#include -#include #include -#include - -class QSK_FLUENT2_EXPORT QskFluent2Theme -{ - public: - enum AccentColors - { - AccentLight3, - AccentLight2, - AccentLight1, - AccentBase, - AccentDark1, - AccentDark2, - AccentDark3, - - NumAccentColors - }; - - QskFluent2Theme( QskSkin::ColorScheme ); - QskFluent2Theme( QskSkin::ColorScheme, const std::array< QRgb, NumAccentColors >& ); - - typedef std::array< QRgb, 2 > BorderGradient; - - struct FillColor - { - struct - { - QRgb primary; - QRgb secondary; - QRgb tertiary; - QRgb disabled; - } text; - - struct - { - QRgb primary; - QRgb secondary; - QRgb tertiary; - QRgb disabled; - } accentText; - - struct - { - QRgb primary; - QRgb secondary; - QRgb tertiary; - QRgb disabled; - QRgb selectedText; - } textOnAccent; - - struct - { - QRgb defaultColor; - QRgb secondary; - QRgb tertiary; - QRgb inputActive; - QRgb disabled; - } control; - - struct - { - QRgb defaultColor; - QRgb disabled; - } controlStrong; - - struct - { - QRgb secondary; - QRgb tertiary; - QRgb disabled; - } subtle; - - struct - { - QRgb defaultColor; - } controlSolid; - - struct - { - QRgb secondary; - QRgb tertiary; - QRgb quaternary; - QRgb disabled; - } controlAlt; - - struct - { - QRgb defaultColor; - QRgb secondary; - QRgb tertiary; - QRgb disabled; - QRgb selectedTextBackground; - } accent; - }; - - struct Elevation - { - struct - { - BorderGradient border; - } control; - - struct - { - BorderGradient border; - } circle; - - struct - { - BorderGradient border; - BorderGradient borderFocused; - } textControl; - - struct - { - BorderGradient border; - } accentControl; - }; - - struct StrokeColor - { - struct - { - QRgb defaultColor; - QRgb secondary; - QRgb onAccentDefault; - QRgb onAccentSecondary; - QRgb onAccentTertiary; - QRgb onAccentDisabled; - } control; - - struct - { - QRgb defaultColor; - QRgb disabled; - } controlStrong; - - struct - { - QRgb defaultColor; - QRgb defaultSolid; - } card; - - struct - { - QRgb defaultColor; - } divider; - - struct - { - QRgb defaultColor; - QRgb flyout; - } surface; - - struct - { - QRgb outer; - QRgb inner; - } focus; - }; - - struct Background - { - struct - { - QRgb defaultColor; - QRgb secondary; - QRgb tertiary; - } card; - - struct - { - QRgb defaultColor; - } overlay; - - struct - { - QRgb alt; - } layer; - - struct - { - QRgb defaultColor; - } flyout; - - struct - { - QRgb base; - QRgb secondary; - QRgb tertiary; - QRgb quaternary; - } solid; - }; - - struct - { - FillColor fillColor; - Elevation elevation; - StrokeColor strokeColor; - Background background; - } palette; - - struct ShadowSettings - { - QskShadowMetrics metrics; - QRgb color; - }; - - struct - { - ShadowSettings cardRest; - ShadowSettings cardHover; - ShadowSettings flyout; - ShadowSettings dialog; - } shadow; -}; +class QskFluent2Theme; class QSK_FLUENT2_EXPORT QskFluent2Skin : public QskSkin { @@ -238,7 +19,7 @@ class QSK_FLUENT2_EXPORT QskFluent2Skin : public QskSkin public: QskFluent2Skin( const QskFluent2Theme&, QObject* parent = nullptr ); - ~QskFluent2Skin() override; + ~QskFluent2Skin() override; enum GraphicRole { @@ -267,7 +48,7 @@ class QSK_FLUENT2_EXPORT QskFluent2Skin : public QskSkin private: void setupFonts(); - void setupGraphicFilters( const QskFluent2Theme& palette ); + void setupGraphicFilters( const QskFluent2Theme& ); void setGraphicColor( GraphicRole, QRgb ); }; diff --git a/skins/fluent2/QskFluent2SkinFactory.cpp b/skins/fluent2/QskFluent2SkinFactory.cpp index 4d015c4b..a98afd83 100644 --- a/skins/fluent2/QskFluent2SkinFactory.cpp +++ b/skins/fluent2/QskFluent2SkinFactory.cpp @@ -5,6 +5,7 @@ #include "QskFluent2SkinFactory.h" #include "QskFluent2Skin.h" +#include "QskFluent2Theme.h" static const QString fluent2LightSkinName = QStringLiteral( "Fluent2 Light" ); static const QString fluent2DarkSkinName = QStringLiteral( "Fluent2 Dark" ); diff --git a/skins/fluent2/QskFluent2SkinFactory.h b/skins/fluent2/QskFluent2SkinFactory.h index 3903bf73..3b081862 100644 --- a/skins/fluent2/QskFluent2SkinFactory.h +++ b/skins/fluent2/QskFluent2SkinFactory.h @@ -19,7 +19,7 @@ class QSK_FLUENT2_EXPORT QskFluent2SkinFactory : public QskSkinFactory public: QskFluent2SkinFactory( QObject* parent = nullptr ); - ~QskFluent2SkinFactory() override; + ~QskFluent2SkinFactory() override; QStringList skinNames() const override; QskSkin* createSkin( const QString& skinName ) override; diff --git a/skins/fluent2/QskFluent2Theme.cpp b/skins/fluent2/QskFluent2Theme.cpp new file mode 100644 index 00000000..10ae8ed2 --- /dev/null +++ b/skins/fluent2/QskFluent2Theme.cpp @@ -0,0 +1,240 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2023 Edelhirsch Software GmbH + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#include "QskFluent2Theme.h" +#include + +namespace +{ + inline constexpr QRgb rgbGray( int value, qreal opacity = 1.0 ) + { + return qRgba( value, value, value, qRound( opacity * 255 ) ); + } +} + +QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme ) + : QskFluent2Theme( colorScheme, + { // default Fluent accent colors: + 0xff98ecfe, + 0xff60ccfe, + 0xff0093f9, + 0xff0078d4, + 0xff005eb7, + 0xff003d92, + 0xff001968 + } ) +{ +} + +QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, + const std::array< QRgb, NumAccentColors >& accentColors ) +{ + if( colorScheme == QskSkin::Light ) + { + // Fill color: + + palette.fillColor.text.primary = rgbGray( 0, 0.8956 ); + palette.fillColor.text.secondary = rgbGray( 0, 0.6063 ); + palette.fillColor.text.tertiary = rgbGray( 0, 0.4458 ); + palette.fillColor.text.disabled = rgbGray( 0, 0.3614 ); + + palette.fillColor.accentText.primary = accentColors[ AccentDark2 ]; + palette.fillColor.accentText.secondary = accentColors[ AccentDark3 ]; + palette.fillColor.accentText.tertiary = accentColors[ AccentDark1 ]; + palette.fillColor.accentText.disabled = rgbGray( 0, 0.3614 ); + + palette.fillColor.textOnAccent.primary = rgbGray( 255 ); + palette.fillColor.textOnAccent.secondary = rgbGray( 255, 0.70 ); + palette.fillColor.textOnAccent.disabled = rgbGray( 255 ); + palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); + + palette.fillColor.control.defaultColor = rgbGray( 255, 0.70 ); + palette.fillColor.control.secondary = rgbGray( 249, 0.50 ); + palette.fillColor.control.tertiary = rgbGray( 249, 0.30 ); + palette.fillColor.control.inputActive = rgbGray( 255 ); + palette.fillColor.control.disabled = rgbGray( 249, 0.30 ); + + palette.fillColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); + palette.fillColor.controlStrong.disabled = rgbGray( 0, 0.3173 ); + + palette.fillColor.subtle.secondary = rgbGray( 0, 0.0373 ); + palette.fillColor.subtle.tertiary = rgbGray( 0, 0.0241 ); + palette.fillColor.subtle.disabled = Qt::transparent; + + palette.fillColor.controlSolid.defaultColor = rgbGray( 255 ); + + palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.0241 ); + palette.fillColor.controlAlt.tertiary = rgbGray( 0, 0.0578 ); + palette.fillColor.controlAlt.quaternary = rgbGray( 0, 0.0924 ); + palette.fillColor.controlAlt.disabled = Qt::transparent; + + palette.fillColor.accent.defaultColor = accentColors[ AccentDark1 ]; + palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.90 ); + palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.80 ); + palette.fillColor.accent.disabled = rgbGray( 0, 0.2169 ); + palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; + + // Elevation: + + palette.elevation.control.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; + palette.elevation.circle.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; + palette.elevation.textControl.border = { rgbGray( 0, 0.0578 ), palette.fillColor.text.secondary }; + palette.elevation.textControl.borderFocused = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.0578 ) }; + palette.elevation.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.40 ) }; + + // Stroke color: + + palette.strokeColor.control.defaultColor = rgbGray( 0, 0.0578 ); + palette.strokeColor.control.secondary = rgbGray( 0, 0.1622 ); + palette.strokeColor.control.onAccentDefault = rgbGray( 255.08 ); + palette.strokeColor.control.onAccentSecondary = rgbGray( 0, 0.40 ); + palette.strokeColor.control.onAccentTertiary = rgbGray( 0, 0.2169 ); + palette.strokeColor.control.onAccentDisabled = rgbGray( 0, 0.0578 ); + + palette.strokeColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); + palette.strokeColor.controlStrong.disabled = rgbGray( 0, 0.2169 ); + + palette.strokeColor.card.defaultColor = rgbGray( 0, 0.0578 ); + palette.strokeColor.card.defaultSolid = rgbGray( 235 ); + + palette.strokeColor.divider.defaultColor = rgbGray( 0, 0.0803 ); + + palette.strokeColor.surface.defaultColor = rgbGray( 117, 0.40 ); + palette.strokeColor.surface.flyout = rgbGray( 0, 0.0578 ); + + palette.strokeColor.focus.outer = rgbGray( 0, 0.8956 ); + palette.strokeColor.focus.inner = rgbGray( 255 ); + + // Background: + + palette.background.card.defaultColor = rgbGray( 255, 0.70 ); + palette.background.card.secondary = rgbGray( 246, 0.50 ); + palette.background.card.tertiary = rgbGray( 255 ); + + palette.background.overlay.defaultColor = rgbGray( 0, 0.30 ); + + palette.background.layer.alt = rgbGray( 255 ); + + palette.background.flyout.defaultColor = rgbGray( 252, 0.85 ); + + palette.background.solid.base = rgbGray( 243 ); + palette.background.solid.secondary = rgbGray( 238 ); + palette.background.solid.tertiary = rgbGray( 249 ); + palette.background.solid.quaternary = rgbGray( 255 ); + + + // Shadow: + + shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.04 ) }; + shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.10 ) }; + shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.14 ) }; + // ### should actually be drawn twice with different values: + shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) }; + } + else if( colorScheme == QskSkin::Dark ) + { + // Fill color: + + palette.fillColor.text.primary = rgbGray( 255 ); + palette.fillColor.text.secondary = rgbGray( 255, 0.786 ); + palette.fillColor.text.tertiary = rgbGray( 255, 0.5442 ); + palette.fillColor.text.disabled = rgbGray( 255, 0.3628 ); + + palette.fillColor.accentText.primary = accentColors[ AccentLight3 ]; + palette.fillColor.accentText.secondary = accentColors[ AccentLight3 ]; + palette.fillColor.accentText.tertiary = accentColors[ AccentLight2 ]; + palette.fillColor.accentText.disabled = rgbGray( 255, 0.3628 ); + + palette.fillColor.textOnAccent.primary = rgbGray( 0 ); + palette.fillColor.textOnAccent.secondary = rgbGray( 0, 0.50 ); + palette.fillColor.textOnAccent.disabled = rgbGray( 255, 0.5302 ); + palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); + + palette.fillColor.control.defaultColor = rgbGray( 255, 0.0605 ); + palette.fillColor.control.secondary = rgbGray( 255, 0.0837 ); + palette.fillColor.control.tertiary = rgbGray( 255, 0.0326 ); + palette.fillColor.control.inputActive = rgbGray( 30, 0.70 ); + palette.fillColor.control.disabled = rgbGray( 255, 0.0419 ); + + palette.fillColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); + palette.fillColor.controlStrong.disabled = rgbGray( 255, 0.2465 ); + + palette.fillColor.subtle.secondary = rgbGray( 255, 0.0605 ); + palette.fillColor.subtle.tertiary = rgbGray( 255, 0.0419 ); + palette.fillColor.subtle.disabled = Qt::transparent; + + palette.fillColor.controlSolid.defaultColor = rgbGray( 69 ); + + palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.10 ); + palette.fillColor.controlAlt.tertiary = rgbGray( 255, 0.0419 ); + palette.fillColor.controlAlt.quaternary = rgbGray( 255, 0.0698 ); + palette.fillColor.controlAlt.disabled = Qt::transparent; + + palette.fillColor.accent.defaultColor = accentColors[ AccentLight2 ]; + palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentLight2 ], 0.90 ); + palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentLight2 ], 0.80 ); + palette.fillColor.accent.disabled = rgbGray( 255, 0.1581 ); + palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; + + // Elevation: + + palette.elevation.control.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; + palette.elevation.circle.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; + + palette.elevation.textControl.border = { rgbGray( 255, 0.08 ), palette.fillColor.text.secondary }; + + palette.elevation.textControl.borderFocused = { rgbGray( 255, 0.08 ), rgbGray( 255, 0.08 ) }; + palette.elevation.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.14 ) }; + + // Stroke color: + + palette.strokeColor.control.defaultColor = rgbGray( 255, 0.0698 ); + palette.strokeColor.control.secondary = rgbGray( 255, 0.093 ); + palette.strokeColor.control.onAccentDefault = rgbGray( 255, 0.08 ); + palette.strokeColor.control.onAccentSecondary = rgbGray( 0, 0.14 ); + palette.strokeColor.control.onAccentTertiary = rgbGray( 0, 0.2169 ); + palette.strokeColor.control.onAccentDisabled = rgbGray( 0, 0.20 ); + + palette.strokeColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); + palette.strokeColor.controlStrong.disabled = rgbGray( 255, 0.1581 ); + + palette.strokeColor.card.defaultColor = rgbGray( 255, 0.0578 ); + palette.strokeColor.card.defaultSolid = rgbGray( 235 ); + + palette.strokeColor.divider.defaultColor = rgbGray( 255, 0.0837 ); + + palette.strokeColor.surface.defaultColor = rgbGray( 117, 0.40 ); + palette.strokeColor.surface.flyout = rgbGray( 0, 0.20 ); + + palette.strokeColor.focus.outer = rgbGray( 255 ); + palette.strokeColor.focus.inner = rgbGray( 0, 0.70 ); + + // Background: + + palette.background.card.defaultColor = rgbGray( 255, 0.0512 ); + palette.background.card.secondary = rgbGray( 255, 0.0326 ); + palette.background.card.tertiary = rgbGray( 255 ); // not set in Figma + + palette.background.overlay.defaultColor = rgbGray( 0, 0.30 ); + + palette.background.layer.alt = rgbGray( 255, 0.0538 ); + + palette.background.flyout.defaultColor = rgbGray( 44, 0.96 ); + + palette.background.solid.base = rgbGray( 32 ); + palette.background.solid.secondary = rgbGray( 28 ); + palette.background.solid.tertiary = rgbGray( 40 ); + palette.background.solid.quaternary = rgbGray( 44 ); + + + // Shadow: + + shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.13 ) }; + shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.26 ) }; + shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.26 ) }; + // ### should actually be drawn twice with different values: + shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.37 ) }; + } +} diff --git a/skins/fluent2/QskFluent2Theme.h b/skins/fluent2/QskFluent2Theme.h new file mode 100644 index 00000000..af563871 --- /dev/null +++ b/skins/fluent2/QskFluent2Theme.h @@ -0,0 +1,232 @@ +/****************************************************************************** + * QSkinny - Copyright (C) 2023 Edelhirsch Software GmbH + * SPDX-License-Identifier: BSD-3-Clause + *****************************************************************************/ + +#ifndef QSK_FLUENT2_THEME_H +#define QSK_FLUENT2_THEME_H + +#include "QskFluent2Global.h" + +#include +#include + +#include +#include + +class QSK_FLUENT2_EXPORT QskFluent2Theme +{ + public: + enum AccentColors + { + AccentLight3, + AccentLight2, + AccentLight1, + AccentBase, + AccentDark1, + AccentDark2, + AccentDark3, + + NumAccentColors + }; + + QskFluent2Theme( QskSkin::ColorScheme ); + QskFluent2Theme( QskSkin::ColorScheme, const std::array< QRgb, NumAccentColors >& ); + + typedef std::array< QRgb, 2 > BorderGradient; + + struct FillColor + { + struct + { + QRgb primary; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + } text; + + struct + { + QRgb primary; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + } accentText; + + struct + { + QRgb primary; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + QRgb selectedText; + } textOnAccent; + + struct + { + QRgb defaultColor; + QRgb secondary; + QRgb tertiary; + QRgb inputActive; + QRgb disabled; + } control; + + struct + { + QRgb defaultColor; + QRgb disabled; + } controlStrong; + + struct + { + QRgb secondary; + QRgb tertiary; + QRgb disabled; + } subtle; + + struct + { + QRgb defaultColor; + } controlSolid; + + struct + { + QRgb secondary; + QRgb tertiary; + QRgb quaternary; + QRgb disabled; + } controlAlt; + + struct + { + QRgb defaultColor; + QRgb secondary; + QRgb tertiary; + QRgb disabled; + QRgb selectedTextBackground; + } accent; + }; + + struct Elevation + { + struct + { + BorderGradient border; + } control; + + struct + { + BorderGradient border; + } circle; + + struct + { + BorderGradient border; + BorderGradient borderFocused; + } textControl; + + struct + { + BorderGradient border; + } accentControl; + }; + + struct StrokeColor + { + struct + { + QRgb defaultColor; + QRgb secondary; + QRgb onAccentDefault; + QRgb onAccentSecondary; + QRgb onAccentTertiary; + QRgb onAccentDisabled; + } control; + + struct + { + QRgb defaultColor; + QRgb disabled; + } controlStrong; + + struct + { + QRgb defaultColor; + QRgb defaultSolid; + } card; + + struct + { + QRgb defaultColor; + } divider; + + struct + { + QRgb defaultColor; + QRgb flyout; + } surface; + + struct + { + QRgb outer; + QRgb inner; + } focus; + }; + + struct Background + { + struct + { + QRgb defaultColor; + QRgb secondary; + QRgb tertiary; + } card; + + struct + { + QRgb defaultColor; + } overlay; + + struct + { + QRgb alt; + } layer; + + struct + { + QRgb defaultColor; + } flyout; + + struct + { + QRgb base; + QRgb secondary; + QRgb tertiary; + QRgb quaternary; + } solid; + }; + + struct + { + FillColor fillColor; + Elevation elevation; + StrokeColor strokeColor; + Background background; + } palette; + + struct ShadowSettings + { + QskShadowMetrics metrics; + QRgb color; + }; + + struct + { + ShadowSettings cardRest; + ShadowSettings cardHover; + ShadowSettings flyout; + ShadowSettings dialog; + } shadow; +}; + +#endif From 9e7e52898edc153621ed060533da1c2e44f12b93 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 07:29:29 +0200 Subject: [PATCH 19/60] QskSkin::ColorScheme with scoped value names --- skins/fluent2/QskFluent2SkinFactory.cpp | 4 ++-- skins/fluent2/QskFluent2Theme.cpp | 4 ++-- skins/material3/QskMaterial3Skin.cpp | 5 ++--- skins/material3/QskMaterial3SkinFactory.cpp | 4 ++-- src/controls/QskSkin.h | 8 +++++--- src/controls/QskSkinManager.cpp | 5 ++++- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/skins/fluent2/QskFluent2SkinFactory.cpp b/skins/fluent2/QskFluent2SkinFactory.cpp index a98afd83..a7127ba8 100644 --- a/skins/fluent2/QskFluent2SkinFactory.cpp +++ b/skins/fluent2/QskFluent2SkinFactory.cpp @@ -28,12 +28,12 @@ QskSkin* QskFluent2SkinFactory::createSkin( const QString& skinName ) { if ( QString::compare( skinName, fluent2LightSkinName, Qt::CaseInsensitive ) == 0 ) { - QskFluent2Theme theme( QskSkin::Light ); + QskFluent2Theme theme( QskSkin::LightScheme ); return new QskFluent2Skin( theme ); } else if ( QString::compare( skinName, fluent2DarkSkinName, Qt::CaseInsensitive ) == 0 ) { - QskFluent2Theme theme( QskSkin::Dark ); + QskFluent2Theme theme( QskSkin::DarkScheme ); return new QskFluent2Skin( theme ); } diff --git a/skins/fluent2/QskFluent2Theme.cpp b/skins/fluent2/QskFluent2Theme.cpp index 10ae8ed2..dcd48867 100644 --- a/skins/fluent2/QskFluent2Theme.cpp +++ b/skins/fluent2/QskFluent2Theme.cpp @@ -31,7 +31,7 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme ) QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, const std::array< QRgb, NumAccentColors >& accentColors ) { - if( colorScheme == QskSkin::Light ) + if( colorScheme == QskSkin::LightScheme ) { // Fill color: @@ -133,7 +133,7 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, // ### should actually be drawn twice with different values: shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) }; } - else if( colorScheme == QskSkin::Dark ) + else if( colorScheme == QskSkin::DarkScheme ) { // Fill color: diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 8f456dcf..21665588 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -54,7 +54,6 @@ #include #include -#include static const int qskDuration = 150; @@ -1210,7 +1209,7 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme, std::array< QskHctColor, NumPaletteTypes > palettes ) : m_palettes( palettes ) { - if ( colorScheme == QskSkin::Light ) + if ( colorScheme == QskSkin::LightScheme ) { primary = m_palettes[ Primary ].toned( 40 ).rgb(); onPrimary = m_palettes[ Primary ].toned( 100 ).rgb(); @@ -1244,7 +1243,7 @@ QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme, shadow = m_palettes[ Neutral ].toned( 0 ).rgb(); } - else if ( colorScheme == QskSkin::Dark ) + else if ( colorScheme == QskSkin::DarkScheme ) { primary = m_palettes[ Primary ].toned( 80 ).rgb(); onPrimary = m_palettes[ Primary ].toned( 20 ).rgb(); diff --git a/skins/material3/QskMaterial3SkinFactory.cpp b/skins/material3/QskMaterial3SkinFactory.cpp index f65f669c..541db64d 100644 --- a/skins/material3/QskMaterial3SkinFactory.cpp +++ b/skins/material3/QskMaterial3SkinFactory.cpp @@ -27,12 +27,12 @@ QskSkin* QskMaterial3SkinFactory::createSkin( const QString& skinName ) { if ( QString::compare( skinName, materialLightSkinName, Qt::CaseInsensitive ) == 0 ) { - QskMaterial3Theme theme( QskSkin::Light ); + QskMaterial3Theme theme( QskSkin::LightScheme ); return new QskMaterial3Skin( theme ); } else if ( QString::compare( skinName, materialDarkSkinName, Qt::CaseInsensitive ) == 0 ) { - QskMaterial3Theme theme( QskSkin::Dark ); + QskMaterial3Theme theme( QskSkin::DarkScheme ); return new QskMaterial3Skin( theme ); } diff --git a/src/controls/QskSkin.h b/src/controls/QskSkin.h index b02facbb..ba6a6206 100644 --- a/src/controls/QskSkin.h +++ b/src/controls/QskSkin.h @@ -50,10 +50,12 @@ class QSK_EXPORT QskSkin : public QObject // Use Qt::ColorScheme once minimum version is Qt 6.5 enum ColorScheme { - Unknown, - Light, - Dark + UnknownScheme, + + LightScheme, + DarkScheme }; + Q_ENUM( ColorScheme ) #endif QskSkin( QObject* parent = nullptr ); diff --git a/src/controls/QskSkinManager.cpp b/src/controls/QskSkinManager.cpp index 45725cd3..3013a8bb 100644 --- a/src/controls/QskSkinManager.cpp +++ b/src/controls/QskSkinManager.cpp @@ -8,14 +8,17 @@ #include #include -#include #include #include #include #include #include #include + +#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 ) +#include #include +#endif static inline QStringList qskSplitPath( const QString& s ) { From aa5b2aaefaa98ac29fc053015ea92f874c75de5f Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 08:03:08 +0200 Subject: [PATCH 20/60] adjusting the section according to the currently focused item --- src/controls/QskFocusIndicator.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/controls/QskFocusIndicator.cpp b/src/controls/QskFocusIndicator.cpp index 7d30a923..c688dffb 100644 --- a/src/controls/QskFocusIndicator.cpp +++ b/src/controls/QskFocusIndicator.cpp @@ -44,6 +44,14 @@ static inline QRectF qskFocusIndicatorClipRect( const QQuickItem* item ) return rect; } +static inline QskAspect::Section qskItemSection( const QQuickItem* item ) +{ + if ( auto control = qskControlCast( item ) ) + return control->section(); + + return QskAspect::Body; +} + class QskFocusIndicator::PrivateData { public: @@ -122,6 +130,8 @@ void QskFocusIndicator::onFocusItemChanged() if ( focusItem && ( focusItem != window()->contentItem() ) ) { + setSection( qskItemSection( focusItem ) ); + auto item = focusItem; m_data->connections += connectItem( item ); From 9550ca62fcbe2531bd7eb7b4dd92c5fb39b7f40a Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 16:45:18 +0200 Subject: [PATCH 21/60] recalculate the scrollable size on skin changes --- src/controls/QskListView.cpp | 8 ++++++++ src/controls/QskListView.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/controls/QskListView.cpp b/src/controls/QskListView.cpp index 478b3716..ad23e8ca 100644 --- a/src/controls/QskListView.cpp +++ b/src/controls/QskListView.cpp @@ -276,6 +276,14 @@ void QskListView::mouseReleaseEvent( QMouseEvent* event ) Inherited::mouseReleaseEvent( event ); } +void QskListView::changeEvent( QEvent* event ) +{ + if ( event->type() == QEvent::StyleChange ) + updateScrollableSize(); + + Inherited::changeEvent( event ); +} + #ifndef QT_NO_WHEELEVENT static qreal qskAlignedToRows( const qreal y0, qreal dy, diff --git a/src/controls/QskListView.h b/src/controls/QskListView.h index 169d31cc..b05f7736 100644 --- a/src/controls/QskListView.h +++ b/src/controls/QskListView.h @@ -87,6 +87,8 @@ class QSK_EXPORT QskListView : public QskScrollView void textOptionsChanged(); protected: + void changeEvent( QEvent* ) override; + void keyPressEvent( QKeyEvent* ) override; void keyReleaseEvent( QKeyEvent* ) override; From 2911aaf88a75e49f6619aa75f7d5cacc9d30ff61 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 16:48:37 +0200 Subject: [PATCH 22/60] messagebox/messageboxQml examples moved to gallery --- examples/CMakeLists.txt | 2 - examples/gallery/dialog/DialogPage.cpp | 142 +++++++++++++--------- examples/messagebox/CMakeLists.txt | 6 - examples/messagebox/main.cpp | 155 ------------------------- examples/messageboxQml/CMakeLists.txt | 9 -- examples/messageboxQml/main.cpp | 29 ----- examples/messageboxQml/messagebox.qml | 147 ----------------------- examples/messageboxQml/messagebox.qrc | 5 - 8 files changed, 84 insertions(+), 411 deletions(-) delete mode 100644 examples/messagebox/CMakeLists.txt delete mode 100644 examples/messagebox/main.cpp delete mode 100644 examples/messageboxQml/CMakeLists.txt delete mode 100644 examples/messageboxQml/main.cpp delete mode 100644 examples/messageboxQml/messagebox.qml delete mode 100644 examples/messageboxQml/messagebox.qrc diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 5a00d0a7..a9951719 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -6,7 +6,6 @@ add_subdirectory(desktop) add_subdirectory(gallery) add_subdirectory(layouts) -add_subdirectory(messagebox) add_subdirectory(mycontrols) add_subdirectory(qvgviewer) add_subdirectory(thumbnails) @@ -18,5 +17,4 @@ if( BUILD_QML_EXPORT ) add_subdirectory(buttons) add_subdirectory(frames) add_subdirectory(glabels) - add_subdirectory(messageboxQml) endif() diff --git a/examples/gallery/dialog/DialogPage.cpp b/examples/gallery/dialog/DialogPage.cpp index bc77a02a..0e9e7946 100644 --- a/examples/gallery/dialog/DialogPage.cpp +++ b/examples/gallery/dialog/DialogPage.cpp @@ -15,80 +15,106 @@ namespace { class Button : public QskPushButton { - Q_OBJECT - public: - enum ButtonType + Button( const QString& text, QQuickItem* parent = nullptr ) + : QskPushButton( text, parent ) { - Message, - Information, - Warning, - Critical, + } + }; - Question, - Selection, - - TypeCount - }; - Q_ENUM( ButtonType ) - - Button( ButtonType type, QQuickItem* parent = nullptr ) - : QskPushButton( parent ) - , m_type( type ) + class ButtonBox : public QskLinearBox + { + public: + ButtonBox( QQuickItem* parent = nullptr ) + : QskLinearBox( Qt::Horizontal, 2, parent ) { - setShape( 10 ); - initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Fixed ); + setObjectName( "ButtonBox" ); - const int index = metaObject()->indexOfEnumerator( "ButtonType" ); - setText( metaObject()->enumerator( index ).key( m_type ) ); + setMargins( 10 ); + setSpacing( 20 ); - connect( this, &QskPushButton::clicked, this, &Button::showDialog ); + auto messageButton = new Button( "Message", this ); + connect( messageButton, &Button::clicked, this, &ButtonBox::execMessage ); + + auto informationButton = new Button( "Information", this ); + connect( informationButton, &Button::clicked, this, &ButtonBox::execInformation ); + + auto questionButton = new Button( "Question", this ); + connect( questionButton, &Button::clicked, this, &ButtonBox::execQuestion ); + + auto warningButton = new Button( "Warning", this ); + connect( warningButton, &Button::clicked, this, &ButtonBox::execWarning ); + + auto criticalButton = new Button( "Critical", this ); + connect( criticalButton, &Button::clicked, this, &ButtonBox::execCritical ); + + auto selectButton = new Button( "Selection", this ); + connect( selectButton, &Button::clicked, this, &ButtonBox::execSelection ); + + setExtraSpacingAt( Qt::BottomEdge ); } private: - void showDialog() + void execMessage() { - switch( static_cast< int >( m_type ) ) - { - case Message: - qskDialog->message( text(), text(), QskStandardSymbol::Ok ); - break; - - case Information: - qskDialog->information( text(), text() ); - break; - - case Warning: - qskDialog->warning( text(), text() ); - break; - - case Critical: - qskDialog->critical( text(), text() ); - break; - - case Question: - qskDialog->question( text(), text() ); - break; - - case Selection: - qskDialog->select( text(), text(), { "yes", "no", "maybe" } ); - break; - } + qskDialog->message( "Message", "Request vector, over.", + QskStandardSymbol::NoSymbol, QskDialog::Close ); } - const ButtonType m_type; + void execInformation() + { + qskDialog->information( "Information", + "We have clearance, Clarence." ); + } + + void execQuestion() + { + qskDialog->question( "Question", + "Roger, Roger. Do we have a vector, Victor ?" ); + } + + void execWarning() + { + qskDialog->warning( "Warning", "We have clearance, Clarence." ); + } + + void execCritical() + { + qskDialog->critical( "Critical", "That's Clarence Oveur. Over." ); + } + + void execSelection() + { + // of course we all love "The Teens" + const QStringList entries = + { + "Give Me More", + "Gimme Gimme Your Love", + "1-2-3-4 Red Light", + "New York", + "If You Walk Away", + "Eloise", + "On The Radio", + "We Are The Teens", + "Never Gonna Tell No Lie To You", + "Walking On Sunshine ", + "Get Out Of My Mind", + "Cover Girl ", + "Here I Stand", + "Gypsy Caravan", + "It´s Good To Have A Friend", + "We´ll Have A Party Tonite ´nite", + "Automatic World", + "Gimme Gimme Gimme Gimme Gimme Your Love" + }; + + qskDialog->select( "Here we go ...", "Hot Hot Hot", entries, 7 ); + } }; } DialogPage::DialogPage( QQuickItem* parent ) : Page( Qt::Horizontal, parent ) { - auto box = new QskLinearBox( Qt::Horizontal, 2, this ); - box->setSpacing( 20 ); - box->setExtraSpacingAt( Qt::BottomEdge ); - - for ( int i = 0; i < Button::TypeCount; i++ ) - new Button( static_cast< Button::ButtonType >( i ), box ); + ( void ) new ButtonBox( this ); } - -#include "DialogPage.moc" diff --git a/examples/messagebox/CMakeLists.txt b/examples/messagebox/CMakeLists.txt deleted file mode 100644 index 525b4612..00000000 --- a/examples/messagebox/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -############################################################################ -# QSkinny - Copyright (C) 2016 Uwe Rathmann -# SPDX-License-Identifier: BSD-3-Clause -############################################################################ - -qsk_add_example(messagebox main.cpp) diff --git a/examples/messagebox/main.cpp b/examples/messagebox/main.cpp deleted file mode 100644 index 360995ae..00000000 --- a/examples/messagebox/main.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -class Button : public QskPushButton -{ - public: - Button( const QString& text, QQuickItem* parent = nullptr ) - : QskPushButton( text, parent ) - { - setObjectName( text ); - setSizePolicy( QskSizePolicy::MinimumExpanding, - QskSizePolicy::MinimumExpanding ); - } -}; - -class ButtonBox : public QskLinearBox -{ - public: - ButtonBox( QQuickItem* parent = nullptr ) - : QskLinearBox( Qt::Horizontal, 2, parent ) - { - setObjectName( "ButtonBox" ); - - setMargins( 10 ); - setSpacing( 5 ); - - Button* messageButton = new Button( "Message", this ); - connect( messageButton, &Button::clicked, this, &ButtonBox::execMessage ); - - Button* informationButton = new Button( "Information", this ); - connect( informationButton, &Button::clicked, this, &ButtonBox::execInformation ); - - Button* questionButton = new Button( "Question", this ); - connect( questionButton, &Button::clicked, this, &ButtonBox::execQuestion ); - - Button* warningButton = new Button( "Warning", this ); - connect( warningButton, &Button::clicked, this, &ButtonBox::execWarning ); - - Button* criticalButton = new Button( "Critical", this ); - connect( criticalButton, &Button::clicked, this, &ButtonBox::execCritical ); - - Button* selectButton = new Button( "Selection", this ); - connect( selectButton, &Button::clicked, this, &ButtonBox::execSelection ); - } - - private: - void execMessage() - { - qDebug() << qskDialog->message( "Message", "Request vector, over.", - QskStandardSymbol::NoSymbol, QskDialog::Close ); - } - - void execInformation() - { - qDebug() << qskDialog->information( "Information", - "We have clearance, Clarence." ); - } - - void execQuestion() - { - qDebug() << qskDialog->question( "Question", - "Roger, Roger. Do we have a vector, Victor ?" ); - } - - void execWarning() - { - qDebug() << qskDialog->warning( "Warning", "We have clearance, Clarence." ); - } - - void execCritical() - { - qDebug() << qskDialog->critical( "Critical", "That's Clarence Oveur. Over." ); - } - - void execSelection() - { - // of course we all love "The Teens" - const QStringList entries = - { - "Give Me More", - "Gimme Gimme Your Love", - "1-2-3-4 Red Light", - "New York", - "If You Walk Away", - "Eloise", - "On The Radio", - "We Are The Teens", - "Never Gonna Tell No Lie To You", - "Walking On Sunshine ", - "Get Out Of My Mind", - "Cover Girl ", - "Here I Stand", - "Gypsy Caravan", - "It´s Good To Have A Friend", - "We´ll Have A Party Tonite ´nite", - "Automatic World", - "Gimme Gimme Gimme Gimme Gimme Your Love" - }; - - qDebug() << qskDialog->select( "Here we go ...", "Hot Hot Hot", entries, 7 ); - } -}; - -int main( int argc, char* argv[] ) -{ -#ifdef ITEM_STATISTICS - QskObjectCounter counter( true ); -#endif - - QGuiApplication app( argc, argv ); - - SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts ); - - qskDialog->setPolicy( QskDialog::EmbeddedBox ); - - auto box = new ButtonBox(); - - /* - To avoid losing the focus, when a message box is executed - we have to define the "main window" ( here a ButtonBox ) to - be a focusScope. - */ - box->setFlag( QQuickItem::ItemIsFocusScope, true ); - box->setTabFence( true ); - box->setFocusPolicy( Qt::TabFocus ); - - // setting the initial focus - box->itemAtIndex( 0 )->setFocus( true ); - box->setFocus( true ); - - QskWindow window; - window.addItem( box ); - window.addItem( new QskFocusIndicator() ); - - window.resize( 800, 800 ); - window.show(); - - return app.exec(); -} diff --git a/examples/messageboxQml/CMakeLists.txt b/examples/messageboxQml/CMakeLists.txt deleted file mode 100644 index db3c2999..00000000 --- a/examples/messageboxQml/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -############################################################################ -# QSkinny - Copyright (C) 2016 Uwe Rathmann -# SPDX-License-Identifier: BSD-3-Clause -############################################################################ - -set(SOURCES main.cpp) -qt_add_resources(SOURCES messagebox.qrc) - -qsk_add_example(messageboxQml ${SOURCES}) diff --git a/examples/messageboxQml/main.cpp b/examples/messageboxQml/main.cpp deleted file mode 100644 index f103efed..00000000 --- a/examples/messageboxQml/main.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/****************************************************************************** - * QSkinny - Copyright (C) 2016 Uwe Rathmann - * SPDX-License-Identifier: BSD-3-Clause - *****************************************************************************/ - -#include - -#include -#include - -#include -#include - -int main( int argc, char* argv[] ) -{ -#ifdef ITEM_STATISTICS - QskObjectCounter counter( true ); -#endif - - QskQml::registerTypes(); - - QGuiApplication app( argc, argv ); - - SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts ); - - QQmlApplicationEngine engine( QUrl( "qrc:/qml/messagebox.qml" ) ); - - return app.exec(); -} diff --git a/examples/messageboxQml/messagebox.qml b/examples/messageboxQml/messagebox.qml deleted file mode 100644 index 6be1eccc..00000000 --- a/examples/messageboxQml/messagebox.qml +++ /dev/null @@ -1,147 +0,0 @@ -import QtQuick 2.0 -import Skinny 1.0 as Qsk -import "qrc:/qml" - -Qsk.Window -{ - id: window - - visible: true - width: 600 - height: 400 - // color: "Beige" - - Qsk.LinearBox - { - orientation: Qt.Horizontal - dimension: 2 - - margins { left: 10; top: 10; right: 10; bottom: 10 } - //margins: 10 - - Qsk.PushButton - { - id: messageButton - text: "Message" - - focus: true - - sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding - - onClicked: - { - var answer = Qsk.Dialog.message( - "Message", "Request vector, over.", - Qsk.StandardSymbol.NoSymbol, Qsk.Dialog.Close - ); - } - } - - Qsk.PushButton - { - id: informationButton - text: "Information" - - sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding - - onClicked: - { - var answer = Qsk.Dialog.information( - "Information", "We have clearance, Clarence." - ); - } - } - - Qsk.PushButton - { - id: questionButton - text: "Question" - - sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding - - onClicked: - { - var answer = Qsk.Dialog.question( - "Question", "Roger, Roger. Do we have a vector, Victor ?", - Qsk.Dialog.Yes | Qsk.Dialog.No - ) - - if ( answer == Qsk.Dialog.Yes ) - console.log( "Yes" ) - else - console.log( "No" ) - } - } - - Qsk.PushButton - { - id: warningButton - text: "Warning" - - sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding - - onClicked: - { - var answer = Qsk.Dialog.warning( - "Warning", "We have clearance, Clarence." - ) - } - } - - Qsk.PushButton - { - id: criticalButton - text: "Critical" - - sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding - - onClicked: - { - var answer = Qsk.Dialog.critical( - "Critical", "That's Clarence Oveur. Over." - ); - } - } - - Qsk.PushButton - { - id: selectionButton - text: "Selection" - - sizePolicy.vertical: Qsk.SizePolicy.MinimumExpanding - - onClicked: - { - var hotTracks = [ - "Give Me More", - "Gimme Gimme Your Love", - "1-2-3-4 Red Light", - "New York", - "If You Walk Away", - "Eloise", - "On The Radio", - "We Are The Teens", - "Never Gonna Tell No Lie To You", - "Walking On Sunshine ", - "Get Out Of My Mind", - "Cover Girl ", - "Here I Stand", - "Gypsy Caravan", - "It´s Good To Have A Friend", - "We´ll Have A Party Tonite ´nite", - "Automatic World", - "Gimme Gimme Gimme Gimme Gimme Your Love" - ] - - var hottestTrackEver = Qsk.Dialog.select( - "Here we go ...", "Hot Hot Hot", hotTracks, 7 ) - - console.log( hottestTrackEver ) - } - } - } - - Qsk.FocusIndicator - { - } -} diff --git a/examples/messageboxQml/messagebox.qrc b/examples/messageboxQml/messagebox.qrc deleted file mode 100644 index 5816580f..00000000 --- a/examples/messageboxQml/messagebox.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - messagebox.qml - - From 7fd2fabb7847cbfa5606648351922edf88aa0f65 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 16:53:12 +0200 Subject: [PATCH 23/60] hardcoded colors removed + themed top level backgrounds --- examples/buttons/buttons.qml | 6 ++--- examples/gallery/main.cpp | 7 +++-- examples/glabels/glabels.qml | 8 +++--- examples/layouts/main.cpp | 42 +++++++++++++++++++---------- examples/qvgviewer/MainWindow.cpp | 5 ++-- examples/qvgviewer/main.cpp | 3 ++- examples/tabview/main.cpp | 3 ++- examples/thumbnails/main.cpp | 9 +++---- playground/dialogbuttons/Window.cpp | 3 ++- playground/inputpanel/main.cpp | 7 ++--- playground/shadows/main.cpp | 3 ++- 11 files changed, 59 insertions(+), 37 deletions(-) diff --git a/examples/buttons/buttons.qml b/examples/buttons/buttons.qml index 0dfe19f0..8ac52c30 100644 --- a/examples/buttons/buttons.qml +++ b/examples/buttons/buttons.qml @@ -9,7 +9,6 @@ Qsk.Window width: 600 height: 600 - color: "Beige" Component.onCompleted: { @@ -30,9 +29,10 @@ Qsk.Window { orientation: Qt.Horizontal dimension: 3 + panel : true // to have a themed background - //margins: 10 // only possible with Qt <= 6.1 - margins { left: 10; top: 10; right: 10; bottom: 10 } + // padding: 10 // only possible with Qt <= 6.1 + padding { left: 10; top: 10; right: 10; bottom: 10 } spacing: 10 TestButton diff --git a/examples/gallery/main.cpp b/examples/gallery/main.cpp index 42e8b280..fd2f41ad 100644 --- a/examples/gallery/main.cpp +++ b/examples/gallery/main.cpp @@ -271,8 +271,11 @@ int main( int argc, char* argv[] ) Qsk::addGraphicProvider( QString(), new GraphicProvider() ); Qsk::addGraphicProvider( "shapes", new SkinnyShapeProvider() ); - // dialogs in faked windows -> QskSubWindow - QskDialog::instance()->setPolicy( QskDialog::EmbeddedBox ); + if ( true ) // environment variable, TODO ... + { + // dialogs in faked windows -> QskSubWindow + QskDialog::instance()->setPolicy( QskDialog::EmbeddedBox ); + } QGuiApplication app( argc, argv ); diff --git a/examples/glabels/glabels.qml b/examples/glabels/glabels.qml index 096a4003..0bf32278 100644 --- a/examples/glabels/glabels.qml +++ b/examples/glabels/glabels.qml @@ -8,15 +8,15 @@ Qsk.Window width: 600 height: 600 - color: "Beige" - Qsk.LinearBox { orientation: Qt.Horizontal + panel: true + dimension: 3 - //margins: 10 - margins { left: 10; top: 10; right: 10; bottom: 10 } + //padding: 10 + padding { left: 10; top: 10; right: 10; bottom: 10 } spacing: 20 Repeater diff --git a/examples/layouts/main.cpp b/examples/layouts/main.cpp index e14cf38f..66ba5509 100644 --- a/examples/layouts/main.cpp +++ b/examples/layouts/main.cpp @@ -20,6 +20,29 @@ #include +namespace +{ + class TabView : public QskTabView + { + public: + TabView( QQuickItem* parent = nullptr ) + : QskTabView( parent ) + { + setMargins( 10 ); + setTabBarEdge( Qt::LeftEdge ); + setAutoFitTabs( true ); + + addTab( "Grid Layout", new GridLayoutPage() ); + addTab( "Flow Layout", new FlowLayoutPage() ); + addTab( "Linear Layout", new LinearLayoutPage() ); + addTab( "Dynamic\nConstraints", new DynamicConstraintsPage() ); + addTab( "Stack Layout", new StackLayoutPage() ); + + setCurrentIndex( 0 ); + } + }; +} + int main( int argc, char* argv[] ) { #ifdef ITEM_STATISTICS @@ -32,25 +55,16 @@ int main( int argc, char* argv[] ) SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts ); - auto tabView = new QskTabView(); + auto box = new QskBox(); // to have a themed application background + box->setAutoLayoutChildren( true ); - tabView->setMargins( 10 ); - tabView->setTabBarEdge( Qt::LeftEdge ); - tabView->setAutoFitTabs( true ); - - tabView->addTab( "Grid Layout", new GridLayoutPage() ); - tabView->addTab( "Flow Layout", new FlowLayoutPage() ); - tabView->addTab( "Linear Layout", new LinearLayoutPage() ); - tabView->addTab( "Dynamic\nConstraints", new DynamicConstraintsPage() ); - tabView->addTab( "Stack Layout", new StackLayoutPage() ); - - tabView->setCurrentIndex( 0 ); + (void) new TabView( box ); QSize size( 800, 600 ); - size = size.expandedTo( tabView->sizeHint().toSize() ); + size = size.expandedTo( box->sizeHint().toSize() ); QskWindow window; - window.addItem( tabView ); + window.addItem( box ); window.addItem( new QskFocusIndicator() ); window.resize( size ); diff --git a/examples/qvgviewer/MainWindow.cpp b/examples/qvgviewer/MainWindow.cpp index d53eabdf..1a53bef4 100644 --- a/examples/qvgviewer/MainWindow.cpp +++ b/examples/qvgviewer/MainWindow.cpp @@ -28,7 +28,7 @@ class GraphicLabel : public QskGraphicLabel public: enum Role { - Normal, + Normal = 1000, Inverted }; @@ -94,7 +94,8 @@ MainWindow::MainWindow() invertButton->setLayoutAlignmentHint( Qt::AlignRight ); auto box = new QskLinearBox( Qt::Vertical ); - box->setMargins( 5 ); + box->setPanel( true ); + box->setPadding( 5 ); box->addItem( invertButton ); box->addItem( m_tabView ); diff --git a/examples/qvgviewer/main.cpp b/examples/qvgviewer/main.cpp index 58a2c338..b5b6af36 100644 --- a/examples/qvgviewer/main.cpp +++ b/examples/qvgviewer/main.cpp @@ -20,7 +20,8 @@ int main( int argc, char* argv[] ) QGuiApplication app( argc, argv ); - SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts ); + SkinnyShortcut::enable( SkinnyShortcut::DebugBackground | + SkinnyShortcut::DebugStatistics | SkinnyShortcut::Quit ); auto focusIndicator = new QskFocusIndicator(); focusIndicator->setObjectName( "FocusIndicator" ); diff --git a/examples/tabview/main.cpp b/examples/tabview/main.cpp index b352ed96..020fe49f 100644 --- a/examples/tabview/main.cpp +++ b/examples/tabview/main.cpp @@ -160,8 +160,9 @@ int main( int argc, char* argv[] ) auto layoutBox = new QskLinearBox( Qt::Vertical ); layoutBox->setDefaultAlignment( Qt::AlignLeft ); - layoutBox->setMargins( 20 ); + layoutBox->setPadding( 20 ); layoutBox->setSpacing( 10 ); + layoutBox->setPanel( true ); layoutBox->addItem( buttonBox ); layoutBox->addItem( tabView ); diff --git a/examples/thumbnails/main.cpp b/examples/thumbnails/main.cpp index afac5d69..e0a7c7e3 100644 --- a/examples/thumbnails/main.cpp +++ b/examples/thumbnails/main.cpp @@ -77,8 +77,6 @@ class Thumbnail : public QskPushButton setBoxShapeHint( QskPushButton::Panel, QskBoxShapeMetrics( 20, Qt::RelativeSize ) ); setStrutSizeHint( QskPushButton::Icon, -1, -1 ); - - setSection( QskAspect::Header ); // to make them flat } private: @@ -191,7 +189,8 @@ class ScrollArea : public QskScrollArea { // settings usually done in the skins setBoxBorderMetricsHint( Viewport, 2 ); - setBoxShapeHint( Viewport, 20 ); + setBoxBorderColorsHint( Viewport, Qt::gray ); // works with most color schemes + setBoxShapeHint( Viewport, 40 ); // a radius to see that clipping works for ( auto subControl : { HorizontalScrollBar, VerticalScrollBar } ) setMetric( subControl | QskAspect::Size, 20 ); @@ -257,7 +256,8 @@ int main( int argc, char* argv[] ) */ auto box = new QskLinearBox( Qt::Vertical ); - box->setMargins( 20 ); + box->setPanel( true ); + box->setPadding( 20 ); auto buttonBox = new QskLinearBox( Qt::Horizontal, box ); buttonBox->setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed ); @@ -280,7 +280,6 @@ int main( int argc, char* argv[] ) QskWindow window; window.resize( 600, 600 ); - window.setColor( "SteelBlue" ); window.addItem( box ); window.addItem( focusIndicator ); diff --git a/playground/dialogbuttons/Window.cpp b/playground/dialogbuttons/Window.cpp index e53cd480..0db8b6cb 100644 --- a/playground/dialogbuttons/Window.cpp +++ b/playground/dialogbuttons/Window.cpp @@ -14,7 +14,8 @@ Window::Window( Qt::Orientation orientation ) { m_layoutBox = new QskLinearBox( invertedOrientation() ); m_layoutBox->setObjectName( "MainBox" ); - m_layoutBox->setMargins( 10 ); + m_layoutBox->setPanel( true ); + m_layoutBox->setPadding( 10 ); m_layoutBox->setExtraSpacingAt( Qt::BottomEdge | Qt::RightEdge ); addBox( QskDialog::Ok ); diff --git a/playground/inputpanel/main.cpp b/playground/inputpanel/main.cpp index 6cd7facc..6f611a25 100644 --- a/playground/inputpanel/main.cpp +++ b/playground/inputpanel/main.cpp @@ -329,7 +329,8 @@ class Window : public QskWindow { auto box = new QskLinearBox( Qt::Horizontal ); box->setSpacing( 10 ); - box->setMargins( 20 ); + box->setPadding( 10 ); + box->setPanel( true ); auto listView = new LocaleListView( box ); auto inputBox = new InputBox( box ); @@ -367,14 +368,14 @@ int main( int argc, char* argv[] ) Window window1; window1.setObjectName( "Window 1" ); - window1.setColor( "PapayaWhip" ); + window1.setTitle( "Window 1" ); window1.resize( 600, 600 ); window1.show(); #if 1 Window window2; window2.setObjectName( "Window 2" ); - window2.setColor( "Pink" ); + window2.setTitle( "Window 2" ); window2.setX( window1.x() + 100 ); window2.resize( 600, 600 ); window2.show(); diff --git a/playground/shadows/main.cpp b/playground/shadows/main.cpp index 44d24bd3..2d6d6de9 100644 --- a/playground/shadows/main.cpp +++ b/playground/shadows/main.cpp @@ -65,7 +65,8 @@ class GridBox : public QskGridBox GridBox( QQuickItem* parent = nullptr ) : QskGridBox( parent ) { - setMargins( 5 ); + setPanel( true ); + setPadding( 5 ); setColumnStretchFactor( 1, 1 ); auto sliderX = new Slider( -50, 50, 1, 10 ); From b00cfbdd6616b36d6657d62e9c6ffb41b47ee8a0 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 16:54:53 +0200 Subject: [PATCH 24/60] themed top level background --- src/dialogs/QskDialogWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dialogs/QskDialogWindow.cpp b/src/dialogs/QskDialogWindow.cpp index 224825a0..99014d6c 100644 --- a/src/dialogs/QskDialogWindow.cpp +++ b/src/dialogs/QskDialogWindow.cpp @@ -42,7 +42,8 @@ QskDialogWindow::QskDialogWindow( QWindow* parent ) // doing the layout manually instead ??? setAutoLayoutChildren( true ); m_data->layoutBox = new QskLinearBox( Qt::Vertical, contentItem() ); - m_data->layoutBox->setMargins( 5 ); + m_data->layoutBox->setPadding( 5 ); + m_data->layoutBox->setPanel( true ); // for a themed background } QskDialogWindow::~QskDialogWindow() From 997926223fa58d31c4aa32fe0e3b56b6ca1246ab Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 16:56:19 +0200 Subject: [PATCH 25/60] broken QskTabButton padding fixed --- skins/squiek/QskSquiekSkin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 18fc6fe6..11c2d3e6 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -780,7 +780,7 @@ void Editor::setupTabButton() { const auto aspect = Q::Panel | variation; - QskMargins margins0, margins1, padding; + QskMargins margins0, margins1; QskBoxBorderMetrics border( 1 ); QskBoxShapeMetrics shape( 4 ); @@ -832,7 +832,7 @@ void Editor::setupTabButton() for ( const auto state : { Q::Checked | A::NoState, Q::Checked | Q::Pressed } ) setMargin( aspect | state, margins1 ); - setPadding( aspect, padding ); + setPadding( aspect, { 6, 12, 6, 12 } ); setBoxBorderMetrics( aspect, border ); setBoxShape( aspect, shape ); From 5cf3f093643c2e56c28798938c3b79d130743151 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 17:31:31 +0200 Subject: [PATCH 26/60] code harmonized with fluent2 branch --- skins/fluent2/QskFluent2Theme.cpp | 292 ++++++++++++++++-------------- 1 file changed, 152 insertions(+), 140 deletions(-) diff --git a/skins/fluent2/QskFluent2Theme.cpp b/skins/fluent2/QskFluent2Theme.cpp index dcd48867..97f4ad3f 100644 --- a/skins/fluent2/QskFluent2Theme.cpp +++ b/skins/fluent2/QskFluent2Theme.cpp @@ -31,99 +31,106 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme ) QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, const std::array< QRgb, NumAccentColors >& accentColors ) { - if( colorScheme == QskSkin::LightScheme ) + using namespace QskRgb; + + if( colorScheme != QskSkin::DarkScheme ) { - // Fill color: + { + auto& colors = palette.fillColor; - palette.fillColor.text.primary = rgbGray( 0, 0.8956 ); - palette.fillColor.text.secondary = rgbGray( 0, 0.6063 ); - palette.fillColor.text.tertiary = rgbGray( 0, 0.4458 ); - palette.fillColor.text.disabled = rgbGray( 0, 0.3614 ); + colors.text.primary = rgbGray( 0, 0.8956 ); + colors.text.secondary = rgbGray( 0, 0.6063 ); + colors.text.tertiary = rgbGray( 0, 0.4458 ); + colors.text.disabled = rgbGray( 0, 0.3614 ); - palette.fillColor.accentText.primary = accentColors[ AccentDark2 ]; - palette.fillColor.accentText.secondary = accentColors[ AccentDark3 ]; - palette.fillColor.accentText.tertiary = accentColors[ AccentDark1 ]; - palette.fillColor.accentText.disabled = rgbGray( 0, 0.3614 ); + colors.accentText.primary = accentColors[ AccentDark2 ]; + colors.accentText.secondary = accentColors[ AccentDark3 ]; + colors.accentText.tertiary = accentColors[ AccentDark1 ]; + colors.accentText.disabled = rgbGray( 0, 0.3614 ); - palette.fillColor.textOnAccent.primary = rgbGray( 255 ); - palette.fillColor.textOnAccent.secondary = rgbGray( 255, 0.70 ); - palette.fillColor.textOnAccent.disabled = rgbGray( 255 ); - palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); + colors.textOnAccent.primary = rgbGray( 255 ); + colors.textOnAccent.secondary = rgbGray( 255, 0.70 ); + colors.textOnAccent.disabled = rgbGray( 255 ); + colors.textOnAccent.selectedText = rgbGray( 255 ); - palette.fillColor.control.defaultColor = rgbGray( 255, 0.70 ); - palette.fillColor.control.secondary = rgbGray( 249, 0.50 ); - palette.fillColor.control.tertiary = rgbGray( 249, 0.30 ); - palette.fillColor.control.inputActive = rgbGray( 255 ); - palette.fillColor.control.disabled = rgbGray( 249, 0.30 ); + colors.control.defaultColor = rgbGray( 255, 0.70 ); + colors.control.secondary = rgbGray( 249, 0.50 ); + colors.control.tertiary = rgbGray( 249, 0.30 ); + colors.control.inputActive = rgbGray( 255 ); + colors.control.disabled = rgbGray( 249, 0.30 ); - palette.fillColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); - palette.fillColor.controlStrong.disabled = rgbGray( 0, 0.3173 ); + colors.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); + colors.controlStrong.disabled = rgbGray( 0, 0.3173 ); - palette.fillColor.subtle.secondary = rgbGray( 0, 0.0373 ); - palette.fillColor.subtle.tertiary = rgbGray( 0, 0.0241 ); - palette.fillColor.subtle.disabled = Qt::transparent; + colors.subtle.secondary = rgbGray( 0, 0.0373 ); + colors.subtle.tertiary = rgbGray( 0, 0.0241 ); + colors.subtle.disabled = Qt::transparent; - palette.fillColor.controlSolid.defaultColor = rgbGray( 255 ); + colors.controlSolid.defaultColor = rgbGray( 255 ); - palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.0241 ); - palette.fillColor.controlAlt.tertiary = rgbGray( 0, 0.0578 ); - palette.fillColor.controlAlt.quaternary = rgbGray( 0, 0.0924 ); - palette.fillColor.controlAlt.disabled = Qt::transparent; + colors.controlAlt.secondary = rgbGray( 0, 0.0241 ); + colors.controlAlt.tertiary = rgbGray( 0, 0.0578 ); + colors.controlAlt.quaternary = rgbGray( 0, 0.0924 ); + colors.controlAlt.disabled = Qt::transparent; - palette.fillColor.accent.defaultColor = accentColors[ AccentDark1 ]; - palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.90 ); - palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentDark1 ], 0.80 ); - palette.fillColor.accent.disabled = rgbGray( 0, 0.2169 ); - palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; + colors.accent.defaultColor = accentColors[ AccentDark1 ]; + colors.accent.secondary = toTransparentF( accentColors[ AccentDark1 ], 0.90 ); + colors.accent.tertiary = toTransparentF( accentColors[ AccentDark1 ], 0.80 ); + colors.accent.disabled = rgbGray( 0, 0.2169 ); + colors.accent.selectedTextBackground = accentColors[ AccentBase ]; + } - // Elevation: + { + auto& colors = palette.elevation; - palette.elevation.control.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; - palette.elevation.circle.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; - palette.elevation.textControl.border = { rgbGray( 0, 0.0578 ), palette.fillColor.text.secondary }; - palette.elevation.textControl.borderFocused = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.0578 ) }; - palette.elevation.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.40 ) }; + colors.control.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; + colors.circle.border = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.1622 ) }; + colors.textControl.border = { rgbGray( 0, 0.0578 ), palette.fillColor.text.secondary }; + colors.textControl.borderFocused = { rgbGray( 0, 0.0578 ), rgbGray( 0, 0.0578 ) }; + colors.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.40 ) }; + } - // Stroke color: + { + auto& colors = palette.strokeColor; - palette.strokeColor.control.defaultColor = rgbGray( 0, 0.0578 ); - palette.strokeColor.control.secondary = rgbGray( 0, 0.1622 ); - palette.strokeColor.control.onAccentDefault = rgbGray( 255.08 ); - palette.strokeColor.control.onAccentSecondary = rgbGray( 0, 0.40 ); - palette.strokeColor.control.onAccentTertiary = rgbGray( 0, 0.2169 ); - palette.strokeColor.control.onAccentDisabled = rgbGray( 0, 0.0578 ); + colors.control.defaultColor = rgbGray( 0, 0.0578 ); + colors.control.secondary = rgbGray( 0, 0.1622 ); + colors.control.onAccentDefault = rgbGray( 255.08 ); + colors.control.onAccentSecondary = rgbGray( 0, 0.40 ); + colors.control.onAccentTertiary = rgbGray( 0, 0.2169 ); + colors.control.onAccentDisabled = rgbGray( 0, 0.0578 ); - palette.strokeColor.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); - palette.strokeColor.controlStrong.disabled = rgbGray( 0, 0.2169 ); + colors.controlStrong.defaultColor = rgbGray( 0, 0.4458 ); + colors.controlStrong.disabled = rgbGray( 0, 0.2169 ); - palette.strokeColor.card.defaultColor = rgbGray( 0, 0.0578 ); - palette.strokeColor.card.defaultSolid = rgbGray( 235 ); + colors.card.defaultColor = rgbGray( 0, 0.0578 ); + colors.card.defaultSolid = rgbGray( 235 ); - palette.strokeColor.divider.defaultColor = rgbGray( 0, 0.0803 ); + colors.divider.defaultColor = rgbGray( 0, 0.0803 ); - palette.strokeColor.surface.defaultColor = rgbGray( 117, 0.40 ); - palette.strokeColor.surface.flyout = rgbGray( 0, 0.0578 ); + colors.surface.defaultColor = rgbGray( 117, 0.40 ); + colors.surface.flyout = rgbGray( 0, 0.0578 ); - palette.strokeColor.focus.outer = rgbGray( 0, 0.8956 ); - palette.strokeColor.focus.inner = rgbGray( 255 ); + colors.focus.outer = rgbGray( 0, 0.8956 ); + colors.focus.inner = rgbGray( 255 ); + } - // Background: + { + auto& colors = palette.background; - palette.background.card.defaultColor = rgbGray( 255, 0.70 ); - palette.background.card.secondary = rgbGray( 246, 0.50 ); - palette.background.card.tertiary = rgbGray( 255 ); + colors.card.defaultColor = rgbGray( 255, 0.70 ); + colors.card.secondary = rgbGray( 246, 0.50 ); + colors.card.tertiary = rgbGray( 255 ); - palette.background.overlay.defaultColor = rgbGray( 0, 0.30 ); - - palette.background.layer.alt = rgbGray( 255 ); - - palette.background.flyout.defaultColor = rgbGray( 252, 0.85 ); - - palette.background.solid.base = rgbGray( 243 ); - palette.background.solid.secondary = rgbGray( 238 ); - palette.background.solid.tertiary = rgbGray( 249 ); - palette.background.solid.quaternary = rgbGray( 255 ); + colors.overlay.defaultColor = rgbGray( 0, 0.30 ); + colors.layer.alt = rgbGray( 255 ); + colors.flyout.defaultColor = rgbGray( 252, 0.85 ); + colors.solid.base = rgbGray( 243 ); + colors.solid.secondary = rgbGray( 238 ); + colors.solid.tertiary = rgbGray( 249 ); + colors.solid.quaternary = rgbGray( 255 ); + } // Shadow: @@ -133,101 +140,106 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, // ### should actually be drawn twice with different values: shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) }; } - else if( colorScheme == QskSkin::DarkScheme ) + else { - // Fill color: + { + auto& colors = palette.fillColor; - palette.fillColor.text.primary = rgbGray( 255 ); - palette.fillColor.text.secondary = rgbGray( 255, 0.786 ); - palette.fillColor.text.tertiary = rgbGray( 255, 0.5442 ); - palette.fillColor.text.disabled = rgbGray( 255, 0.3628 ); + colors.text.primary = rgbGray( 255 ); + colors.text.secondary = rgbGray( 255, 0.786 ); + colors.text.tertiary = rgbGray( 255, 0.5442 ); + colors.text.disabled = rgbGray( 255, 0.3628 ); - palette.fillColor.accentText.primary = accentColors[ AccentLight3 ]; - palette.fillColor.accentText.secondary = accentColors[ AccentLight3 ]; - palette.fillColor.accentText.tertiary = accentColors[ AccentLight2 ]; - palette.fillColor.accentText.disabled = rgbGray( 255, 0.3628 ); + colors.accentText.primary = accentColors[ AccentLight3 ]; + colors.accentText.secondary = accentColors[ AccentLight3 ]; + colors.accentText.tertiary = accentColors[ AccentLight2 ]; + colors.accentText.disabled = rgbGray( 255, 0.3628 ); - palette.fillColor.textOnAccent.primary = rgbGray( 0 ); - palette.fillColor.textOnAccent.secondary = rgbGray( 0, 0.50 ); - palette.fillColor.textOnAccent.disabled = rgbGray( 255, 0.5302 ); - palette.fillColor.textOnAccent.selectedText = rgbGray( 255 ); + colors.textOnAccent.primary = rgbGray( 0 ); + colors.textOnAccent.secondary = rgbGray( 0, 0.50 ); + colors.textOnAccent.disabled = rgbGray( 255, 0.5302 ); + colors.textOnAccent.selectedText = rgbGray( 255 ); - palette.fillColor.control.defaultColor = rgbGray( 255, 0.0605 ); - palette.fillColor.control.secondary = rgbGray( 255, 0.0837 ); - palette.fillColor.control.tertiary = rgbGray( 255, 0.0326 ); - palette.fillColor.control.inputActive = rgbGray( 30, 0.70 ); - palette.fillColor.control.disabled = rgbGray( 255, 0.0419 ); + colors.control.defaultColor = rgbGray( 255, 0.0605 ); + colors.control.secondary = rgbGray( 255, 0.0837 ); + colors.control.tertiary = rgbGray( 255, 0.0326 ); + colors.control.inputActive = rgbGray( 30, 0.70 ); + colors.control.disabled = rgbGray( 255, 0.0419 ); - palette.fillColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); - palette.fillColor.controlStrong.disabled = rgbGray( 255, 0.2465 ); + colors.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); + colors.controlStrong.disabled = rgbGray( 255, 0.2465 ); - palette.fillColor.subtle.secondary = rgbGray( 255, 0.0605 ); - palette.fillColor.subtle.tertiary = rgbGray( 255, 0.0419 ); - palette.fillColor.subtle.disabled = Qt::transparent; + colors.subtle.secondary = rgbGray( 255, 0.0605 ); + colors.subtle.tertiary = rgbGray( 255, 0.0419 ); + colors.subtle.disabled = Qt::transparent; - palette.fillColor.controlSolid.defaultColor = rgbGray( 69 ); + colors.controlSolid.defaultColor = rgbGray( 69 ); - palette.fillColor.controlAlt.secondary = rgbGray( 0, 0.10 ); - palette.fillColor.controlAlt.tertiary = rgbGray( 255, 0.0419 ); - palette.fillColor.controlAlt.quaternary = rgbGray( 255, 0.0698 ); - palette.fillColor.controlAlt.disabled = Qt::transparent; + colors.controlAlt.secondary = rgbGray( 0, 0.10 ); + colors.controlAlt.tertiary = rgbGray( 255, 0.0419 ); + colors.controlAlt.quaternary = rgbGray( 255, 0.0698 ); + colors.controlAlt.disabled = Qt::transparent; - palette.fillColor.accent.defaultColor = accentColors[ AccentLight2 ]; - palette.fillColor.accent.secondary = QskRgb::toTransparentF( accentColors[ AccentLight2 ], 0.90 ); - palette.fillColor.accent.tertiary = QskRgb::toTransparentF( accentColors[ AccentLight2 ], 0.80 ); - palette.fillColor.accent.disabled = rgbGray( 255, 0.1581 ); - palette.fillColor.accent.selectedTextBackground = accentColors[ AccentBase ]; + colors.accent.defaultColor = accentColors[ AccentLight2 ]; + colors.accent.secondary = toTransparentF( accentColors[ AccentLight2 ], 0.90 ); + colors.accent.tertiary = toTransparentF( accentColors[ AccentLight2 ], 0.80 ); + colors.accent.disabled = rgbGray( 255, 0.1581 ); + colors.accent.selectedTextBackground = accentColors[ AccentBase ]; + } - // Elevation: + { + auto& colors = palette.elevation; - palette.elevation.control.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; - palette.elevation.circle.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; + colors.control.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; + colors.circle.border = { rgbGray( 255, 0.093 ), rgbGray( 255, 0.0698 ) }; - palette.elevation.textControl.border = { rgbGray( 255, 0.08 ), palette.fillColor.text.secondary }; + colors.textControl.border = { rgbGray( 255, 0.08 ), palette.fillColor.text.secondary }; - palette.elevation.textControl.borderFocused = { rgbGray( 255, 0.08 ), rgbGray( 255, 0.08 ) }; - palette.elevation.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.14 ) }; + colors.textControl.borderFocused = { rgbGray( 255, 0.08 ), rgbGray( 255, 0.08 ) }; + colors.accentControl.border = { rgbGray( 255, 0.08 ), rgbGray( 0, 0.14 ) }; + } - // Stroke color: + { + auto& colors = palette.strokeColor; - palette.strokeColor.control.defaultColor = rgbGray( 255, 0.0698 ); - palette.strokeColor.control.secondary = rgbGray( 255, 0.093 ); - palette.strokeColor.control.onAccentDefault = rgbGray( 255, 0.08 ); - palette.strokeColor.control.onAccentSecondary = rgbGray( 0, 0.14 ); - palette.strokeColor.control.onAccentTertiary = rgbGray( 0, 0.2169 ); - palette.strokeColor.control.onAccentDisabled = rgbGray( 0, 0.20 ); + colors.control.defaultColor = rgbGray( 255, 0.0698 ); + colors.control.secondary = rgbGray( 255, 0.093 ); + colors.control.onAccentDefault = rgbGray( 255, 0.08 ); + colors.control.onAccentSecondary = rgbGray( 0, 0.14 ); + colors.control.onAccentTertiary = rgbGray( 0, 0.2169 ); + colors.control.onAccentDisabled = rgbGray( 0, 0.20 ); - palette.strokeColor.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); - palette.strokeColor.controlStrong.disabled = rgbGray( 255, 0.1581 ); + colors.controlStrong.defaultColor = rgbGray( 255, 0.5442 ); + colors.controlStrong.disabled = rgbGray( 255, 0.1581 ); - palette.strokeColor.card.defaultColor = rgbGray( 255, 0.0578 ); - palette.strokeColor.card.defaultSolid = rgbGray( 235 ); + colors.card.defaultColor = rgbGray( 255, 0.0578 ); + colors.card.defaultSolid = rgbGray( 235 ); - palette.strokeColor.divider.defaultColor = rgbGray( 255, 0.0837 ); + colors.divider.defaultColor = rgbGray( 255, 0.0837 ); - palette.strokeColor.surface.defaultColor = rgbGray( 117, 0.40 ); - palette.strokeColor.surface.flyout = rgbGray( 0, 0.20 ); + colors.surface.defaultColor = rgbGray( 117, 0.40 ); + colors.surface.flyout = rgbGray( 0, 0.20 ); - palette.strokeColor.focus.outer = rgbGray( 255 ); - palette.strokeColor.focus.inner = rgbGray( 0, 0.70 ); + colors.focus.outer = rgbGray( 255 ); + colors.focus.inner = rgbGray( 0, 0.70 ); + } - // Background: + { + auto& colors = palette.background; - palette.background.card.defaultColor = rgbGray( 255, 0.0512 ); - palette.background.card.secondary = rgbGray( 255, 0.0326 ); - palette.background.card.tertiary = rgbGray( 255 ); // not set in Figma + colors.card.defaultColor = rgbGray( 255, 0.0512 ); + colors.card.secondary = rgbGray( 255, 0.0326 ); + colors.card.tertiary = rgbGray( 255 ); // not set in Figma - palette.background.overlay.defaultColor = rgbGray( 0, 0.30 ); - - palette.background.layer.alt = rgbGray( 255, 0.0538 ); - - palette.background.flyout.defaultColor = rgbGray( 44, 0.96 ); - - palette.background.solid.base = rgbGray( 32 ); - palette.background.solid.secondary = rgbGray( 28 ); - palette.background.solid.tertiary = rgbGray( 40 ); - palette.background.solid.quaternary = rgbGray( 44 ); + colors.overlay.defaultColor = rgbGray( 0, 0.30 ); + colors.layer.alt = rgbGray( 255, 0.0538 ); + colors.flyout.defaultColor = rgbGray( 44, 0.96 ); + colors.solid.base = rgbGray( 32 ); + colors.solid.secondary = rgbGray( 28 ); + colors.solid.tertiary = rgbGray( 40 ); + colors.solid.quaternary = rgbGray( 44 ); + } // Shadow: From e5e2921bbad17e2a98eb8b1b0ca3ae5075f51e74 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 3 Jul 2023 17:50:57 +0200 Subject: [PATCH 27/60] Fluent2 skin reactivated --- skins/fluent2/QskFluent2Skin.cpp | 1868 ++++++++++++++++------- skins/fluent2/QskFluent2Skin.h | 5 +- skins/fluent2/QskFluent2SkinFactory.cpp | 76 +- skins/fluent2/QskFluent2Theme.cpp | 122 +- skins/fluent2/QskFluent2Theme.h | 35 +- src/controls/QskSkinManager.cpp | 4 - 6 files changed, 1507 insertions(+), 603 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 18559b93..e1641198 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -7,6 +7,67 @@ Definitions ( where possible ) taken from https://www.figma.com/file/NAWMapFlXnoOb86Q2H5GKr/Windows-UI-(Community) */ + +/* + TODO: + + - we have a lot of lines with 1 pixels. Unfortunately OpenGL does some sort + of antialiasing, when a line is not a pixel position. On screens with high + resolution usually no probem, but f.e on mine ... + + - QskCheckBox::Error is not properly supported + + - Pressed state is missing + + - QskComboBox + - QskPageIndicator + + - Hovered state is missing + + - QskPageIndicator + + - QskScrollView + + The extended mode of the scrollbar needs to be implemented + + - QskListView + + - hover state is not implemented + - Indicator subcontrol might be better than using the border of the selection box + + - using qskDpToPixels ? + */ + +/* + The palette is made of a specific configurable colors and + predefined semitransparent shades of gray. Both need to + be resolved to opaque colors with the base colors of the sections. + + Resolving the colors can be done in 2 ways: + + - render time + + This actually means, that we do not create opaque colors and + create the scene graph nodes with semitransparent colors. + + - definition time + + We create opaque colors for the base colors of the sections + and set them as skin hints. + + Resolving at render time sounds like the right solution as we + background colors set in application code will just work. + + Unfortunately we have 2 different sets of grays for light/dark + base colors and when applications are setting a light color, where a + dark color ( or v.v ) is expected we might end up with unacceptable + results: ( white on light or black on dark ). + + So there are pros and cons and we do not have a final opinion + about waht to do. For the moment we implement resolving at definition + time as an option to be able to play with both solutions. + */ + #include "QskFluent2Skin.h" #include "QskFluent2Theme.h" @@ -17,6 +78,7 @@ #include #include #include +#include #include #include #include @@ -79,52 +141,124 @@ namespace return qRgba( value, value, value, qRound( opacity * 255 ) ); } - inline QRgb flattenedColor( QRgb foregroundColor, QRgb backgroundColor ) + inline constexpr QRgb rgbFlattened( QRgb foreground, QRgb background ) { - const qreal alphaRatio = ( ( foregroundColor & QskRgb::AlphaMask ) >> 24 ) / 255.0; - return QskRgb::interpolated( backgroundColor, foregroundColor, alphaRatio ); + //Q_ASSERT( qAlpha( background ) == 255 ); + + const auto r2 = qAlpha( foreground ) / 255.0; + const auto r1 = 1.0 - r2; + + const auto r = qRound( r1 * qRed( background ) + r2 * qRed( foreground ) ); + const auto g = qRound( r1 * qGreen( background ) + r2 * qGreen( foreground ) ); + const auto b = qRound( r1 * qBlue( background ) + r2 * qBlue( foreground ) ); + + return qRgb( r, g, b ); + } + + inline constexpr QRgb rgbSolid( QRgb foreground, QRgb background ) + { + /* + dummy method, so that we can compare the results with + or without resolving the foreground alpha value + */ + +#if 0 + return rgbFlattened( foreground, background ); +#else + //Q_ASSERT( qAlpha( background ) == 255 ); + Q_UNUSED( background ); + return foreground; +#endif } class Editor : private QskSkinHintTableEditor { public: - Editor( QskSkinHintTable* table, const QskFluent2Theme& palette ) + Editor( QskSkinHintTable* table ) : QskSkinHintTableEditor( table ) - , theme( palette ) { } - void setup(); + void setupMetrics(); + void setupColors( QskAspect::Section, const QskFluent2Theme& ); private: - void setupBox(); - void setupCheckBox(); - void setupComboBox(); - void setupDialogButtonBox(); - void setupFocusIndicator(); - void setupInputPanel(); - void setupListView(); - void setupMenu(); - void setupPageIndicator(); - void setupPopup(); - void setupProgressBar(); - void setupPushButton(); - void setupRadioBox(); - void setupScrollView(); - void setupSegmentedBar(); - void setupSeparator(); - void setupSlider(); - void setupSpinBox(); - void setupSubWindow(); - void setupSwitchButton(); - void setupTabButton(); - void setupTabBar(); - void setupTabView(); - void setupTextInput(); - void setupTextLabel(); - void setupVirtualKeyboard(); + void setupPopup( const QskFluent2Theme& ); + void setupSubWindow( const QskFluent2Theme& ); - QskGraphic symbol( const char* name ) const + void setupBoxMetrics(); + void setupBoxColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupCheckBoxMetrics(); + void setupCheckBoxColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupComboBoxMetrics(); + void setupComboBoxColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupDialogButtonBoxMetrics(); + void setupDialogButtonBoxColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupFocusIndicatorMetrics(); + void setupFocusIndicatorColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupGraphicLabelMetrics(); + void setupGraphicLabelColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupListViewMetrics(); + void setupListViewColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupMenuMetrics(); + void setupMenuColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupPageIndicatorMetrics(); + void setupPageIndicatorColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupProgressBarMetrics(); + void setupProgressBarColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupPushButtonMetrics(); + void setupPushButtonColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupRadioBoxMetrics(); + void setupRadioBoxColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupScrollViewMetrics(); + void setupScrollViewColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupSegmentedBarMetrics(); + void setupSegmentedBarColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupSeparatorMetrics(); + void setupSeparatorColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupSliderMetrics(); + void setupSliderColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupSpinBoxMetrics(); + void setupSpinBoxColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupSwitchButtonMetrics(); + void setupSwitchButtonColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupTabButtonMetrics(); + void setupTabButtonColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupTabBarMetrics(); + void setupTabBarColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupTabViewMetrics(); + void setupTabViewColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupTextInputMetrics(); + void setupTextInputColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupTextLabelMetrics(); + void setupTextLabelColors( QskAspect::Section, const QskFluent2Theme& ); + + void setupVirtualKeyboardMetrics(); + void setupVirtualKeyboardColors( QskAspect::Section, const QskFluent2Theme& ); + + inline QskGraphic symbol( const char* name ) const { const QString path = QStringLiteral( ":fluent2/icons/qvg/" ) + name + QStringLiteral( ".qvg" ); @@ -132,66 +266,102 @@ namespace return QskGraphicIO::read( path ); } - void setBoxBorderGradient( QskAspect aspect, QskFluent2Theme::BorderGradient gradient, QRgb baseColor ) + inline void setBoxBorderGradient( QskAspect aspect, + QRgb border1, QRgb border2, QRgb baseColor ) { - const QRgb leftTopRightColor = flattenedColor( gradient[ 0 ], baseColor ); - const QRgb bottomColor = flattenedColor( gradient[ 1 ], baseColor ); + border1 = rgbFlattened( border1, baseColor ); + border2 = rgbFlattened( border2, baseColor ); - setBoxBorderColors( aspect, { leftTopRightColor, leftTopRightColor, leftTopRightColor, bottomColor } ); + setBoxBorderColors( aspect, { border1, border1, border1, border2 } ); } - const QskFluent2Theme& theme; + inline void setBoxBorderGradient( QskAspect aspect, + const QskFluent2Theme::BorderGradient& gradient, QRgb baseColor ) + { + setBoxBorderGradient( aspect, gradient[ 0 ], gradient[ 1 ], baseColor ); + } }; } -void Editor::setup() +void Editor::setupMetrics() { - setupBox(); - setupCheckBox(); - setupComboBox(); - setupDialogButtonBox(); - setupFocusIndicator(); - setupInputPanel(); - setupListView(); - setupMenu(); - setupPageIndicator(); - setupPopup(); - setupProgressBar(); - setupPushButton(); - setupRadioBox(); - setupScrollView(); - setupSegmentedBar(); - setupSeparator(); - setupSlider(); - setupSpinBox(); - setupSubWindow(); - setupSwitchButton(); - setupTabButton(); - setupTabBar(); - setupTabView(); - setupTextInput(); - setupTextLabel(); - setupVirtualKeyboard(); + setupBoxMetrics(); + setupCheckBoxMetrics(); + setupComboBoxMetrics(); + setupDialogButtonBoxMetrics(); + setupFocusIndicatorMetrics(); + setupGraphicLabelMetrics(); + setupListViewMetrics(); + setupMenuMetrics(); + setupPageIndicatorMetrics(); + setupProgressBarMetrics(); + setupPushButtonMetrics(); + setupRadioBoxMetrics(); + setupScrollViewMetrics(); + setupSegmentedBarMetrics(); + setupSeparatorMetrics(); + setupSliderMetrics(); + setupSpinBoxMetrics(); + setupSwitchButtonMetrics(); + setupTabButtonMetrics(); + setupTabBarMetrics(); + setupTabViewMetrics(); + setupTextInputMetrics(); + setupTextLabelMetrics(); + setupVirtualKeyboardMetrics(); } -void Editor::setupBox() +void Editor::setupColors( QskAspect::Section section, const QskFluent2Theme& theme ) { - using Q = QskBox; - using A = QskAspect; + if ( section == QskAspect::Body ) + { + // TODO + setupPopup( theme ); + setupSubWindow( theme ); + } - const auto& pal = theme.palette; + setupBoxColors( section, theme ); + setupCheckBoxColors( section, theme ); + setupComboBoxColors( section, theme ); + setupDialogButtonBoxColors( section, theme ); + setupFocusIndicatorColors( section, theme ); + setupGraphicLabelColors( section, theme ); + setupGraphicLabelMetrics(); + setupListViewColors( section, theme ); + setupMenuColors( section, theme ); + setupPageIndicatorColors( section, theme ); + setupProgressBarColors( section, theme ); + setupPushButtonColors( section, theme ); + setupRadioBoxColors( section, theme ); + setupScrollViewColors( section, theme ); + setupSegmentedBarColors( section, theme ); + setupSeparatorColors( section, theme ); + setupSliderColors( section, theme ); + setupSwitchButtonColors( section, theme ); + setupSpinBoxColors( section, theme ); + setupTabButtonColors( section, theme ); + setupTabBarColors( section, theme ); + setupTabViewColors( section, theme ); + setupTextInputColors( section, theme ); + setupTextLabelColors( section, theme ); + setupVirtualKeyboardColors( section, theme ); +}; - setGradient( Q::Panel, pal.background.solid.base ); - setGradient( Q::Panel | A::Header, pal.background.solid.tertiary ); - setGradient( Q::Panel | A::Footer, pal.background.solid.tertiary ); +void Editor::setupBoxMetrics() +{ } -void Editor::setupCheckBox() +void Editor::setupBoxColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + setGradient( QskBox::Panel | section, + theme.palette.background.solid.base ); +} + +void Editor::setupCheckBoxMetrics() { using Q = QskCheckBox; - const auto& pal = theme.palette; - setStrutSize( Q::Panel, 126, 38 ); setSpacing( Q::Panel, 8 ); @@ -200,482 +370,941 @@ void Editor::setupCheckBox() setBoxBorderMetrics( Q::Box, 1 ); setPadding( Q::Box, 5 ); // "icon size" - setGradient( Q::Box, pal.fillColor.controlAlt.secondary ); - setBoxBorderColors( Q::Box, pal.strokeColor.controlStrong.defaultColor ); - - setGradient( Q::Box | Q::Checked, pal.fillColor.accent.defaultColor ); - setBoxBorderColors( Q::Box | Q::Checked, pal.fillColor.accent.defaultColor ); - - const auto checkMark = symbol( "checkmark" ); - setSymbol( Q::Indicator | Q::Checked, checkMark, { QskStateCombination::CombinationNoState, Q::Disabled } ); - setGraphicRole( Q::Indicator, QskFluent2Skin::GraphicRoleFillColorTextOnAccentPrimary ); - setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.fillColor.text.primary ); - - - setGradient( Q::Box | Q::Hovered, pal.fillColor.controlAlt.tertiary ); - setBoxBorderColors( Q::Box | Q::Hovered, pal.strokeColor.controlStrong.defaultColor ); - setGradient( Q::Box | Q::Hovered | Q::Checked, pal.fillColor.accent.secondary ); - setBoxBorderColors( Q::Box | Q::Hovered | Q::Checked, pal.fillColor.accent.secondary ); - // indicator the same as in Rest state - - setGradient( Q::Box | Q::Pressed, pal.fillColor.controlAlt.quaternary ); - setBoxBorderColors( Q::Box | Q::Pressed, pal.strokeColor.controlStrong.disabled ); - setGradient( Q::Box | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); - setBoxBorderColors( Q::Box | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); - setGraphicRole( Q::Indicator | Q::Pressed | Q::Checked, QskFluent2Skin::GraphicRoleFillColorTextOnAccentSecondary ); - - setGradient( Q::Box | Q::Disabled, pal.fillColor.controlAlt.disabled ); - setBoxBorderColors( Q::Box | Q::Disabled, pal.strokeColor.controlStrong.disabled ); - setGradient( Q::Box | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); - setBoxBorderColors( Q::Box | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); - setGraphicRole( Q::Indicator | Q::Disabled | Q::Checked, QskFluent2Skin::GraphicRoleFillColorTextOnAccentDisabled ); - setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); } -void Editor::setupComboBox() +void Editor::setupCheckBoxColors( + QskAspect::Section section, const QskFluent2Theme& theme ) { - using Q = QskComboBox; + using Q = QskCheckBox; + using A = QskAspect; const auto& pal = theme.palette; + const auto checkMark = symbol( "checkmark" ); + + for ( const auto state1 : { A::NoState, Q::Hovered, Q::Pressed, Q::Disabled } ) + { + QRgb fillColor, borderColor, textColor; + + for ( const auto state2 : { A::NoState, Q::Checked } ) + { + const auto states = state1 | state2; + + if ( states == A::NoState ) + { + fillColor = pal.fillColor.controlAlt.secondary; + borderColor = pal.strokeColor.controlStrong.defaultColor; + textColor = pal.fillColor.text.primary; + } + else if ( states == Q::Hovered ) + { + fillColor = pal.fillColor.controlAlt.tertiary; + borderColor = pal.strokeColor.controlStrong.defaultColor; + textColor = pal.fillColor.text.primary; + } + else if ( states == ( Q::Hovered | Q::Checked ) ) + { + fillColor = pal.fillColor.accent.secondary; + borderColor = fillColor; + textColor = pal.fillColor.text.primary; + } + else if ( states == Q::Checked ) + { + fillColor = pal.fillColor.accent.defaultColor; + borderColor = pal.fillColor.accent.defaultColor; + textColor = pal.fillColor.text.primary; + } + else if ( states == Q::Pressed ) + { + fillColor = pal.fillColor.controlAlt.quaternary; + borderColor = pal.strokeColor.controlStrong.disabled; + textColor = pal.fillColor.text.primary; + } + else if ( states == ( Q::Pressed | Q::Checked ) ) + { + fillColor = pal.fillColor.accent.tertiary; + borderColor = pal.fillColor.accent.tertiary; + textColor = pal.fillColor.text.primary; + + setSymbol( Q::Indicator | states, checkMark ); + } + else if ( states == Q::Disabled ) + { + fillColor = pal.fillColor.controlAlt.disabled; + borderColor = pal.strokeColor.controlStrong.disabled; + textColor = pal.fillColor.text.disabled; + } + else if ( states == ( Q::Disabled | Q::Checked ) ) + { + fillColor = pal.fillColor.accent.disabled; + borderColor = pal.fillColor.accent.disabled; + textColor = pal.fillColor.text.disabled; + } + + /* + Support for QskCheckBox::Error is not properly defined. + Doing some basic definitions, so that we can at least + see the boxes with this state. TODO ... + */ + for ( const auto state3 : { A::NoState, Q::Error } ) + { + const auto box = Q::Box | section | states | state3; + const auto text = Q::Text | section | states | state3; + const auto indicator = Q::Indicator | section | states | state3; + +#if 1 + if ( state3 == Q::Error && !( states & Q::Disabled ) ) + { + borderColor = QskRgb::IndianRed; + if ( states & Q::Checked ) + fillColor = QskRgb::DarkRed; + } +#endif + fillColor = rgbSolid( fillColor, pal.background.solid.base ); + setGradient( box, fillColor ); + + borderColor = rgbSolid( borderColor, fillColor ); + setBoxBorderColors( box, borderColor ); + + setColor( text, textColor ); + + if ( states & Q::Checked ) + { + setGraphicRole( indicator, ( states & Q::Disabled ) + ? QskFluent2Skin::GraphicRoleFillColorTextOnAccentDisabled + : QskFluent2Skin::GraphicRoleFillColorTextOnAccentPrimary ); + + setSymbol( indicator, checkMark ); + } + } + } + } +} + +void Editor::setupComboBoxMetrics() +{ + using Q = QskComboBox; + setStrutSize( Q::Panel, { -1, 32 } ); setBoxBorderMetrics( Q::Panel, 1 ); setBoxShape( Q::Panel, 3 ); setPadding( Q::Panel, { 11, 0, 11, 0 } ); - setGradient( Q::Panel, pal.fillColor.control.defaultColor ); - setBoxBorderGradient( Q::Panel, pal.elevation.control.border, - pal.fillColor.control.defaultColor ); - setStrutSize( Q::Icon, 12, 12 ); setPadding( Q::Icon, { 0, 0, 8, 0 } ); - setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary ); setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.fillColor.text.primary ); setStrutSize( Q::StatusIndicator, 12, 12 ); setSymbol( Q::StatusIndicator, symbol( "spin-box-arrow-down" ) ); setSymbol( Q::StatusIndicator | Q::PopupOpen, symbol( "spin-box-arrow-up" ) ); - setGraphicRole( Q::StatusIndicator, QskFluent2Skin::GraphicRoleFillColorTextSecondary ); - - // Hovered: - - setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); - setBoxBorderGradient( Q::Panel | Q::Hovered, pal.elevation.textControl.border, - pal.fillColor.control.secondary ); - - - // Focused (Pressed doesn't exist yet): - + // Using Focused (Pressed doesn't exist yet): setBoxBorderMetrics( Q::Panel | Q::Focused, { 1, 1, 1, 2 } ); - - setGradient( Q::Panel | Q::Focused, pal.fillColor.control.inputActive ); - - auto gradient = pal.elevation.textControl.border; - gradient.at( 1 ) = pal.fillColor.accent.defaultColor; - - setBoxBorderGradient( Q::Panel | Q::Focused, gradient, pal.fillColor.control.inputActive ); - - // Disabled: - - setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.control.defaultColor ); - - setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); - setGraphicRole( Q::Icon | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); - - setGraphicRole( Q::StatusIndicator | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); } -void Editor::setupDialogButtonBox() +void Editor::setupComboBoxColors( + QskAspect::Section section, const QskFluent2Theme& theme ) { - using Q = QskDialogButtonBox; + using Q = QskComboBox; + using W = QskFluent2Skin; + const auto& pal = theme.palette; - setPadding( Q::Panel, 24 ); - setGradient( Q::Panel, pal.background.solid.base ); - setPadding(Q::Panel, 20 ); + for ( const auto state : { QskAspect::NoState, Q::Hovered, Q::Focused, Q::Disabled } ) + { + QRgb panelColor, borderColor1, borderColor2, textColor; + + if ( state == QskAspect::NoState ) + { + panelColor = pal.fillColor.control.defaultColor; + borderColor1 = pal.elevation.control.border[0]; + borderColor2 = pal.elevation.control.border[1]; + textColor = pal.fillColor.text.primary; + + } + else if ( state == Q::Hovered ) + { + panelColor = pal.fillColor.control.secondary; + borderColor1 = pal.elevation.textControl.border[0]; + borderColor2 = pal.elevation.textControl.border[1]; + textColor = pal.fillColor.text.primary; + } + else if ( state == Q::Focused ) + { + + panelColor = pal.fillColor.control.inputActive; + borderColor1 = pal.elevation.textControl.border[0]; + borderColor2 = pal.fillColor.accent.defaultColor; + textColor = pal.fillColor.text.primary; + } + else if ( state == Q::Disabled ) + { + panelColor = pal.fillColor.control.disabled; + borderColor2 = borderColor1 = pal.strokeColor.control.defaultColor; + textColor = pal.fillColor.text.disabled; + } + + const auto panel = Q::Panel | section | state; + const auto text = Q::Text | section | state; + const auto icon = Q::Icon | section | state; + const auto indicator = Q::StatusIndicator | section | state; + + panelColor = rgbSolid( panelColor, pal.background.solid.base ); + + setGradient( panel, panelColor ); + setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor ); + + setColor( text, textColor ); + + if ( state == Q::Disabled ) + { + setGraphicRole( icon, W::GraphicRoleFillColorTextDisabled ); + setGraphicRole( indicator, W::GraphicRoleFillColorTextDisabled ); + } + else + { + setGraphicRole( icon, W::GraphicRoleFillColorTextPrimary ); + setGraphicRole( indicator, W::GraphicRoleFillColorTextSecondary ); + } + } } -void Editor::setupFocusIndicator() +void Editor::setupDialogButtonBoxMetrics() +{ + setPadding( QskDialogButtonBox::Panel, 20 ); +} + +void Editor::setupDialogButtonBoxColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + setGradient( QskDialogButtonBox::Panel | section, + theme.palette.background.solid.base ); +} + +void Editor::setupFocusIndicatorMetrics() { using Q = QskFocusIndicator; - const auto& pal = theme.palette; setBoxBorderMetrics( Q::Panel, 2 ); setPadding( Q::Panel, 3 ); setBoxShape( Q::Panel, 4 ); - setBoxBorderColors( Q::Panel, pal.strokeColor.focus.outer ); } -void Editor::setupInputPanel() +void Editor::setupFocusIndicatorColors( + QskAspect::Section section, const QskFluent2Theme& theme ) { + using Q = QskFocusIndicator; + const auto& pal = theme.palette; + + setBoxBorderColors( Q::Panel | section, pal.strokeColor.focus.outer ); } -void Editor::setupListView() +void Editor::setupListViewMetrics() { + using Q = QskListView; + + setBoxBorderMetrics( Q::Cell | Q::Selected, { 3, 0, 0, 0 } ); } -void Editor::setupMenu() +void Editor::setupListViewColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskListView; + using A = QskAspect; + + const auto& pal = theme.palette; + + for ( const auto state1 : { A::NoState, Q::Hovered, Q::Pressed, Q::Disabled } ) + { + QRgb textColor, indicatorColor; + + if ( state1 == Q::Disabled ) + { + textColor = pal.fillColor.text.disabled; + indicatorColor = pal.fillColor.accent.disabled; + } + if ( state1 == Q::Pressed ) + { + textColor = pal.fillColor.text.secondary; + indicatorColor = pal.fillColor.accent.defaultColor; + } + else + { + textColor = pal.fillColor.text.primary; + indicatorColor = pal.fillColor.accent.defaultColor; + } + + for ( const auto state2 : { A::NoState, Q::Selected } ) + { + QRgb cellColor; + + if ( state2 == A::NoState ) + { + if ( state1 == Q::Hovered ) + cellColor = pal.fillColor.subtle.secondary; + else if ( state1 == Q::Pressed ) + cellColor = pal.fillColor.subtle.tertiary; + else + cellColor = Qt::transparent; + } + else + { + if ( state1 == Q::Hovered ) + cellColor = pal.fillColor.subtle.tertiary; + else + cellColor = pal.fillColor.subtle.secondary; + } + + const auto cell = Q::Cell | section | state1 | state2; + const auto text = Q::Text | section | state1 | state2; + + setGradient( cell, cellColor ); + + { + /* + We are using a section of the left border to display a + bar indicating the selection. Maybe we should introduce a + subcontrol instead TODO ... + */ + const auto c1 = cellColor; + const auto c2 = indicatorColor; + + const auto p1 = ( state1 == Q::Pressed ) ? 0.33 : 0.25; + const auto p2 = 1.0 - p1; + + setBoxBorderColors( cell, + QskGradient( { { p1, c1 }, { p1, c2 }, { p2, c2 }, { p2, c1 } } ) ); + } + + setColor( text, textColor ); + } + } +} + +void Editor::setupMenuMetrics() { using Q = QskMenu; - const auto& pal = theme.palette; setPadding( Q::Panel, { 4, 6, 4, 6 } ); setBoxBorderMetrics( Q::Panel, 1 ); - setBoxBorderColors( Q::Panel, pal.strokeColor.surface.flyout ); setBoxShape( Q::Panel, 7 ); - setGradient( Q::Panel, pal.background.flyout.defaultColor ); - setShadowMetrics( Q::Panel, theme.shadow.flyout.metrics ); - setShadowColor( Q::Panel, theme.shadow.flyout.color ); setPadding( Q::Segment, { 0, 10, 0, 10 } ); setSpacing( Q::Segment, 15 ); - - setGradient( Q::Segment | Q::Selected, pal.fillColor.subtle.secondary ); setBoxBorderMetrics( Q::Segment | Q::Selected, { 3, 0, 0, 0 } ); - QskGradient selectedGradient( { { 0.0, pal.fillColor.subtle.secondary }, - { 0.25, pal.fillColor.subtle.secondary }, - { 0.25, pal.fillColor.accent.defaultColor }, - { 0.75, pal.fillColor.accent.defaultColor }, - { 0.75, pal.fillColor.subtle.secondary }, - { 1.0, pal.fillColor.subtle.secondary } } ); - setBoxBorderColors( Q::Segment | Q::Selected, selectedGradient ); - setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.fillColor.text.primary ); setStrutSize( Q::Icon, 12, 12 ); setPadding( Q::Icon, { 8, 8, 0, 8 } ); +} + +void Editor::setupMenuColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + Q_UNUSED( section ); + + using Q = QskMenu; + +#if 1 + setShadowMetrics( Q::Panel, theme.shadow.flyout.metrics ); +#endif + + const auto& pal = theme.palette; + + setBoxBorderColors( Q::Panel, pal.strokeColor.surface.flyout ); + setGradient( Q::Panel, pal.background.flyout.defaultColor ); + setShadowColor( Q::Panel, theme.shadow.flyout.color ); + + setGradient( Q::Segment | Q::Selected, pal.fillColor.subtle.secondary ); + + /* + We are using a section of the left border to display a + bar indicating the selection. Maybe we should introduce a + subcontrol instead TODO ... + */ + const auto c1 = pal.fillColor.subtle.secondary; + const auto c2 = pal.fillColor.accent.defaultColor; + + setBoxBorderColors( Q::Segment | Q::Selected, + QskGradient( { { 0.25, c1 }, { 0.25, c2 }, { 0.75, c2 }, { 0.75, c1 } } ) ); + + setColor( Q::Text, pal.fillColor.text.primary ); + setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary ); } -void Editor::setupPageIndicator() +void Editor::setupPageIndicatorMetrics() { + using Q = QskPageIndicator; + using A = QskAspect; + + setPadding( Q::Panel, 5 ); + setSpacing( Q::Panel, 6 ); + + // circles, without border + + setBoxShape( Q::Bullet, 100, Qt::RelativeSize ); + setBoxBorderMetrics( Q::Bullet, 0 ); + + /* + Pressed/Hovered are not yet implemented. + Sizes would be: + + - Q::Pressed : 3 + - Q::Pressed | Q::Selected : 5 + - Q::Hovered : 5 + - Q::Hovered | Q::Selected : 7 + */ + + setStrutSize( Q::Bullet, 6, 6 ); + + /* + Using the margin to adjust sizes is a weired type of implementation. + Needs to be changed TODO ... + */ + for ( auto state : { A::NoState, Q::Disabled } ) + { + setMargin( Q::Bullet | state | Q::Selected, 0 ); + setMargin( Q::Bullet | state, 1 ); + } } -void Editor::setupPopup() +void Editor::setupPageIndicatorColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskPageIndicator; + using A = QskAspect; + + const auto& pal = theme.palette; + + setGradient( Q::Panel, QskGradient() ); + + // Pressed/Hovered are missing - color for both would be pal.fillColor.text.secondary + + for ( const auto state : { A::NoState, Q::Disabled } ) + { + const auto color = ( state == A::NoState ) + ? pal.fillColor.controlStrong.defaultColor + : pal.fillColor.controlStrong.disabled; + + const auto bullet = Q::Bullet | state | section; + + setGradient( bullet, color ); + setGradient( bullet | Q::Selected, color ); + } +} + +void Editor::setupPopup( const QskFluent2Theme& theme ) { using Q = QskPopup; + const auto& pal = theme.palette; setGradient( Q::Overlay, pal.background.overlay.defaultColor ); } -void Editor::setupProgressBar() +void Editor::setupProgressBarMetrics() { using Q = QskProgressBar; using A = QskAspect; - const auto& pal = theme.palette; setMetric( Q::Groove | A::Size, 1 ); setBoxShape( Q::Groove, 100, Qt::RelativeSize ); - setGradient( Q::Groove, pal.strokeColor.controlStrong.defaultColor ); - setMetric( Q::Bar| A::Size, 3 ); + setMetric( Q::Bar | A::Size, 3 ); setBoxShape( Q::Bar, 100, Qt::RelativeSize ); - setGradient( Q::Bar, pal.fillColor.accent.defaultColor ); } -void Editor::setupPushButton() +void Editor::setupProgressBarColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskProgressBar; + + const auto& pal = theme.palette; + + setGradient( Q::Groove | section, pal.strokeColor.controlStrong.defaultColor ); + setGradient( Q::Bar | section, pal.fillColor.accent.defaultColor ); +} + +void Editor::setupPushButtonMetrics() { using Q = QskPushButton; using W = QskFluent2Skin; - const auto& pal = theme.palette; setStrutSize( Q::Panel, { 120, 32 } ); setBoxShape( Q::Panel, 4 ); setBoxBorderMetrics( Q::Panel, 1 ); + setBoxBorderMetrics( Q::Panel | W::Accent | Q::Disabled, 0 ); // Fluent buttons don't really have icons, - // but for the sake of compatibility with the - // gallery app, let's define their style here as well: + setStrutSize( Q::Icon, 12, 12 ); setPadding( Q::Icon, { 0, 0, 8, 0 } ); - setFontRole( Q::Text, QskFluent2Skin::Body ); - - // Accent buttons: - - setBoxBorderGradient( Q::Panel | W::Accent, pal.elevation.accentControl.border, - pal.fillColor.accent.defaultColor ); - - setGradient( Q::Panel | W::Accent, pal.fillColor.accent.defaultColor ); - setColor( Q::Text | W::Accent, pal.fillColor.textOnAccent.primary ); - setGraphicRole( Q::Icon | W::Accent, QskFluent2Skin::GraphicRoleFillColorTextOnAccentPrimary ); - - - setBoxBorderGradient( Q::Panel | W::Accent | Q::Hovered, pal.elevation.accentControl.border, - pal.fillColor.accent.secondary ); - - - setGradient( Q::Panel | W::Accent | Q::Hovered, pal.fillColor.accent.secondary ); - - - setGradient( Q::Panel | W::Accent | Q::Pressed, pal.fillColor.accent.tertiary ); - setColor( Q::Text | W::Accent | Q::Pressed, pal.fillColor.textOnAccent.secondary ); - setGraphicRole( Q::Icon | W::Accent | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextOnAccentSecondary ); - - const QRgb accentPressedBorderColor = flattenedColor( pal.strokeColor.control.onAccentDefault, - pal.fillColor.accent.tertiary ); - - setBoxBorderColors( Q::Panel | W::Accent | Q::Pressed, accentPressedBorderColor ); - - - setGradient( Q::Panel | W::Accent | Q::Disabled, pal.fillColor.accent.disabled ); - setColor( Q::Text | W::Accent | Q::Disabled, pal.fillColor.textOnAccent.disabled ); - setGraphicRole( Q::Icon | W::Accent | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextOnAccentDisabled ); - setBoxBorderMetrics( Q::Panel | W::Accent | Q::Disabled, 0 ); - - - // Standard buttons: - - setBoxBorderGradient( Q::Panel, pal.elevation.control.border, - pal.fillColor.control.defaultColor ); - - - setGradient( Q::Panel, pal.fillColor.control.defaultColor ); - setColor( Q::Text, pal.fillColor.text.primary ); - setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary ); - - - setBoxBorderGradient( Q::Panel | Q::Hovered, pal.elevation.control.border, - pal.fillColor.control.secondary ); - - - setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); - - - const QRgb standardPressedBorderColor = flattenedColor( pal.strokeColor.control.defaultColor, - pal.fillColor.control.tertiary ); - - setBoxBorderColors( Q::Panel | Q::Pressed, standardPressedBorderColor ); - - setGradient( Q::Panel | Q::Pressed, pal.fillColor.control.tertiary ); - setColor( Q::Text | Q::Pressed, pal.fillColor.text.secondary ); - setGraphicRole( Q::Icon | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextSecondary ); - - - const QRgb standardDisabledBorderColor = flattenedColor( pal.strokeColor.control.defaultColor, - pal.fillColor.control.disabled ); - - setBoxBorderColors( Q::Panel | Q::Disabled, standardDisabledBorderColor ); - - setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); - setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); - setGraphicRole( Q::Icon | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); + setFontRole( Q::Text, W::Body ); } -void Editor::setupRadioBox() +void Editor::setupPushButtonColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskPushButton; + using W = QskFluent2Skin; + + const auto& pal = theme.palette; + + for ( const auto variation : { QskAspect::NoVariation, W::Accent } ) + { + const auto panel = Q::Panel | section | variation; + const auto text = Q::Text | section | variation; + const auto icon = Q::Icon | section | variation; + + for ( const auto state : { QskAspect::NoState, Q::Hovered, Q::Pressed, Q::Disabled } ) + { + QRgb panelColor, borderColor1, borderColor2, textColor; + int graphicRole; + + if ( variation == W::Accent ) + { + if ( state == Q::Hovered ) + { + panelColor = pal.fillColor.accent.secondary; + borderColor1 = pal.elevation.accentControl.border[0]; + borderColor2 = pal.elevation.accentControl.border[1]; + textColor = pal.fillColor.textOnAccent.primary; + graphicRole = W::GraphicRoleFillColorTextOnAccentPrimary; + } + else if ( state == Q::Pressed ) + { + panelColor = pal.fillColor.accent.tertiary; + borderColor1 = borderColor2 = pal.strokeColor.control.onAccentDefault; + textColor = pal.fillColor.textOnAccent.secondary; + graphicRole = W::GraphicRoleFillColorTextOnAccentSecondary; + } + else if ( state == Q::Disabled ) + { + panelColor = pal.fillColor.accent.disabled; + borderColor1 = borderColor2 = panelColor; // irrelevant: width is 0 + textColor = pal.fillColor.textOnAccent.disabled; + graphicRole = W::GraphicRoleFillColorTextOnAccentDisabled; + } + else + { + panelColor = pal.fillColor.accent.defaultColor; + borderColor1 = pal.elevation.accentControl.border[0]; + borderColor2 = pal.elevation.accentControl.border[1]; + textColor = pal.fillColor.textOnAccent.primary; + graphicRole = W::GraphicRoleFillColorTextOnAccentPrimary; + } + } + else + { + if ( state == Q::Hovered ) + { + panelColor = pal.fillColor.control.secondary; + borderColor1 = pal.elevation.control.border[0]; + borderColor2 = pal.elevation.control.border[1]; + textColor = pal.fillColor.text.primary; + graphicRole = W::GraphicRoleFillColorTextPrimary; + } + else if ( state == Q::Pressed ) + { + panelColor = pal.fillColor.control.tertiary; + borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor; + textColor = pal.fillColor.text.secondary; + graphicRole = W::GraphicRoleFillColorTextSecondary; + } + else if ( state == Q::Disabled ) + { + panelColor = pal.fillColor.control.disabled; + borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor; + textColor = pal.fillColor.text.disabled; + graphicRole = W::GraphicRoleFillColorTextDisabled; + } + else + { + panelColor = pal.fillColor.control.defaultColor; + borderColor1 = pal.elevation.control.border[0]; + borderColor2 = pal.elevation.control.border[0]; + textColor = pal.fillColor.text.primary; + graphicRole = W::GraphicRoleFillColorTextPrimary; + } + } + + panelColor = rgbSolid( panelColor, pal.background.solid.base ); + + setGradient( panel | state, panelColor ); + + setBoxBorderGradient( panel | state, + borderColor1, borderColor2, panelColor ); + + setColor( text | state, textColor ); + setGraphicRole( icon | state, graphicRole ); + } + } +} + +void Editor::setupRadioBoxMetrics() { using Q = QskRadioBox; - const auto& pal = theme.palette; setSpacing( Q::Button, 8 ); setStrutSize( Q::Button, { 115, 38 } ); - setStrutSize( Q::CheckIndicatorPanel, { 20, 20 } ); + /* + We do not have an indicator - states are indicated by the panel border + + However the colors of the inner side of the border are not solid for + the selected states and we use a dummy indicator to get this done. + + How to solve this in a better way, TODO ... + */ + + setBoxShape( Q::CheckIndicator, 100, Qt::RelativeSize ); + setBoxBorderMetrics( Q::CheckIndicator, 0 ); + setBoxBorderMetrics( Q::CheckIndicator | Q::Selected, 1 ); + setBoxBorderMetrics( Q::CheckIndicator | Q::Pressed | Q::Selected, 1 ); + setBoxShape( Q::CheckIndicatorPanel, 100, Qt::RelativeSize ); + setStrutSize( Q::CheckIndicatorPanel, { 20, 20 } ); + setBoxBorderMetrics( Q::CheckIndicatorPanel, 1 ); - setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.fillColor.text.primary ); - // Rest - - setGradient( Q::CheckIndicatorPanel, pal.fillColor.controlAlt.secondary ); - setBoxBorderColors( Q::CheckIndicatorPanel, pal.strokeColor.controlStrong.defaultColor ); - - setGradient( Q::CheckIndicatorPanel | Q::Selected, pal.fillColor.accent.defaultColor ); setBoxBorderMetrics( Q::CheckIndicatorPanel | Q::Selected, 0 ); - setPadding( Q::CheckIndicatorPanel | Q::Selected, { 5, 5 } ); // indicator "strut size" - setBoxShape( Q::CheckIndicator | Q::Selected, 100, Qt::RelativeSize ); - setBoxBorderMetrics( Q::CheckIndicator | Q::Selected, 1 ); - setGradient( Q::CheckIndicator | Q::Selected, pal.fillColor.textOnAccent.primary ); - - setBoxBorderGradient( Q::CheckIndicator | Q::Selected, pal.elevation.circle.border, - pal.fillColor.accent.defaultColor ); - - - // Hover - - setGradient( Q::CheckIndicatorPanel | Q::Hovered, pal.fillColor.controlAlt.tertiary ); - - setGradient( Q::CheckIndicatorPanel | Q::Hovered | Q::Selected, pal.fillColor.accent.secondary ); setPadding( Q::CheckIndicatorPanel | Q::Hovered | Q::Selected, { 4, 4 } ); // indicator "strut size" - - setBoxBorderGradient( Q::CheckIndicator | Q::Hovered, pal.elevation.circle.border, - pal.fillColor.accent.secondary ); - - // Pressed - - setGradient( Q::CheckIndicatorPanel | Q::Pressed, pal.fillColor.controlAlt.quaternary ); - setBoxBorderColors( Q::CheckIndicatorPanel | Q::Pressed, pal.strokeColor.controlStrong.disabled ); - setPadding( Q::CheckIndicatorPanel | Q::Pressed, { 7, 7 } ); // indicator "strut size" - setBoxShape( Q::CheckIndicator | Q::Pressed, 100, Qt::RelativeSize ); - setBoxBorderMetrics( Q::CheckIndicator | Q::Pressed, 0 ); - setGradient( Q::CheckIndicator | Q::Pressed, pal.fillColor.textOnAccent.primary ); - - setGradient( Q::CheckIndicatorPanel | Q::Pressed | Q::Selected, pal.fillColor.accent.tertiary ); setBoxBorderMetrics( Q::CheckIndicatorPanel | Q::Pressed | Q::Selected, 0 ); - setPadding( Q::CheckIndicatorPanel | Q::Pressed | Q::Selected, { 6, 6 } ); // indicator "strut size" - setBoxBorderMetrics( Q::CheckIndicator | Q::Pressed, 1 ); - setBoxBorderGradient( Q::CheckIndicator | Q::Pressed | Q::Selected, pal.elevation.circle.border, - pal.fillColor.accent.tertiary ); - - // Disabled - - setGradient( Q::CheckIndicatorPanel | Q::Disabled, pal.fillColor.controlAlt.disabled ); - setBoxBorderColors( Q::CheckIndicatorPanel | Q::Disabled, pal.strokeColor.controlStrong.disabled ); - - setGradient( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, pal.fillColor.accent.disabled ); setBoxBorderMetrics( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, 0 ); - setPadding( Q::CheckIndicatorPanel | Q::Disabled | Q::Selected, { 6, 6 } ); // indicator "strut size" - setBoxBorderMetrics( Q::CheckIndicator | Q::Disabled | Q::Selected, 0 ); - setGradient( Q::CheckIndicator | Q::Disabled | Q::Selected, pal.fillColor.textOnAccent.primary ); - setBoxShape( Q::CheckIndicator | Q::Disabled | Q::Selected, 100, Qt::RelativeSize ); - - setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); + setFontRole( Q::Text, QskFluent2Skin::Body ); } -void Editor::setupScrollView() +void Editor::setupRadioBoxColors( + QskAspect::Section section, const QskFluent2Theme& theme ) { + using Q = QskRadioBox; + using A = QskAspect; + + const auto& pal = theme.palette; + + for ( const auto state1 : { A::NoState, Q::Hovered, Q::Pressed, Q::Disabled } ) + { + for ( const auto state2 : { A::NoState, Q::Selected } ) + { + const auto states = state1 | state2; + + auto indicatorColor = pal.fillColor.textOnAccent.primary; + if ( !( states & Q::Selected ) ) + indicatorColor = QskRgb::toTransparent( indicatorColor, 0 ); + + auto textColor = pal.fillColor.text.primary; + if ( states & Q::Disabled ) + textColor = pal.fillColor.text.disabled; + + QRgb panelBorderColor; + if ( states & ( Q::Disabled | Q::Pressed ) ) + panelBorderColor = pal.strokeColor.controlStrong.disabled; + else + panelBorderColor = pal.strokeColor.controlStrong.defaultColor; + + auto panelColor = pal.fillColor.accent.defaultColor; + + if ( states == A::NoState ) + { + panelColor = pal.fillColor.controlAlt.secondary; + } + else if ( states == Q::Selected ) + { + } + else if ( states == Q::Hovered ) + { + panelColor = pal.fillColor.controlAlt.tertiary; + } + else if ( states == ( Q::Hovered | Q::Selected ) ) + { + panelColor = pal.fillColor.accent.secondary; + } + else if ( states == Q::Pressed ) + { + panelColor = pal.fillColor.controlAlt.quaternary; + } + else if ( states == ( Q::Pressed | Q::Selected ) ) + { + panelColor = pal.fillColor.accent.tertiary; + } + else if ( states == Q::Disabled ) + { + panelColor = pal.fillColor.controlAlt.disabled; + } + else if ( states == ( Q::Disabled | Q::Selected ) ) + { + panelColor = pal.fillColor.accent.disabled; + } + + const auto panel = Q::CheckIndicatorPanel | section | states; + const auto indicator = Q::CheckIndicator | section | states; + const auto text = Q::Text | section | states; + + +#if 0 + // we have different colors when making colors solid early. TODO ... + panelColor = rgbSolid2( panelColor, pal.background.solid.base ); + indicatorColor = rgbSolid2( indicatorColor, pal.background.solid.base ); +#endif + setBoxBorderGradient( indicator, pal.elevation.circle.border, panelColor ); + + setGradient( panel, panelColor ); + setBoxBorderColors( panel, panelBorderColor ); + + setGradient( indicator, indicatorColor ); + + setColor( text, textColor ); + } + } } -void Editor::setupSegmentedBar() +void Editor::setupScrollViewMetrics() +{ + using A = QskAspect; + using Q = QskScrollView; + + for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) + setMetric( subControl | A::Size, 2 ); + + const auto handleExtent = 40.0; + setStrutSize( Q::HorizontalScrollHandle, handleExtent, 0.0 ); + setStrutSize( Q::VerticalScrollHandle, 0.0, handleExtent ); +} + +void Editor::setupScrollViewColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskScrollView; + + const auto& pal = theme.palette; + +#if 1 + setGradient( Q::Panel, QColor() ); + setGradient( Q::Viewport, QColor() ); +#endif + + for ( auto subControl : { Q::HorizontalScrollHandle, Q::VerticalScrollHandle } ) + { + setGradient( subControl | section, pal.fillColor.controlStrong.defaultColor ); + } +} + +void Editor::setupSegmentedBarMetrics() { using Q = QskSegmentedBar; using A = QskAspect; - const auto& pal = theme.palette; const QSizeF segmentStrutSize( 120, 32 ); setBoxBorderMetrics( Q::Panel, 1 ); - - setBoxBorderGradient( Q::Panel, pal.elevation.control.border, - pal.fillColor.control.defaultColor ); - - setGradient( Q::Panel, pal.fillColor.control.defaultColor ); + setBoxBorderMetrics( Q::Panel | Q::Selected | Q::Disabled, 0 ); setSpacing( Q::Panel, 8 ); setStrutSize( Q::Icon, { 12, 12 } ); - setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.fillColor.text.primary ); setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize ); setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() ); - setBoxShape( Q::Segment , 4 ); + setBoxShape( Q::Segment, 4 ); setPadding( Q::Segment, { 8, 0, 8, 0 } ); - - // Hovered: - setGradient( Q::Segment | Q::Hovered, pal.fillColor.control.secondary ); - - setBoxBorderGradient( Q::Segment | Q::Hovered, pal.elevation.control.border, - pal.fillColor.control.secondary ); - - // Selected: - setGradient( Q::Segment | Q::Selected, pal.fillColor.accent.defaultColor ); - setGraphicRole( Q::Icon | Q::Selected, QskFluent2Skin::GraphicRoleFillColorTextOnAccentPrimary ); - setColor( Q::Text | Q::Selected, pal.fillColor.textOnAccent.primary ); - - // Disabled: - const QRgb standardDisabledBorderColor = flattenedColor( pal.strokeColor.control.defaultColor, - pal.fillColor.control.disabled ); - - setBoxBorderColors( Q::Segment | Q::Disabled, standardDisabledBorderColor ); - - setGradient( Q::Segment | Q::Disabled, pal.fillColor.control.disabled ); - setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); - setGraphicRole( Q::Icon | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); - - - setGradient( Q::Segment | Q::Selected | Q::Disabled, pal.fillColor.accent.disabled ); - setColor( Q::Text | Q::Selected | Q::Disabled, pal.fillColor.textOnAccent.disabled ); - setGraphicRole( Q::Icon | Q::Selected | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextOnAccentDisabled ); - setBoxBorderMetrics( Q::Panel | Q::Selected | Q::Disabled, 0 ); - } -void Editor::setupSeparator() +void Editor::setupSegmentedBarColors( + QskAspect::Section section, const QskFluent2Theme& theme ) { + using Q = QskSegmentedBar; using A = QskAspect; - using Q = QskSeparator; + using W = QskFluent2Skin; const auto& pal = theme.palette; - for ( auto variation : { A::Horizontal, A::Vertical } ) - { - const auto aspect = Q::Panel | variation; + auto panelColor = pal.fillColor.control.defaultColor; + panelColor = rgbSolid( panelColor, pal.background.solid.base ); - setMetric( aspect | A::Size, 1 ); - setBoxShape( Q::Panel, 0 ); - setBoxBorderMetrics( Q::Panel, 0 ); - setGradient( aspect, pal.strokeColor.divider.defaultColor ); + setGradient( Q::Panel, panelColor ); + + for ( const auto state1 : { A::NoState, Q::Hovered, Q::Disabled } ) + { + for ( const auto state2 : { A::NoState, Q::Selected } ) + { + const auto states = state1 | state2; + + QRgb segmentColor, borderColor1, borderColor2, textColor; + int graphicRole; + + if ( states == A::NoState ) + { + segmentColor = pal.fillColor.control.defaultColor; + borderColor1 = pal.elevation.control.border[0]; + borderColor2 = pal.elevation.control.border[1]; + textColor = pal.fillColor.text.primary; + + graphicRole = W::GraphicRoleFillColorTextPrimary; + } + else if ( states & Q::Hovered ) + { + segmentColor = pal.fillColor.control.secondary; + borderColor1 = pal.elevation.control.border[0]; + borderColor2 = pal.elevation.control.border[1]; + textColor = pal.fillColor.text.primary; + + graphicRole = W::GraphicRoleFillColorTextPrimary; + } + else if ( states == ( Q::Selected | Q::Disabled ) ) + { + segmentColor = pal.fillColor.accent.disabled; + borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor; + textColor = pal.fillColor.textOnAccent.disabled; + + graphicRole = W::GraphicRoleFillColorTextOnAccentDisabled; + } + else if ( states & Q::Selected ) + { + segmentColor = pal.fillColor.accent.defaultColor; + borderColor1 = pal.elevation.control.border[0]; + borderColor2 = pal.elevation.control.border[1]; + textColor = pal.fillColor.textOnAccent.primary; + + graphicRole = W::GraphicRoleFillColorTextOnAccentPrimary; + } + else if ( states == Q::Disabled ) + { + segmentColor = pal.fillColor.control.disabled; + borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor; + textColor = pal.fillColor.text.disabled; + graphicRole = W::GraphicRoleFillColorTextDisabled; + } + + const auto segment = Q::Segment | section | states; + const auto text = Q::Text | section | states; + const auto icon = Q::Icon | section | states; + + segmentColor = rgbSolid( segmentColor, pal.background.solid.base ); + + setGradient( segment, segmentColor ); + setBoxBorderGradient( segment, borderColor1, borderColor2, panelColor ); + + setColor( text, textColor ); + + setGraphicRole( icon, graphicRole ); + } } } -void Editor::setupSlider() +void Editor::setupSeparatorMetrics() +{ + using Q = QskSeparator; + using A = QskAspect; + + setMetric( Q::Panel | A::Size, 1 ); + setBoxShape( Q::Panel, 0 ); + setBoxBorderMetrics( Q::Panel, 0 ); +} + +void Editor::setupSeparatorColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskSeparator; + + const auto& pal = theme.palette; + setGradient( Q::Panel | section, pal.strokeColor.divider.defaultColor ); +} + +void Editor::setupSliderMetrics() { using Q = QskSlider; using A = QskAspect; - const auto& pal = theme.palette; const qreal extent = 22; setMetric( Q::Panel | A::Size, extent ); setBoxShape( Q::Panel, 0 ); setBoxBorderMetrics( Q::Panel, 0 ); - setGradient( Q::Panel, {} ); setPadding( Q::Panel | A::Horizontal, QskMargins( 0.5 * extent, 0 ) ); setPadding( Q::Panel | A::Vertical, QskMargins( 0, 0.5 * extent ) ); setMetric( Q::Groove | A::Size, 4 ); - setGradient( Q::Groove, pal.fillColor.controlStrong.defaultColor ); setBoxShape( Q::Groove, 100, Qt::RelativeSize ); setMetric( Q::Fill | A::Size, 4 ); - setGradient( Q::Fill, pal.fillColor.accent.defaultColor ); setBoxShape( Q::Fill, 100, Qt::RelativeSize ); setStrutSize( Q::Handle, { 22, 22 } ); - setGradient( Q::Handle, pal.fillColor.controlSolid.defaultColor ); setBoxShape( Q::Handle, 100, Qt::RelativeSize ); setBoxBorderMetrics( Q::Handle, 1 ); - setBoxBorderGradient( Q::Handle, pal.elevation.circle.border, pal.fillColor.controlSolid.defaultColor ); setStrutSize( Q::Ripple, { 12, 12 } ); - setGradient( Q::Ripple, pal.fillColor.accent.defaultColor ); setBoxShape( Q::Ripple, 100, Qt::RelativeSize ); setStrutSize( Q::Ripple | Q::Hovered, { 14, 14 } ); setStrutSize( Q::Ripple | Q::Pressed, { 10, 10 } ); - setGradient( Q::Ripple | Q::Pressed, pal.fillColor.accent.tertiary ); - - setGradient( Q::Groove | Q::Disabled, pal.fillColor.controlStrong.disabled ); - setGradient( Q::Fill | Q::Disabled, pal.fillColor.accent.disabled ); - setGradient( Q::Ripple | Q::Disabled, pal.fillColor.controlStrong.disabled ); } -void Editor::setupSpinBox() +void Editor::setupSliderColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskSlider; + using A = QskAspect; + + const auto& pal = theme.palette; + + { + const auto handleColor = pal.fillColor.controlSolid.defaultColor; + + setGradient( Q::Handle, handleColor ); + setBoxBorderGradient( Q::Handle, pal.elevation.circle.border, handleColor ); + } + + for ( auto state : { A::NoState , Q::Pressed , Q::Disabled } ) + { + QRgb grooveColor, fillColor, rippleColor; + + if ( state == A::NoState ) + { + grooveColor = pal.fillColor.controlStrong.defaultColor; + fillColor = pal.fillColor.accent.defaultColor; + rippleColor = fillColor; + } + else if ( state == Q::Pressed ) + { + grooveColor = pal.fillColor.controlStrong.defaultColor; + fillColor = pal.fillColor.accent.defaultColor; + rippleColor = pal.fillColor.accent.tertiary; + } + else if ( state == Q::Disabled ) + { + grooveColor = pal.fillColor.controlStrong.disabled; + fillColor = pal.fillColor.accent.disabled; + rippleColor = grooveColor; + } + + grooveColor = rgbSolid( grooveColor, pal.background.solid.base ); + + setGradient( Q::Groove | section | state, grooveColor ); + setGradient( Q::Fill | section | state, fillColor ); + setGradient( Q::Ripple | section | state, rippleColor ); + } +} + +void Editor::setupSpinBoxMetrics() { using Q = QskSpinBox; - const auto& pal = theme.palette; setHint( Q::Panel | QskAspect::Style, Q::ButtonsRight ); setStrutSize( Q::Panel, { -1, 32 } ); @@ -683,19 +1312,11 @@ void Editor::setupSpinBox() setBoxShape( Q::Panel, 3 ); setPadding( Q::Panel, { 11, 0, 11, 0 } ); - setGradient( Q::Panel, pal.fillColor.control.defaultColor ); - setBoxBorderGradient( Q::Panel, pal.elevation.control.border, - pal.fillColor.control.defaultColor ); - setAlignment( Q::Text, Qt::AlignLeft ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.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 } ); @@ -705,213 +1326,407 @@ void Editor::setupSpinBox() setSymbol( Q::UpIndicator, symbol( "spin-box-arrow-up" ) ); setSymbol( Q::DownIndicator, symbol( "spin-box-arrow-down" ) ); - setGraphicRole( Q::UpIndicator, QskFluent2Skin::GraphicRoleFillColorTextSecondary ); - setGraphicRole( Q::DownIndicator, QskFluent2Skin::GraphicRoleFillColorTextSecondary ); - - // Hovered: - - setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); - setBoxBorderGradient( Q::Panel | Q::Hovered, pal.elevation.textControl.border, - pal.fillColor.control.secondary ); - - // Focused (Pressed doesn't exist yet): - setBoxBorderMetrics( Q::Panel | Q::Focused, { 1, 1, 1, 2 } ); - - setGradient( Q::Panel | Q::Focused, pal.fillColor.control.inputActive ); - - auto gradient = pal.elevation.textControl.border; - gradient.at( 1 ) = pal.fillColor.accent.defaultColor; - - setBoxBorderGradient( Q::Panel | Q::Focused, gradient, pal.fillColor.control.inputActive ); - - // Disabled: - - setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.control.defaultColor ); - - setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); - - setGraphicRole( Q::UpIndicator | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); - setGraphicRole( Q::DownIndicator | Q::Disabled, QskFluent2Skin::GraphicRoleFillColorTextDisabled ); } -void Editor::setupTabBar() +void Editor::setupSpinBoxColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskSpinBox; + using A = QskAspect; + + const auto& pal = theme.palette; + + for ( auto state : { A::NoState, Q::Hovered, Q::Focused, Q::Disabled } ) + { + QRgb panelColor, borderColor1, borderColor2; + + if ( state == A::NoState ) + { + panelColor = pal.fillColor.control.defaultColor; + borderColor1 = pal.elevation.control.border[0]; + borderColor2 = pal.elevation.control.border[1]; + } + else if ( state == Q::Hovered ) + { + panelColor = pal.fillColor.control.secondary; + borderColor1 = pal.elevation.textControl.border[0]; + borderColor2 = pal.elevation.textControl.border[1]; + } + else if ( state == Q::Focused ) + { + // Focused (Pressed doesn't exist yet): + + panelColor = pal.fillColor.control.inputActive; + borderColor1 = pal.elevation.textControl.border[0]; + borderColor2 = pal.fillColor.accent.defaultColor; + } + else if ( state == Q::Disabled ) + { + panelColor = pal.fillColor.control.disabled; + borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor; + } + + QRgb textColor; + int graphicRole; + + if ( state != Q::Disabled ) + { + textColor = pal.fillColor.text.primary; + graphicRole = QskFluent2Skin::GraphicRoleFillColorTextSecondary; + } + else + { + textColor = pal.fillColor.text.disabled; + graphicRole = QskFluent2Skin::GraphicRoleFillColorTextDisabled; + } + + const auto panel = Q::Panel | section | state; + const auto text = Q::Text | section | state; + const auto upIndicator = Q::UpIndicator | section | state; + const auto downIndicator = Q::DownIndicator | section | state; + + panelColor = rgbSolid( panelColor, pal.background.solid.base ); + + setGradient( panel, panelColor ); + setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor ); + + setColor( text, textColor ); + + setGraphicRole( upIndicator, graphicRole ); + setGraphicRole( downIndicator, graphicRole ); + } +} + +void Editor::setupTabBarMetrics() { } -void Editor::setupTabButton() +void Editor::setupTabBarColors( QskAspect::Section section, const QskFluent2Theme& theme ) +{ + setGradient( QskTabBar::Panel | section, theme.palette.background.solid.base ); +} + +void Editor::setupTabButtonMetrics() { using Q = QskTabButton; - const auto& pal = theme.palette; setStrutSize( Q::Panel, { -1, 31 } ); setPadding( Q::Panel, { 7, 0, 7, 0 } ); setBoxShape( Q::Panel, { 7, 7, 0, 0 } ); - setGradient( Q::Panel, Qt::transparent ); - setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1 } ); - setBoxBorderColors( Q::Panel, pal.strokeColor.card.defaultColor ); - - setGradient( Q::Panel | Q::Checked, pal.background.solid.tertiary ); - setBoxBorderMetrics( Q::Panel | Q::Checked, { 1, 1, 1, 0 } ); - setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter ); + setBoxBorderMetrics( Q::Panel, { 0, 0, 0, 1 } ); + setBoxBorderMetrics( Q::Panel | Q::Checked, { 1, 1, 1, 0 } ); + setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.fillColor.text.secondary ); - setFontRole( Q::Text | Q::Checked, QskFluent2Skin::BodyStrong ); - setColor( Q::Text | Q::Checked, pal.fillColor.text.primary ); - - setGradient( Q::Panel | Q::Hovered, pal.fillColor.subtle.secondary ); - - setGradient( Q::Panel | Q::Pressed, pal.fillColor.subtle.tertiary ); } -void Editor::setupTabView() +void Editor::setupTabButtonColors( + QskAspect::Section section, const QskFluent2Theme& theme ) { - using Q = QskTabView; + using Q = QskTabButton; const auto& pal = theme.palette; - setGradient( Q::Page, pal.background.solid.tertiary ); + for ( const auto state : { QskAspect::NoState, + Q::Checked, Q::Hovered, Q::Pressed, Q::Disabled } ) + { + QRgb panelColor, textColor; + + if ( state == Q::Checked ) + { + panelColor = pal.background.solid.secondary; + textColor = pal.fillColor.text.primary; + } + else if ( state == Q::Hovered ) + { + panelColor = pal.fillColor.subtle.secondary; + textColor = pal.fillColor.text.secondary; + } + else if ( state == Q::Pressed ) + { + panelColor = pal.fillColor.subtle.tertiary; + textColor = pal.fillColor.text.secondary; + } + else if ( state == Q::Disabled ) + { + panelColor = pal.fillColor.control.disabled; + textColor = pal.fillColor.text.disabled; + } + else + { + panelColor = pal.fillColor.subtle.tertiary; + textColor = pal.fillColor.text.secondary; + } + + const auto panel = Q::Panel | section | state; + const auto text = Q::Text | section | state; + + panelColor = rgbSolid( panelColor, pal.background.solid.base ); + setGradient( panel, panelColor ); + + const auto borderColor = rgbSolid( + pal.strokeColor.card.defaultColor, pal.background.solid.base ); + + setBoxBorderColors( panel, borderColor ); + + setColor( text, textColor ); + } } -void Editor::setupTextLabel() +void Editor::setupTabViewMetrics() +{ +} + +void Editor::setupTabViewColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskTabView; + setGradient( Q::Page | section, theme.palette.background.solid.secondary ); +} + +void Editor::setupGraphicLabelMetrics() +{ + using Q = QskGraphicLabel; + + setPadding( Q::Panel, 10 ); + setBoxShape( Q::Panel, 3 ); + setBoxBorderMetrics( Q::Panel, 1 ); +} + +void Editor::setupGraphicLabelColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskGraphicLabel; + const auto& pal = theme.palette; + +#if 1 + setColor( Q::Panel | section, pal.fillColor.subtle.secondary ); + setBoxBorderColors( Q::Panel | section, pal.strokeColor.control.defaultColor ); +#endif +} + +void Editor::setupTextLabelMetrics() +{ + using Q = QskTextLabel; + + setPadding( Q::Panel, 10 ); + setBoxShape( Q::Panel, 3 ); + setBoxBorderMetrics( Q::Panel, 1 ); + + setFontRole( Q::Text, QskFluent2Skin::Body ); +} + +void Editor::setupTextLabelColors( + QskAspect::Section section, const QskFluent2Theme& theme ) { using Q = QskTextLabel; const auto& pal = theme.palette; - setPadding( Q::Panel, 10 ); - - setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.fillColor.text.primary ); +#if 1 + setColor( Q::Panel | section, pal.fillColor.subtle.secondary ); + setBoxBorderColors( Q::Panel | section, pal.strokeColor.control.defaultColor ); +#endif + setColor( Q::Text | section, pal.fillColor.text.primary ); } - -void Editor::setupTextInput() +void Editor::setupTextInputMetrics() { using Q = QskTextInput; - const auto& pal = theme.palette; setStrutSize( Q::Panel, { -1, 30 } ); - setBoxBorderMetrics( Q::Panel, 1 ); - setBoxShape( Q::Panel, 3 ); setPadding( Q::Panel, { 11, 0, 11, 0 } ); + setBoxBorderMetrics( Q::Panel, 1 ); + for( const auto& state : { Q::Focused, Q::Editing } ) + setBoxBorderMetrics( Q::Panel | state, { 1, 1, 1, 2 } ); + + setBoxShape( Q::Panel, 3 ); + setAlignment( Q::Text, Qt::AlignLeft | Qt::AlignVCenter ); setFontRole( Q::Text, QskFluent2Skin::Body ); - setColor( Q::Text, pal.fillColor.text.secondary ); +} - setGradient( Q::Panel, pal.fillColor.control.defaultColor ); - setBoxBorderGradient( Q::Panel, pal.elevation.textControl.border, - pal.fillColor.control.defaultColor ); +void Editor::setupTextInputColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskTextInput; + using A = QskAspect; + + const auto& pal = theme.palette; setColor( Q::PanelSelected, pal.fillColor.accent.selectedTextBackground ); setColor( Q::TextSelected, pal.fillColor.textOnAccent.selectedText ); - // Hovered: - - setGradient( Q::Panel | Q::Hovered, pal.fillColor.control.secondary ); - setBoxBorderGradient( Q::Panel | Q::Hovered, pal.elevation.textControl.border, - pal.fillColor.control.secondary ); - - - // Pressed & Focused: - - for( const auto& state : { Q::Focused, Q::Editing } ) + for( const auto state : { A::NoState, Q::Hovered, Q::Focused, Q::Editing, Q::Disabled } ) { - setBoxBorderMetrics( Q::Panel | state, { 1, 1, 1, 2 } ); + QRgb panelColor, borderColor1, borderColor2, textColor; - setGradient( Q::Panel | state, pal.fillColor.control.inputActive ); + if ( state == A::NoState ) + { + panelColor = pal.fillColor.control.defaultColor; + borderColor1 = pal.elevation.textControl.border[0]; + borderColor2 = pal.elevation.textControl.border[1]; + textColor = pal.fillColor.text.secondary; + } + else if ( state == Q::Disabled ) + { + panelColor = pal.fillColor.control.secondary; + borderColor1 = pal.elevation.textControl.border[0]; + borderColor2 = pal.elevation.textControl.border[1]; + textColor = pal.fillColor.text.secondary; + } + else if ( ( state == Q::Focused ) || ( state == Q::Editing ) ) + { + panelColor = pal.fillColor.control.inputActive; + borderColor1 = pal.elevation.textControl.border[0]; + borderColor2 = pal.fillColor.accent.defaultColor; + textColor = pal.fillColor.text.secondary; + } + else if ( state == Q::Disabled ) + { + panelColor = pal.fillColor.control.disabled; + borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor; + textColor = pal.fillColor.text.disabled; + } - auto gradient = pal.elevation.textControl.border; - gradient.at( 1 ) = pal.fillColor.accent.defaultColor; + const auto panel = Q::Panel | section | state; + const auto text = Q::Text | section | state; - setBoxBorderGradient( Q::Panel | state, gradient, pal.fillColor.control.inputActive ); + panelColor = rgbSolid( panelColor, pal.background.solid.base ); + + setGradient( panel, panelColor ); + setBoxBorderGradient( panel, borderColor1, borderColor2, panelColor ); + + setColor( text, textColor ); } - - // Disabled: - - setGradient( Q::Panel | Q::Disabled, pal.fillColor.control.disabled ); - setBoxBorderColors( Q::Panel | Q::Disabled, pal.strokeColor.control.defaultColor ); - - setColor( Q::Text | Q::Disabled, pal.fillColor.text.disabled ); } -void Editor::setupSwitchButton() +void Editor::setupSwitchButtonMetrics() { using Q = QskSwitchButton; using A = QskAspect; - const auto& pal = theme.palette; const QSizeF strutSize( 38, 18 ); setStrutSize( Q::Groove | A::Horizontal, strutSize ); setStrutSize( Q::Groove | A::Vertical, strutSize.transposed() ); setBoxShape( Q::Groove, 100, Qt::RelativeSize ); + setBoxBorderMetrics( Q::Groove, 1 ); setBoxBorderMetrics( Q::Groove | Q::Checked, 0 ); setBoxShape( Q::Handle, 100, Qt::RelativeSize ); setPosition( Q::Handle, 0.1, { QskStateCombination::CombinationNoState, Q::Disabled } ); - setPosition( Q::Handle | Q::Checked, 0.9, { QskStateCombination::CombinationNoState, Q::Disabled } ); - setAnimation( Q::Handle | A::Metric, 100 ); + setPosition( Q::Handle | Q::Checked, 0.9, + { QskStateCombination::CombinationNoState, Q::Disabled } ); + setBoxBorderMetrics( Q::Handle, 0 ); setBoxBorderMetrics( Q::Handle | Q::Checked, 1 ); - - // ### big size during animation - - setGradient( Q::Groove, pal.fillColor.controlAlt.secondary ); - setGradient( Q::Groove | Q::Checked, pal.fillColor.accent.defaultColor ); - setBoxBorderColors( Q::Groove, pal.strokeColor.controlStrong.defaultColor ); + setBoxBorderMetrics( Q::Handle | Q::Disabled | Q::Checked, 0 ); setStrutSize( Q::Handle, 12, 12 ); - setGradient( Q::Handle, pal.strokeColor.controlStrong.defaultColor ); - setGradient( Q::Handle | Q::Checked, pal.fillColor.textOnAccent.primary ); - setBoxBorderGradient( Q::Handle | Q::Checked, pal.elevation.circle.border, - pal.fillColor.accent.defaultColor ); - - - setGradient( Q::Groove | Q::Hovered, pal.fillColor.controlAlt.tertiary ); - setGradient( Q::Groove | Q::Hovered | Q::Checked, pal.fillColor.accent.secondary ); - setBoxBorderColors( Q::Groove | Q::Hovered, pal.fillColor.text.secondary ); - - setStrutSize( Q::Handle | Q::Hovered, 14, 14, { QskStateCombination::CombinationNoState, Q::Checked } ); - setGradient( Q::Handle | Q::Hovered, pal.fillColor.text.secondary ); - // Handle | Hovered | Checked is the same as in Rest state - - setBoxBorderGradient( Q::Handle | Q::Hovered | Q::Checked, pal.elevation.circle.border, - pal.fillColor.accent.secondary ); - - - setGradient( Q::Groove | Q::Pressed, pal.fillColor.controlAlt.quaternary ); - setGradient( Q::Groove | Q::Pressed | Q::Checked, pal.fillColor.accent.tertiary ); - setBoxBorderColors( Q::Groove | Q::Pressed, pal.strokeColor.controlStrong.defaultColor ); + setStrutSize( Q::Handle | Q::Hovered, 14, 14, + { QskStateCombination::CombinationNoState, Q::Checked } ); const QSizeF pressedSize( 17, 14 ); - setStrutSize( Q::Handle | Q::Pressed | A::Horizontal, pressedSize, { QskStateCombination::CombinationNoState, Q::Checked } ); - setStrutSize( Q::Handle | Q::Pressed | A::Vertical, pressedSize.transposed(), { QskStateCombination::CombinationNoState, Q::Checked } ); - setGradient( Q::Handle | Q::Pressed, pal.strokeColor.controlStrong.defaultColor ); - // Handle | Pressed | Checked is the same as in Rest state - setBoxBorderGradient( Q::Handle | Q::Pressed | Q::Checked, pal.elevation.circle.border, - pal.fillColor.accent.tertiary ); + setStrutSize( Q::Handle | Q::Pressed | A::Horizontal, + pressedSize, { QskStateCombination::CombinationNoState, Q::Checked } ); + setStrutSize( Q::Handle | Q::Pressed | A::Vertical, + pressedSize.transposed(), { QskStateCombination::CombinationNoState, Q::Checked } ); - setGradient( Q::Groove | Q::Disabled, pal.fillColor.controlAlt.disabled ); - setBoxBorderColors( Q::Groove | Q::Disabled, pal.fillColor.text.disabled ); - setGradient( Q::Groove | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); - setBoxBorderColors( Q::Groove | Q::Disabled | Q::Checked, pal.fillColor.accent.disabled ); + setStrutSize( Q::Handle | Q::Disabled, 12, 12, + { QskStateCombination::CombinationNoState, Q::Checked } ); - setStrutSize( Q::Handle | Q::Disabled, 12, 12, { QskStateCombination::CombinationNoState, Q::Checked } ); - setGradient( Q::Handle | Q::Disabled, pal.fillColor.text.disabled ); - setGradient( Q::Handle | Q::Disabled | Q::Checked, pal.fillColor.textOnAccent.disabled ); - setBoxBorderMetrics( Q::Handle | Q::Disabled | Q::Checked, 1 ); + setAnimation( Q::Handle | A::Metric, 100 ); } -void Editor::setupSubWindow() +void Editor::setupSwitchButtonColors( + QskAspect::Section section, const QskFluent2Theme& theme ) +{ + using Q = QskSwitchButton; + using A = QskAspect; + + const auto& pal = theme.palette; + + for ( const auto state1 : { A::NoState, Q::Hovered, Q::Pressed, Q::Disabled } ) + { + for ( const auto state2 : { A::NoState, Q::Checked } ) + { + const auto states = state1 | state2; + + QRgb grooveColor, grooveBorderColor, handleColor; + + if ( states == A::NoState ) + { + grooveColor = pal.fillColor.controlAlt.secondary; + grooveBorderColor = pal.strokeColor.controlStrong.defaultColor; + handleColor = pal.strokeColor.controlStrong.defaultColor; + } + else if ( states == Q::Checked ) + { + grooveColor = pal.fillColor.accent.defaultColor; + grooveBorderColor = pal.strokeColor.controlStrong.defaultColor; + handleColor = pal.fillColor.textOnAccent.primary; + } + else if ( states == Q::Hovered ) + { + grooveColor = pal.fillColor.controlAlt.tertiary; + grooveBorderColor = pal.fillColor.text.secondary; + handleColor = pal.fillColor.text.secondary; + } + else if ( states == ( Q::Hovered | Q::Checked ) ) + { + grooveColor = pal.fillColor.accent.secondary; + grooveBorderColor = pal.strokeColor.controlStrong.defaultColor; + handleColor = pal.fillColor.textOnAccent.primary; + //handleColor = pal.fillColor.accent.defaultColor; + } + else if ( states == Q::Pressed ) + { + grooveColor = pal.fillColor.controlAlt.quaternary; + grooveBorderColor = pal.strokeColor.controlStrong.defaultColor; + handleColor = pal.strokeColor.controlStrong.defaultColor; + } + else if ( states == ( Q::Pressed | Q::Checked ) ) + { + grooveColor = pal.fillColor.accent.tertiary; + grooveBorderColor = pal.strokeColor.controlStrong.defaultColor; + handleColor = pal.fillColor.textOnAccent.primary; + } + else if ( states == Q::Disabled ) + { + grooveColor = pal.fillColor.controlAlt.disabled; + grooveBorderColor = pal.fillColor.text.disabled; + handleColor = pal.fillColor.text.disabled; + } + else if ( states == ( Q::Disabled | Q::Checked ) ) + { + grooveColor = pal.fillColor.accent.disabled; + grooveBorderColor = pal.fillColor.accent.disabled; + handleColor = pal.fillColor.textOnAccent.disabled; + } + + const auto groove = Q::Groove | section | states; + const auto handle = Q::Handle | section | states; + + grooveColor = rgbSolid( grooveColor, pal.background.solid.base ); + + setGradient( groove, grooveColor ); + setBoxBorderColors( groove, grooveBorderColor ); + + setGradient( handle, handleColor ); + setBoxBorderGradient( handle, pal.elevation.circle.border, grooveColor ); + } + } +} + +void Editor::setupSubWindow( const QskFluent2Theme& theme ) { using Q = QskSubWindow; const auto& pal = theme.palette; @@ -933,32 +1748,51 @@ void Editor::setupSubWindow() setTextOptions( Q::TitleBarText, Qt::ElideRight, QskTextOptions::NoWrap ); } -void Editor::setupVirtualKeyboard() +void Editor::setupVirtualKeyboardMetrics() { using Q = QskVirtualKeyboard; - const auto& pal = theme.palette; setMargin( Q::ButtonPanel, 2 ); + setFontRole( Q::ButtonText, QskFluent2Skin::BodyLarge ); + setPadding( Q::Panel, 8 ); +} + +void Editor::setupVirtualKeyboardColors( + QskAspect::Section, const QskFluent2Theme& theme ) +{ + using Q = QskVirtualKeyboard; + + const auto& pal = theme.palette; + setGradient( Q::ButtonPanel, pal.fillColor.control.defaultColor ); setGradient( Q::ButtonPanel | Q::Hovered, pal.fillColor.control.secondary ); setGradient( Q::ButtonPanel | QskPushButton::Pressed, pal.fillColor.control.tertiary ); setColor( Q::ButtonText, pal.fillColor.text.primary ); - setFontRole( Q::ButtonText, QskFluent2Skin::BodyLarge ); setColor( Q::ButtonText | QskPushButton::Pressed, pal.fillColor.text.secondary ); - setGradient( Q::Panel, pal.background.solid.secondary ); - setPadding( Q::Panel, 8 ); + setGradient( Q::Panel, pal.background.solid.tertiary ); } -QskFluent2Skin::QskFluent2Skin( const QskFluent2Theme& palette, QObject* parent ) +QskFluent2Skin::QskFluent2Skin( QObject* parent ) : Inherited( parent ) { setupFonts(); - setupGraphicFilters( palette ); - Editor editor( &hintTable(), palette ); - editor.setup(); + Editor editor( &hintTable() ); + editor.setupMetrics(); +} + +void QskFluent2Skin::addTheme( QskAspect::Section section, const QskFluent2Theme& theme ) +{ + if ( section == QskAspect::Body ) + { + // design flaw: we can't have section sensitive filters. TODO .. + setupGraphicFilters( theme ); + } + + Editor editor( &hintTable() ); + editor.setupColors( section, theme ); } QskFluent2Skin::~QskFluent2Skin() diff --git a/skins/fluent2/QskFluent2Skin.h b/skins/fluent2/QskFluent2Skin.h index f731327f..2678dba4 100644 --- a/skins/fluent2/QskFluent2Skin.h +++ b/skins/fluent2/QskFluent2Skin.h @@ -18,9 +18,12 @@ class QSK_FLUENT2_EXPORT QskFluent2Skin : public QskSkin using Inherited = QskSkin; public: - QskFluent2Skin( const QskFluent2Theme&, QObject* parent = nullptr ); + QskFluent2Skin( QObject* parent = nullptr ); ~QskFluent2Skin() override; + void addTheme( QskAspect::Section, const QskFluent2Theme& ); + void setup(); + enum GraphicRole { GraphicRoleFillColorTextDisabled, diff --git a/skins/fluent2/QskFluent2SkinFactory.cpp b/skins/fluent2/QskFluent2SkinFactory.cpp index a7127ba8..8b393b73 100644 --- a/skins/fluent2/QskFluent2SkinFactory.cpp +++ b/skins/fluent2/QskFluent2SkinFactory.cpp @@ -7,8 +7,16 @@ #include "QskFluent2Skin.h" #include "QskFluent2Theme.h" -static const QString fluent2LightSkinName = QStringLiteral( "Fluent2 Light" ); -static const QString fluent2DarkSkinName = QStringLiteral( "Fluent2 Dark" ); +static const QString nameLight = QStringLiteral( "Fluent2 Light" ); +static const QString nameDark = QStringLiteral( "Fluent2 Dark" ); + +namespace +{ + inline constexpr QRgb rgbGray( int value ) + { + return qRgba( value, value, value, 255 ); + } +} QskFluent2SkinFactory::QskFluent2SkinFactory( QObject* parent ) : QskSkinFactory( parent ) @@ -21,23 +29,71 @@ QskFluent2SkinFactory::~QskFluent2SkinFactory() QStringList QskFluent2SkinFactory::skinNames() const { - return { fluent2LightSkinName, fluent2DarkSkinName }; + return { nameLight, nameDark }; } QskSkin* QskFluent2SkinFactory::createSkin( const QString& skinName ) { - if ( QString::compare( skinName, fluent2LightSkinName, Qt::CaseInsensitive ) == 0 ) + QskSkin::ColorScheme colorScheme; + + if ( QString::compare( skinName, nameLight, Qt::CaseInsensitive ) == 0 ) { - QskFluent2Theme theme( QskSkin::LightScheme ); - return new QskFluent2Skin( theme ); + colorScheme = QskSkin::LightScheme; } - else if ( QString::compare( skinName, fluent2DarkSkinName, Qt::CaseInsensitive ) == 0 ) + else if ( QString::compare( skinName, nameDark, Qt::CaseInsensitive ) == 0 ) { - QskFluent2Theme theme( QskSkin::DarkScheme ); - return new QskFluent2Skin( theme ); + colorScheme = QskSkin::DarkScheme; + } + else + { + return nullptr; } - return nullptr; + struct + { + QskSkin::ColorScheme scheme; + QskFluent2Theme::BaseColors baseColors; + QskFluent2Theme::AccentColors accentColors; + + QskFluent2Theme theme() const { return { scheme, baseColors, accentColors }; } + } colors[2]; + + switch( colorScheme ) + { + case QskSkin::LightScheme: + { + colors[0].scheme = colorScheme; + colors[0].baseColors = { rgbGray( 243 ), rgbGray( 249 ), rgbGray( 238 ) }; + colors[0].accentColors = { 0xff0078d4, 0xff005eb7, 0xff003d92, 0xff001968 }; + + colors[1].scheme = colorScheme; + colors[1].baseColors = { rgbGray( 249 ), rgbGray( 249 ), rgbGray( 238 ) }; + colors[1].accentColors = colors[0].accentColors; + + break; + } + case QskSkin::DarkScheme: + { + colors[0].scheme = colorScheme; + colors[0].baseColors = { rgbGray( 32 ), rgbGray( 40 ), rgbGray( 28 ) }; + colors[0].accentColors = { 0xff0078d4, 0xff0093f9, 0xff60ccfe, 0xff98ecfe }; + + colors[1].scheme = colorScheme; + colors[1].baseColors = { rgbGray( 40 ), rgbGray( 44 ), rgbGray( 28 ) }; + colors[1].accentColors = colors[0].accentColors; + + break; + } + default:; + } + + auto skin = new QskFluent2Skin(); + + skin->addTheme( QskAspect::Body, colors[0].theme() ); + skin->addTheme( QskAspect::Header, colors[1].theme() ); + skin->addTheme( QskAspect::Footer, colors[1].theme() ); + + return skin; } #include "moc_QskFluent2SkinFactory.cpp" diff --git a/skins/fluent2/QskFluent2Theme.cpp b/skins/fluent2/QskFluent2Theme.cpp index 97f4ad3f..402d86cf 100644 --- a/skins/fluent2/QskFluent2Theme.cpp +++ b/skins/fluent2/QskFluent2Theme.cpp @@ -14,27 +14,25 @@ namespace } } -QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme ) - : QskFluent2Theme( colorScheme, - { // default Fluent accent colors: - 0xff98ecfe, - 0xff60ccfe, - 0xff0093f9, - 0xff0078d4, - 0xff005eb7, - 0xff003d92, - 0xff001968 - } ) -{ -} - QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, - const std::array< QRgb, NumAccentColors >& accentColors ) + const BaseColors& baseColors, const AccentColors& accentColors ) { using namespace QskRgb; + { + auto& colors = palette.background; + + colors.solid.base = baseColors.primary; + colors.solid.secondary = baseColors.secondary; + colors.solid.tertiary = baseColors.tertiary; + } + if( colorScheme != QskSkin::DarkScheme ) { + { + palette.background.solid.quaternary = rgbGray( 255 ); + } + { auto& colors = palette.fillColor; @@ -43,9 +41,10 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, colors.text.tertiary = rgbGray( 0, 0.4458 ); colors.text.disabled = rgbGray( 0, 0.3614 ); - colors.accentText.primary = accentColors[ AccentDark2 ]; - colors.accentText.secondary = accentColors[ AccentDark3 ]; - colors.accentText.tertiary = accentColors[ AccentDark1 ]; + colors.accentText.primary = accentColors.tertiary; + colors.accentText.secondary = accentColors.quaternary; + colors.accentText.tertiary = accentColors.secondary; + colors.accentText.disabled = rgbGray( 0, 0.3614 ); colors.textOnAccent.primary = rgbGray( 255 ); @@ -73,13 +72,34 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, colors.controlAlt.quaternary = rgbGray( 0, 0.0924 ); colors.controlAlt.disabled = Qt::transparent; - colors.accent.defaultColor = accentColors[ AccentDark1 ]; - colors.accent.secondary = toTransparentF( accentColors[ AccentDark1 ], 0.90 ); - colors.accent.tertiary = toTransparentF( accentColors[ AccentDark1 ], 0.80 ); + colors.accent.defaultColor = accentColors.secondary; + colors.accent.secondary = toTransparentF( accentColors.secondary, 0.90 ); + colors.accent.tertiary = toTransparentF( accentColors.secondary, 0.80 ); colors.accent.disabled = rgbGray( 0, 0.2169 ); - colors.accent.selectedTextBackground = accentColors[ AccentBase ]; + colors.accent.selectedTextBackground = accentColors.primary; } +#if 0 + { + // system colors + + critical = 0xffc42b1c; + success = 0xff0f7b0f; + attention = 0xff005fb7; + caution = 0xff9d5d00; + attentionBackground = rgbGray( 246, 0.50 ); + successBackground = 0xffdff6dd; + cautionBackground = 0xfffff4ce; + criticalBackground = 0xfffde7e9; + neutral = rgbGray( 0, 0.4458 ); + neutralBackground = rgbGray( 0, 0.0241 ); + + solidNeutral = rgbGray( 138 ); + solidAttentionBackground = rgbGray( 247 ); + solidNeutralBackground = rgbGray( 243 ); + } +#endif + { auto& colors = palette.elevation; @@ -118,30 +138,23 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, { auto& colors = palette.background; - colors.card.defaultColor = rgbGray( 255, 0.70 ); - colors.card.secondary = rgbGray( 246, 0.50 ); - colors.card.tertiary = rgbGray( 255 ); - colors.overlay.defaultColor = rgbGray( 0, 0.30 ); colors.layer.alt = rgbGray( 255 ); colors.flyout.defaultColor = rgbGray( 252, 0.85 ); - colors.solid.base = rgbGray( 243 ); - colors.solid.secondary = rgbGray( 238 ); - colors.solid.tertiary = rgbGray( 249 ); - colors.solid.quaternary = rgbGray( 255 ); } // Shadow: - shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.04 ) }; - shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.10 ) }; shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.14 ) }; // ### should actually be drawn twice with different values: shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.1474 ) }; } else { + { + palette.background.solid.quaternary = rgbGray( 44 ); + } { auto& colors = palette.fillColor; @@ -150,9 +163,9 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, colors.text.tertiary = rgbGray( 255, 0.5442 ); colors.text.disabled = rgbGray( 255, 0.3628 ); - colors.accentText.primary = accentColors[ AccentLight3 ]; - colors.accentText.secondary = accentColors[ AccentLight3 ]; - colors.accentText.tertiary = accentColors[ AccentLight2 ]; + colors.accentText.primary = accentColors.quaternary; + colors.accentText.secondary = accentColors.quaternary; + colors.accentText.tertiary = accentColors.tertiary; colors.accentText.disabled = rgbGray( 255, 0.3628 ); colors.textOnAccent.primary = rgbGray( 0 ); @@ -180,13 +193,33 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, colors.controlAlt.quaternary = rgbGray( 255, 0.0698 ); colors.controlAlt.disabled = Qt::transparent; - colors.accent.defaultColor = accentColors[ AccentLight2 ]; - colors.accent.secondary = toTransparentF( accentColors[ AccentLight2 ], 0.90 ); - colors.accent.tertiary = toTransparentF( accentColors[ AccentLight2 ], 0.80 ); + colors.accent.defaultColor = accentColors.tertiary; + colors.accent.secondary = toTransparentF( accentColors.tertiary, 0.90 ); + colors.accent.tertiary = toTransparentF( accentColors.tertiary, 0.80 ); colors.accent.disabled = rgbGray( 255, 0.1581 ); - colors.accent.selectedTextBackground = accentColors[ AccentBase ]; + colors.accent.selectedTextBackground = accentColors.primary; } +#if 0 + { + // system colors + + critical = 0xffff99a4; + success = 0xff6ccb5f; + attention = 0xff60cdff; + caution = 0xfffce100; + attentionBackground = rgbGray( 255, 0.0326 ); + successBackground = 0xff393d1b; + cautionBackground = 0xff433519; + criticalBackground = 0xff442726; + neutral = rgbGray( 255, 0.5442 ); + neutralBackground = rgbGray( 255, 0.0326 ); + solidNeutral = rgbGray( 157 ); + solidAttentionBackground = rgbGray( 46 ); + solidNeutralBackground = rgbGray( 46 ); + } +#endif + { auto& colors = palette.elevation; @@ -227,24 +260,13 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, { auto& colors = palette.background; - colors.card.defaultColor = rgbGray( 255, 0.0512 ); - colors.card.secondary = rgbGray( 255, 0.0326 ); - colors.card.tertiary = rgbGray( 255 ); // not set in Figma - colors.overlay.defaultColor = rgbGray( 0, 0.30 ); colors.layer.alt = rgbGray( 255, 0.0538 ); colors.flyout.defaultColor = rgbGray( 44, 0.96 ); - - colors.solid.base = rgbGray( 32 ); - colors.solid.secondary = rgbGray( 28 ); - colors.solid.tertiary = rgbGray( 40 ); - colors.solid.quaternary = rgbGray( 44 ); } // Shadow: - shadow.cardRest = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.13 ) }; - shadow.cardHover = { QskShadowMetrics( 0, 4, QPointF( 0, 2 ) ), rgbGray( 0, 0.26 ) }; shadow.flyout = { QskShadowMetrics( 0, 16, QPointF( 0, 8 ) ), rgbGray( 0, 0.26 ) }; // ### should actually be drawn twice with different values: shadow.dialog = { QskShadowMetrics( 0, 21, QPointF( 0, 2 ) ), rgbGray( 0, 0.37 ) }; diff --git a/skins/fluent2/QskFluent2Theme.h b/skins/fluent2/QskFluent2Theme.h index af563871..8aba499b 100644 --- a/skins/fluent2/QskFluent2Theme.h +++ b/skins/fluent2/QskFluent2Theme.h @@ -17,21 +17,23 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme { public: - enum AccentColors + struct BaseColors { - AccentLight3, - AccentLight2, - AccentLight1, - AccentBase, - AccentDark1, - AccentDark2, - AccentDark3, - - NumAccentColors + QRgb primary; + QRgb secondary; + QRgb tertiary; }; - QskFluent2Theme( QskSkin::ColorScheme ); - QskFluent2Theme( QskSkin::ColorScheme, const std::array< QRgb, NumAccentColors >& ); + struct AccentColors + { + QRgb primary; + QRgb secondary; + QRgb tertiary; + QRgb quaternary; + }; + + QskFluent2Theme( QskSkin::ColorScheme, const BaseColors& baseColors, + const AccentColors& accentColors ); typedef std::array< QRgb, 2 > BorderGradient; @@ -175,13 +177,6 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme struct Background { - struct - { - QRgb defaultColor; - QRgb secondary; - QRgb tertiary; - } card; - struct { QRgb defaultColor; @@ -222,8 +217,6 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme struct { - ShadowSettings cardRest; - ShadowSettings cardHover; ShadowSettings flyout; ShadowSettings dialog; } shadow; diff --git a/src/controls/QskSkinManager.cpp b/src/controls/QskSkinManager.cpp index 3013a8bb..a41fcfca 100644 --- a/src/controls/QskSkinManager.cpp +++ b/src/controls/QskSkinManager.cpp @@ -90,10 +90,6 @@ namespace const auto factoryData = pluginData.value( TokenData ).toObject(); m_factoryId = factoryData.value( TokenFactoryId ).toString().toLower(); -#if 1 - if ( m_factoryId == "fluent2factory" ) - return false; // we need to solve a couple of problems first -#endif if ( m_factoryId.isEmpty() ) { // Creating a dummy factory id From 0f6a1206e6615d244472363c3d3d828560d12407 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 4 Jul 2023 07:49:38 +0200 Subject: [PATCH 28/60] missing cell padding added for fluent2 --- examples/gallery/listbox/ListBoxPage.cpp | 4 ---- skins/fluent2/QskFluent2Skin.cpp | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/gallery/listbox/ListBoxPage.cpp b/examples/gallery/listbox/ListBoxPage.cpp index e0650d87..4393e32e 100644 --- a/examples/gallery/listbox/ListBoxPage.cpp +++ b/examples/gallery/listbox/ListBoxPage.cpp @@ -16,10 +16,6 @@ namespace : QskSimpleListBox( parent ) { setMargins( QMarginsF( 15, 10, 10, 10 ) ); - - // increasing the padding of each row: usually the job of the skin ! - setPaddingHint( Cell, QMargins( 10, 20, 10, 20 ) ); - populate(); setSelectedRow( 5 ); diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index e1641198..0cd05f89 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -34,6 +34,7 @@ - hover state is not implemented - Indicator subcontrol might be better than using the border of the selection box + - cell padding unclear - using qskDpToPixels ? */ @@ -607,6 +608,10 @@ void Editor::setupListViewMetrics() using Q = QskListView; setBoxBorderMetrics( Q::Cell | Q::Selected, { 3, 0, 0, 0 } ); +#if 1 + // taken from M3 - what are the actual values, TODO ... + setPadding( Q::Cell, { 16, 12, 16, 12 } ); +#endif } void Editor::setupListViewColors( From f126a9007d3787d4758de1c950e531dd12ef0aa2 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Fri, 30 Jun 2023 15:28:20 +0200 Subject: [PATCH 29/60] menu: Support hovered state --- skins/fluent2/QskFluent2Skin.cpp | 4 +++- skins/material3/QskMaterial3Skin.cpp | 11 ++++++++--- src/controls/QskMenu.cpp | 26 ++++++++++++++++++++++++++ src/controls/QskMenu.h | 5 +++++ src/controls/QskMenuSkinlet.cpp | 12 ++++++++++++ 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 0cd05f89..fdb93bf1 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -724,6 +724,8 @@ void Editor::setupMenuColors( setGradient( Q::Panel, pal.background.flyout.defaultColor ); setShadowColor( Q::Panel, theme.shadow.flyout.color ); + setGradient( Q::Segment | Q::Hovered, pal.fillColor.subtle.secondary ); + setGradient( Q::Segment | Q::Selected, pal.fillColor.subtle.secondary ); /* @@ -734,7 +736,7 @@ void Editor::setupMenuColors( const auto c1 = pal.fillColor.subtle.secondary; const auto c2 = pal.fillColor.accent.defaultColor; - setBoxBorderColors( Q::Segment | Q::Selected, + setBoxBorderColors( Q::Segment | Q::Selected, QskGradient( { { 0.25, c1 }, { 0.25, c2 }, { 0.75, c2 }, { 0.75, c1 } } ) ); setColor( Q::Text, pal.fillColor.text.primary ); diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 21665588..8728a0ee 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -340,8 +340,8 @@ void Editor::setupMenu() // The color here is primary with an opacity of 8% - we blend that // with the background, because we don't want the menu to have transparency: - const auto panel = flattenedColor( m_pal.primary, m_pal.background, 0.08 ); - setGradient( Q::Panel, panel ); + const auto panelColor = flattenedColor( m_pal.primary, m_pal.background, 0.08 ); + setGradient( Q::Panel, panelColor ); setShadowMetrics( Q::Panel, m_pal.elevation2 ); setShadowColor( Q::Panel, m_pal.shadow ); @@ -355,7 +355,12 @@ void Editor::setupMenu() setSpacing( Q::Segment, 5_dp ); setGradient( Q::Segment, Qt::transparent ); - setGradient( Q::Cursor, m_pal.primary12 ); + const auto hoverColor = flattenedColor( m_pal.onSurface, panelColor, m_pal.hoverOpacity ); + setGradient( Q::Segment | Q::Hovered, hoverColor ); + + setGradient( Q::Segment | Q::Selected, m_pal.primary12 ); + const auto hoverSelectedColor = flattenedColor( m_pal.onSurface, m_pal.primary12, m_pal.hoverOpacity ); + setGradient( Q::Segment | Q::Selected | Q::Hovered, hoverSelectedColor ); setPadding( Q::Icon, 7_dp ); setStrutSize( Q::Icon, 24_dp, 24_dp ); diff --git a/src/controls/QskMenu.cpp b/src/controls/QskMenu.cpp index 3e2c2cba..b72877e8 100644 --- a/src/controls/QskMenu.cpp +++ b/src/controls/QskMenu.cpp @@ -72,6 +72,8 @@ QskMenu::QskMenu( QQuickItem* parent ) connect( this, &QskMenu::opened, this, [this]() { m_data->triggeredIndex = -1; } ); + + setAcceptHoverEvents( true ); } QskMenu::~QskMenu() @@ -319,6 +321,30 @@ void QskMenu::keyReleaseEvent( QKeyEvent* ) } } +void QskMenu::hoverEnterEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); + update(); +} + +void QskMenu::hoverMoveEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); + update(); +} + +void QskMenu::hoverLeaveEvent( QHoverEvent* ) +{ + using A = QskAspect; + + setSkinHint( Segment | Hovered | A::Metric | A::Position, QPointF() ); + update(); +} + #ifndef QT_NO_WHEELEVENT void QskMenu::wheelEvent( QWheelEvent* event ) diff --git a/src/controls/QskMenu.h b/src/controls/QskMenu.h index 9a4e6624..ce4da4fc 100644 --- a/src/controls/QskMenu.h +++ b/src/controls/QskMenu.h @@ -68,6 +68,7 @@ class QSK_EXPORT QskMenu : public QskPopup QVector< int > actions() const; int currentIndex() const; + QString currentText() const; int triggeredIndex() const; @@ -97,6 +98,10 @@ class QSK_EXPORT QskMenu : public QskPopup void keyPressEvent( QKeyEvent* ) override; void keyReleaseEvent( QKeyEvent* ) override; + void hoverEnterEvent( QHoverEvent* ) override; + void hoverMoveEvent( QHoverEvent* ) override; + void hoverLeaveEvent( QHoverEvent* ) override; + #ifndef QT_NO_WHEELEVENT void wheelEvent( QWheelEvent* ) override; #endif diff --git a/src/controls/QskMenuSkinlet.cpp b/src/controls/QskMenuSkinlet.cpp index b5e9b8e3..c99e94e1 100644 --- a/src/controls/QskMenuSkinlet.cpp +++ b/src/controls/QskMenuSkinlet.cpp @@ -385,6 +385,7 @@ QskAspect::States QskMenuSkinlet::sampleStates( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const { using Q = QskMenu; + using A = QskAspect; auto states = Inherited::sampleStates( skinnable, subControl, index ); @@ -394,6 +395,17 @@ QskAspect::States QskMenuSkinlet::sampleStates( if ( menu->currentIndex() == menu->actions()[ index ] ) states |= QskMenu::Selected; + + const auto cursorPos = menu->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); + + if( !cursorPos.isNull() && menu->indexAtPosition( cursorPos ) == index ) + { + states |= Q::Hovered; + } + else + { + states &= ~Q::Hovered; + } } return states; From e00c2f5335050bc90e362d01bbadf2a21658c090 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Fri, 30 Jun 2023 15:44:49 +0200 Subject: [PATCH 30/60] menu: support pressed state --- skins/fluent2/QskFluent2Skin.cpp | 6 ++++++ skins/material3/QskMaterial3Skin.cpp | 2 ++ src/controls/QskMenu.cpp | 10 ++++++++-- src/controls/QskMenu.h | 4 +++- src/controls/QskMenuSkinlet.cpp | 13 ++++++++++++- 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index fdb93bf1..725fa4c9 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -725,6 +725,7 @@ void Editor::setupMenuColors( setShadowColor( Q::Panel, theme.shadow.flyout.color ); setGradient( Q::Segment | Q::Hovered, pal.fillColor.subtle.secondary ); + setGradient( Q::Segment | Q::Selected | Q::Pressed, pal.fillColor.subtle.tertiary ); setGradient( Q::Segment | Q::Selected, pal.fillColor.subtle.secondary ); @@ -739,9 +740,14 @@ void Editor::setupMenuColors( setBoxBorderColors( Q::Segment | Q::Selected, QskGradient( { { 0.25, c1 }, { 0.25, c2 }, { 0.75, c2 }, { 0.75, c1 } } ) ); + setBoxBorderColors( Q::Segment | Q::Selected | Q::Pressed, + QskGradient( { { 0.33, c1 }, { 0.33, c2 }, { 0.67, c2 }, { 0.67, c1 } } ) ); + setColor( Q::Text, pal.fillColor.text.primary ); + setColor( Q::Text | Q::Selected | Q::Pressed, pal.fillColor.text.secondary ); setGraphicRole( Q::Icon, QskFluent2Skin::GraphicRoleFillColorTextPrimary ); + setGraphicRole( Q::Icon | Q::Selected | Q::Pressed, QskFluent2Skin::GraphicRoleFillColorTextSecondary ); } void Editor::setupPageIndicatorMetrics() diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 8728a0ee..4ebd9606 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -361,6 +361,8 @@ void Editor::setupMenu() setGradient( Q::Segment | Q::Selected, m_pal.primary12 ); const auto hoverSelectedColor = flattenedColor( m_pal.onSurface, m_pal.primary12, m_pal.hoverOpacity ); setGradient( Q::Segment | Q::Selected | Q::Hovered, hoverSelectedColor ); + const auto pressedSelectedColor = flattenedColor( m_pal.onSurface, m_pal.primary12, m_pal.pressedOpacity ); + setGradient( Q::Segment | Q::Pressed | Q::Selected, pressedSelectedColor ); setPadding( Q::Icon, 7_dp ); setStrutSize( Q::Icon, 24_dp, 24_dp ); diff --git a/src/controls/QskMenu.cpp b/src/controls/QskMenu.cpp index b72877e8..7390e317 100644 --- a/src/controls/QskMenu.cpp +++ b/src/controls/QskMenu.cpp @@ -27,6 +27,7 @@ QSK_SUBCONTROL( QskMenu, Icon ) QSK_SUBCONTROL( QskMenu, Separator ) QSK_SYSTEM_STATE( QskMenu, Selected, QskAspect::FirstSystemState << 2 ) +QSK_SYSTEM_STATE( QskMenu, Pressed, QskAspect::FirstSystemState << 3 ) static inline int qskActionIndex( const QVector< int >& actions, int index ) { @@ -309,7 +310,7 @@ void QskMenu::keyPressEvent( QKeyEvent* event ) void QskMenu::keyReleaseEvent( QKeyEvent* ) { - if( m_data->isPressed ) + if( isPressed() ) { m_data->isPressed = false; @@ -416,7 +417,7 @@ void QskMenu::mouseReleaseEvent( QMouseEvent* event ) { if ( event->button() == Qt::LeftButton ) { - if( m_data->isPressed ) + if( isPressed() ) { m_data->isPressed = false; @@ -481,6 +482,11 @@ int QskMenu::indexAtPosition( const QPointF& pos ) const return m_data->actions.value( index, -1 ); } +bool QskMenu::isPressed() const +{ + return m_data->isPressed; +} + void QskMenu::trigger( int index ) { if ( index >= 0 && index < m_data->options.count() ) diff --git a/src/controls/QskMenu.h b/src/controls/QskMenu.h index ce4da4fc..bc4cb2ca 100644 --- a/src/controls/QskMenu.h +++ b/src/controls/QskMenu.h @@ -38,7 +38,7 @@ class QSK_EXPORT QskMenu : public QskPopup public: QSK_SUBCONTROLS( Overlay, Panel, Segment, Cursor, Text, Icon, Separator ) - QSK_STATES( Selected ) + QSK_STATES( Selected, Pressed ) QskMenu( QQuickItem* parentItem = nullptr ); ~QskMenu() override; @@ -79,6 +79,8 @@ class QSK_EXPORT QskMenu : public QskPopup QRectF cellRect( int index ) const; int indexAtPosition( const QPointF& ) const; + bool isPressed() const; + Q_INVOKABLE int exec(); Q_SIGNALS: diff --git a/src/controls/QskMenuSkinlet.cpp b/src/controls/QskMenuSkinlet.cpp index c99e94e1..0629b137 100644 --- a/src/controls/QskMenuSkinlet.cpp +++ b/src/controls/QskMenuSkinlet.cpp @@ -394,7 +394,18 @@ QskAspect::States QskMenuSkinlet::sampleStates( const auto menu = static_cast< const QskMenu* >( skinnable ); if ( menu->currentIndex() == menu->actions()[ index ] ) - states |= QskMenu::Selected; + { + states |= Q::Selected; + + if( menu->isPressed() ) + { + states |= Q::Pressed; + } + else + { + states &= ~Q::Pressed; + } + } const auto cursorPos = menu->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); From b97bce236033bcd93d7a05ba46e396ce4dc9c56a Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Fri, 30 Jun 2023 17:17:48 +0200 Subject: [PATCH 31/60] combo box: Support pressed state --- skins/fluent2/QskFluent2Skin.cpp | 15 +++++++++++++-- skins/material3/QskMaterial3Skin.cpp | 4 ++++ src/controls/QskComboBox.cpp | 26 +++++++++++++++++++++++++- src/controls/QskComboBox.h | 12 +++++++++++- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 725fa4c9..3ea8864d 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -514,7 +514,7 @@ void Editor::setupComboBoxColors( const auto& pal = theme.palette; - for ( const auto state : { QskAspect::NoState, Q::Hovered, Q::Focused, Q::Disabled } ) + for ( const auto state : { QskAspect::NoState, Q::Hovered, Q::Focused, Q::Pressed, Q::Disabled } ) { QRgb panelColor, borderColor1, borderColor2, textColor; @@ -535,12 +535,18 @@ void Editor::setupComboBoxColors( } else if ( state == Q::Focused ) { - panelColor = pal.fillColor.control.inputActive; borderColor1 = pal.elevation.textControl.border[0]; borderColor2 = pal.fillColor.accent.defaultColor; textColor = pal.fillColor.text.primary; } + else if ( state == Q::Pressed ) + { + panelColor = pal.fillColor.control.inputActive; + borderColor1 = pal.elevation.textControl.border[0]; + borderColor2 = pal.fillColor.accent.defaultColor; + textColor = pal.fillColor.text.secondary; + } else if ( state == Q::Disabled ) { panelColor = pal.fillColor.control.disabled; @@ -565,6 +571,11 @@ void Editor::setupComboBoxColors( setGraphicRole( icon, W::GraphicRoleFillColorTextDisabled ); setGraphicRole( indicator, W::GraphicRoleFillColorTextDisabled ); } + else if( state == Q::Pressed ) + { + setGraphicRole( icon, W::GraphicRoleFillColorTextSecondary ); + setGraphicRole( indicator, W::GraphicRoleFillColorTextSecondary ); + } else { setGraphicRole( icon, W::GraphicRoleFillColorTextPrimary ); diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 4ebd9606..bcc38219 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -278,6 +278,10 @@ void Editor::setupComboBox() m_pal.surfaceVariant, m_pal.focusOpacity ); setGradient( Q::Panel | Q::Focused, focusColor ); + const auto pressedColor = flattenedColor( m_pal.onSurfaceVariant, + m_pal.surfaceVariant, m_pal.pressedOpacity ); + setGradient( Q::Panel | Q::Pressed, pressedColor ); + const auto activeColor = flattenedColor( m_pal.onSurfaceVariant, m_pal.surfaceVariant, m_pal.pressedOpacity ); setGradient( Q::Panel | Q::PopupOpen, activeColor ); diff --git a/src/controls/QskComboBox.cpp b/src/controls/QskComboBox.cpp index dd9e4679..ef79a486 100644 --- a/src/controls/QskComboBox.cpp +++ b/src/controls/QskComboBox.cpp @@ -18,7 +18,8 @@ QSK_SUBCONTROL( QskComboBox, Icon ) QSK_SUBCONTROL( QskComboBox, Text ) QSK_SUBCONTROL( QskComboBox, StatusIndicator ) -QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 1 ) +QSK_SYSTEM_STATE( QskComboBox, Pressed, QskAspect::FirstSystemState << 1 ) +QSK_SYSTEM_STATE( QskComboBox, PopupOpen, QskAspect::FirstSystemState << 2 ) static inline void qskTraverseOptions( QskComboBox* comboBox, int steps ) { @@ -89,6 +90,25 @@ QskComboBox::~QskComboBox() { } +bool QskComboBox::isPressed() const +{ + return hasSkinState( Pressed ); +} + +void QskComboBox::setPressed( bool on ) +{ + if ( on == isPressed() ) + return; + + setSkinStateFlag( Pressed, on ); + Q_EMIT pressedChanged( on ); + + if ( on ) + Q_EMIT pressed(); + else + Q_EMIT released(); +} + void QskComboBox::setPopupOpen( bool on ) { if ( on == isPopupOpen() ) @@ -246,11 +266,13 @@ void QskComboBox::closePopup() void QskComboBox::mousePressEvent( QMouseEvent* ) { + setPressed( true ); setPopupOpen( true ); } void QskComboBox::mouseReleaseEvent( QMouseEvent* ) { + setPressed( false ); } void QskComboBox::keyPressEvent( QKeyEvent* event ) @@ -259,6 +281,7 @@ void QskComboBox::keyPressEvent( QKeyEvent* event ) { if ( !event->isAutoRepeat() ) { + setPressed( true ); setPopupOpen( true ); return; } @@ -270,6 +293,7 @@ void QskComboBox::keyPressEvent( QKeyEvent* event ) case Qt::Key_F4: { // QComboBox does this ??? + setPressed( true ); setPopupOpen( true ); return; } diff --git a/src/controls/QskComboBox.h b/src/controls/QskComboBox.h index 8a7e064a..83a9f1ec 100644 --- a/src/controls/QskComboBox.h +++ b/src/controls/QskComboBox.h @@ -34,16 +34,22 @@ class QSK_EXPORT QskComboBox : public QskControl Q_PROPERTY( int indexInPopup READ indexInPopup NOTIFY indexInPopupChanged ) + Q_PROPERTY( bool pressed READ isPressed + WRITE setPressed NOTIFY pressedChanged FINAL ) + using Inherited = QskControl; public: QSK_SUBCONTROLS( Panel, Icon, Text, StatusIndicator ) - QSK_STATES( PopupOpen ) + QSK_STATES( Pressed, PopupOpen ) QskComboBox( QQuickItem* parent = nullptr ); ~QskComboBox() override; + void setPressed( bool on ); + bool isPressed() const; + void setPopupOpen( bool ); bool isPopupOpen() const; @@ -78,6 +84,10 @@ class QSK_EXPORT QskComboBox : public QskControl void setCurrentIndex( int ); Q_SIGNALS: + void pressed(); + void released(); + void pressedChanged( bool ); + void currentIndexChanged( int ); void indexInPopupChanged( int ); From 11f74a2f57d21a14404a1be0a93322a9810ab69a Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Sun, 5 Feb 2023 13:20:11 +0100 Subject: [PATCH 32/60] push buttons: Improve ripple effect --- skins/material3/QskMaterial3Skin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index bcc38219..95abc1cc 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -645,6 +645,7 @@ void Editor::setupPushButton() setSpacing( Q::Panel, 8_dp ); setPadding( Q::Panel, { 24_dp, 0, 24_dp, 0 } ); setBoxShape( Q::Panel, 100, Qt::RelativeSize ); + setShadowColor( Q::Panel, m_pal.shadow ); setStrutSize( Q::Icon, 18_dp, 18_dp ); setPadding( Q::Icon, { 0, 0, 8_dp, 0 } ); @@ -653,8 +654,7 @@ void Editor::setupPushButton() setFontRole( Q::Text, QskMaterial3Skin::M3LabelLarge ); setPadding( Q::Text, 0 ); - setShadowColor( Q::Panel, m_pal.shadow ); - + setBoxShape( Q::Splash, 40_dp ); setAnimation( Q::Splash | QskAspect::Color, qskDuration ); From 6b43231ca20ef148cf1858c5054ebf220f90ee17 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Sun, 5 Feb 2023 13:45:29 +0100 Subject: [PATCH 33/60] segmented bar: Add splash rect and style for M3 --- skins/material3/QskMaterial3Skin.cpp | 7 +++ src/controls/QskPushButton.cpp | 1 + src/controls/QskSegmentedBar.cpp | 12 +++++ src/controls/QskSegmentedBar.h | 2 +- src/controls/QskSegmentedBarSkinlet.cpp | 70 ++++++++++++++++++++++++- src/controls/QskSegmentedBarSkinlet.h | 4 ++ 6 files changed, 93 insertions(+), 3 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 95abc1cc..a1a404de 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -571,6 +571,13 @@ void Editor::setupSegmentedBar() setBoxBorderColors( Q::Cursor, Qt::transparent ); } + { + // Splash + setBoxShape( Q::Splash, 20_dp ); + setGradient( Q::Splash, stateLayerColor( m_pal.onSecondaryContainer, m_pal.pressedOpacity ) ); + setAnimation( Q::Splash | A::Color, qskDuration ); + } + { // Text diff --git a/src/controls/QskPushButton.cpp b/src/controls/QskPushButton.cpp index fc495d22..862872f2 100644 --- a/src/controls/QskPushButton.cpp +++ b/src/controls/QskPushButton.cpp @@ -306,6 +306,7 @@ void QskPushButton::mousePressEvent( QMouseEvent* event ) using A = QskAspect; const auto hint = animationHint( Splash | A::Color ); + if( hint.isValid() ) { setPositionHint( Splash, qskMousePosition( event ).x() ); diff --git a/src/controls/QskSegmentedBar.cpp b/src/controls/QskSegmentedBar.cpp index 0dc68537..78ab401f 100644 --- a/src/controls/QskSegmentedBar.cpp +++ b/src/controls/QskSegmentedBar.cpp @@ -10,12 +10,14 @@ #include "QskEvent.h" #include "QskSkinlet.h" #include "QskAspect.h" +#include "QskAnimationHint.h" #include #include #include QSK_SUBCONTROL( QskSegmentedBar, Panel ) +QSK_SUBCONTROL( QskSegmentedBar, Splash ) QSK_SUBCONTROL( QskSegmentedBar, Segment ) QSK_SUBCONTROL( QskSegmentedBar, Separator ) QSK_SUBCONTROL( QskSegmentedBar, Cursor ) @@ -148,6 +150,8 @@ QskAspect::Variation QskSegmentedBar::effectiveVariation() const void QskSegmentedBar::mousePressEvent( QMouseEvent* event ) { + using A = QskAspect; + const int index = indexAtPosition( qskMousePosition( event ) ); if( isSegmentEnabled( index ) ) @@ -163,6 +167,14 @@ void QskSegmentedBar::mousePressEvent( QMouseEvent* event ) } } } + + const auto hint = animationHint( Splash | A::Color ); + + if( hint.isValid() ) + { + setSkinHint( Splash | A::Metric | A::Position, event->pos() ); + startTransition( Splash | A::Metric | A::Size, hint, 0.0, 1.0 ); + } } void QskSegmentedBar::mouseUngrabEvent() diff --git a/src/controls/QskSegmentedBar.h b/src/controls/QskSegmentedBar.h index 252513fd..c48e6b66 100644 --- a/src/controls/QskSegmentedBar.h +++ b/src/controls/QskSegmentedBar.h @@ -36,7 +36,7 @@ class QSK_EXPORT QskSegmentedBar : public QskControl using Inherited = QskControl; public: - QSK_SUBCONTROLS( Panel, Segment, Separator, Cursor, Text, Icon ) + QSK_SUBCONTROLS( Panel, Splash, Segment, Separator, Cursor, Text, Icon ) QSK_STATES( Selected, Minimum, Maximum ) QskSegmentedBar( QQuickItem* parent = nullptr ); diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index 8581dbcf..4632f746 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -10,6 +10,7 @@ #include "QskGraphic.h" #include "QskColorFilter.h" #include "QskFunctions.h" +#include "QskSGNode.h" #include "QskSkin.h" #include "QskStandardSymbol.h" #include "QskSubcontrolLayoutEngine.h" @@ -66,8 +67,8 @@ namespace QskSegmentedBarSkinlet::QskSegmentedBarSkinlet( QskSkin* skin ) : Inherited( skin ) { - setNodeRoles( { PanelRole, SegmentRole, - SeparatorRole, CursorRole, TextRole, IconRole } ); + setNodeRoles( { PanelRole, SegmentRole, SeparatorRole, + CursorRole, SplashRole, TextRole, IconRole } ); } QskSegmentedBarSkinlet::~QskSegmentedBarSkinlet() = default; @@ -86,6 +87,9 @@ QRectF QskSegmentedBarSkinlet::subControlRect( if( subControl == Q::Cursor ) return cursorRect( bar, contentsRect ); + if( subControl == Q::Splash ) + return splashRect( bar, contentsRect ); + return Inherited::subControlRect( skinnable, contentsRect, subControl ); } @@ -120,6 +124,35 @@ QRectF QskSegmentedBarSkinlet::cursorRect( return cursorRect; } +QRectF QskSegmentedBarSkinlet::splashRect( + const QskSegmentedBar* bar, const QRectF& contentsRect ) const +{ + using Q = QskSegmentedBar; + + QRectF rect; + + const auto ratio = bar->metric( Q::Splash | QskAspect::Size ); + + if ( ratio > 0.0 ) + { + const auto pos = bar->effectiveSkinHint( + Q::Splash | QskAspect::Metric | QskAspect::Position ).toPointF(); + + const int index = bar->indexAtPosition( pos ); + + if( index >= 0 && index < bar->count() ) + { + const auto sr = segmentRect( bar, contentsRect, index ); + rect = sr; + rect.setSize( { 2.0 * rect.width() * ratio, rect.height() * 2.0 } ); + rect.moveCenter( pos ); + rect = rect.intersected( sr ); + } + } + + return rect; +} + QRectF QskSegmentedBarSkinlet::segmentRect( const QskSegmentedBar* bar, const QRectF& contentsRect, int index ) const { @@ -183,11 +216,16 @@ QSGNode* QskSegmentedBarSkinlet::updateSubNode( { using Q = QskSegmentedBar; + const auto bar = static_cast< const QskSegmentedBar* >( skinnable ); + switch( nodeRole ) { case CursorRole: return updateBoxNode( skinnable, node, Q::Cursor ); + case SplashRole: + return updateSplashNode( bar, node ); + case PanelRole: return updateBoxNode( skinnable, node, Q::Panel ); @@ -387,4 +425,32 @@ QSGNode* QskSegmentedBarSkinlet::updateSampleNode( const QskSkinnable* skinnable return Inherited::updateSampleNode( skinnable, subControl, index, node ); } +QSGNode* QskSegmentedBarSkinlet::updateSplashNode( + const QskSegmentedBar* bar, QSGNode* node ) const +{ + using Q = QskSegmentedBar; + + const auto splashRect = bar->subControlRect( Q::Splash ); + if ( splashRect.isEmpty() ) + return nullptr; + + auto clipNode = updateBoxClipNode( bar, node, + bar->subControlRect( Q::Cursor ), Q::Cursor ); + + if ( clipNode ) + { + auto boxNode = QskSGNode::findChildNode( clipNode, SplashRole ); + boxNode = updateBoxNode( bar, boxNode, splashRect, Q::Splash ); + + if ( boxNode == nullptr ) + return nullptr; + + QskSGNode::setNodeRole( boxNode, SplashRole ); + if ( boxNode->parent() != clipNode ) + clipNode->appendChildNode( boxNode ); + } + + return clipNode; +} + #include "moc_QskSegmentedBarSkinlet.cpp" diff --git a/src/controls/QskSegmentedBarSkinlet.h b/src/controls/QskSegmentedBarSkinlet.h index a2a0a055..15fa1d39 100644 --- a/src/controls/QskSegmentedBarSkinlet.h +++ b/src/controls/QskSegmentedBarSkinlet.h @@ -23,6 +23,7 @@ class QSK_EXPORT QskSegmentedBarSkinlet : public QskSkinlet SegmentRole, SeparatorRole, CursorRole, + SplashRole, TextRole, IconRole, @@ -60,6 +61,9 @@ class QSK_EXPORT QskSegmentedBarSkinlet : public QskSkinlet QRectF segmentRect( const QskSegmentedBar*, const QRectF&, int index ) const; QRectF separatorRect( const QskSegmentedBar*, const QRectF&, int index ) const; QRectF cursorRect( const QskSegmentedBar*, const QRectF& ) const; + QRectF splashRect( const QskSegmentedBar*, const QRectF& ) const; + + QSGNode* updateSplashNode( const QskSegmentedBar*, QSGNode* ) const; }; #endif From 636f548fed036d5f571bf5362b27387a0ffb179b Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Sun, 5 Feb 2023 16:01:30 +0100 Subject: [PATCH 34/60] segmented bar: Add Pressed state and style also for Hovered --- skins/material3/QskMaterial3Skin.cpp | 1 + src/controls/QskSegmentedBar.cpp | 5 +++-- src/controls/QskSegmentedBar.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index a1a404de..1fcb1d27 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -566,6 +566,7 @@ void Editor::setupSegmentedBar() setGradient( Q::Cursor, m_pal.secondaryContainer ); setGradient( Q::Cursor | Q::Disabled, m_pal.onSurface12 ); + setGradient( Q::Cursor | Q::Hovered, stateLayerColor( m_pal.onSurface, m_pal.hoverOpacity ) ); setBoxBorderMetrics( Q::Cursor, 1_dp ); setBoxBorderColors( Q::Cursor, Qt::transparent ); diff --git a/src/controls/QskSegmentedBar.cpp b/src/controls/QskSegmentedBar.cpp index 78ab401f..c3b88654 100644 --- a/src/controls/QskSegmentedBar.cpp +++ b/src/controls/QskSegmentedBar.cpp @@ -24,7 +24,8 @@ QSK_SUBCONTROL( QskSegmentedBar, Cursor ) QSK_SUBCONTROL( QskSegmentedBar, Text ) QSK_SUBCONTROL( QskSegmentedBar, Icon ) -QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState << 1 ) +QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState ) +QSK_SYSTEM_STATE( QskSegmentedBar, Pressed, QskAspect::FirstSystemState << 1 ) QSK_SYSTEM_STATE( QskSegmentedBar, Minimum, QskAspect::FirstSystemState << 2 ) QSK_SYSTEM_STATE( QskSegmentedBar, Maximum, QskAspect::FirstSystemState << 3 ) @@ -172,7 +173,7 @@ void QskSegmentedBar::mousePressEvent( QMouseEvent* event ) if( hint.isValid() ) { - setSkinHint( Splash | A::Metric | A::Position, event->pos() ); + setSkinHint( Splash | A::Metric | A::Position, qskMousePosition( event ) ); startTransition( Splash | A::Metric | A::Size, hint, 0.0, 1.0 ); } } diff --git a/src/controls/QskSegmentedBar.h b/src/controls/QskSegmentedBar.h index c48e6b66..93ba1486 100644 --- a/src/controls/QskSegmentedBar.h +++ b/src/controls/QskSegmentedBar.h @@ -37,7 +37,7 @@ class QSK_EXPORT QskSegmentedBar : public QskControl public: QSK_SUBCONTROLS( Panel, Splash, Segment, Separator, Cursor, Text, Icon ) - QSK_STATES( Selected, Minimum, Maximum ) + QSK_STATES( Selected, Pressed, Minimum, Maximum ) QskSegmentedBar( QQuickItem* parent = nullptr ); QskSegmentedBar( Qt::Orientation, QQuickItem* parent = nullptr ); From acb225bb8254bfc47e48edc0353adb40b699fe3d Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Fri, 10 Feb 2023 14:14:57 +0100 Subject: [PATCH 35/60] segmented bar: support hovered state --- skins/material3/QskMaterial3Skin.cpp | 17 +++++++++++ src/controls/QskSegmentedBar.cpp | 26 +++++++++++++++++ src/controls/QskSegmentedBar.h | 4 +++ src/controls/QskSegmentedBarSkinlet.cpp | 39 +++++++++++++++++++++++-- 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 1fcb1d27..52d81277 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -530,8 +530,25 @@ void Editor::setupSegmentedBar() setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize ); setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() ); setGradient( Q::Segment, Qt::transparent ); + setGradient( Q::Segment | Q::Hovered, m_pal.onSurface12, + { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum | Q::Selected } ); setPadding( Q::Segment | A::Horizontal, 12_dp, 0, 12_dp, 0 ); setPadding( Q::Segment | A::Vertical, 0, 12_dp, 0, 12_dp ); + + setBoxShape( Q::Segment, 0 ); + setBoxShape( Q::Segment | Q::Minimum | A::Horizontal, + { 100, 0, 100, 0, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Disabled } ); + setBoxShape( Q::Segment | Q::Maximum | A::Horizontal, + { 0, 100, 0, 100, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Disabled } ); + + setBoxShape( Q::Segment | Q::Minimum | A::Vertical, + { 100, 100, 0, 0, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Disabled } ); + setBoxShape( Q::Segment | Q::Maximum | A::Vertical, + { 0, 0, 100, 100, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Disabled } ); } { diff --git a/src/controls/QskSegmentedBar.cpp b/src/controls/QskSegmentedBar.cpp index c3b88654..493f1b4e 100644 --- a/src/controls/QskSegmentedBar.cpp +++ b/src/controls/QskSegmentedBar.cpp @@ -56,6 +56,8 @@ QskSegmentedBar::QskSegmentedBar( Qt::Orientation orientation, QQuickItem* paren : Inherited( parent ) , m_data( new PrivateData( orientation ) ) { + setAcceptHoverEvents( true ); + if( orientation == Qt::Horizontal ) initSizePolicy( QskSizePolicy::MinimumExpanding, QskSizePolicy::Fixed ); else @@ -273,6 +275,30 @@ void QskSegmentedBar::keyReleaseEvent( QKeyEvent* event ) Inherited::keyReleaseEvent( event ); } +void QskSegmentedBar::hoverEnterEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( Segment | A::Metric | A::Position, qskHoverPosition( event ) ); + update(); +} + +void QskSegmentedBar::hoverMoveEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( Segment | A::Metric | A::Position, qskHoverPosition( event ) ); + update(); +} + +void QskSegmentedBar::hoverLeaveEvent( QHoverEvent* event ) +{ + using A = QskAspect; + + setSkinHint( Segment | A::Metric | A::Position, QPointF() ); + update(); +} + void QskSegmentedBar::focusInEvent( QFocusEvent* event ) { int index = m_data->currentIndex; diff --git a/src/controls/QskSegmentedBar.h b/src/controls/QskSegmentedBar.h index 93ba1486..790de3c2 100644 --- a/src/controls/QskSegmentedBar.h +++ b/src/controls/QskSegmentedBar.h @@ -94,6 +94,10 @@ class QSK_EXPORT QskSegmentedBar : public QskControl void keyPressEvent( QKeyEvent* ) override; void keyReleaseEvent( QKeyEvent* ) override; + void hoverEnterEvent( QHoverEvent* ) override; + void hoverMoveEvent( QHoverEvent* ) override; + void hoverLeaveEvent( QHoverEvent* ) override; + void focusInEvent( QFocusEvent* ) override; private: diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index 4632f746..5905263a 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -355,13 +355,46 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates( const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const { using Q = QskSegmentedBar; + using A = QskAspect; auto states = Inherited::sampleStates( skinnable, subControl, index ); - if ( subControl == Q::Segment || subControl == Q::Icon || subControl == Q::Text ) - { - const auto bar = static_cast< const QskSegmentedBar* >( skinnable ); + const auto* bar = static_cast< const QskSegmentedBar* >( skinnable ); + if ( subControl == Q::Segment ) + { + const auto cursorPos = bar->effectiveSkinHint( Q::Segment | A::Metric | A::Position ).toPointF(); + + if( !cursorPos.isNull() && bar->indexAtPosition( cursorPos ) == index ) + { + states |= Q::Hovered; + } + else + { + states &= ~Q::Hovered; + } + + if( bar->count() > 0 ) + { + if( index == 0 ) + { + states &= ~Q::Maximum; + states |= Q::Minimum; + } + else if( index == bar->count() - 1 ) + { + states &= ~Q::Minimum; + states |= Q::Maximum; + } + else + { + states &= ~Q::Minimum; + states &= ~Q::Maximum; + } + } + } + else if( subControl == Q::Icon || subControl == Q::Text || subControl == Q::Cursor ) + { if ( bar->isSegmentEnabled( index ) ) { if ( bar->selectedIndex() == index ) From caba0d57353fba069b91a1d892bdfbadade85069 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 27 Mar 2023 14:05:45 +0200 Subject: [PATCH 36/60] segmented bar: Support focus --- skins/material3/QskMaterial3Skin.cpp | 63 ++++++++++++------------ src/common/QskAspect.h | 2 +- src/controls/QskSegmentedBar.cpp | 64 ++++++++++++++++++------- src/controls/QskSegmentedBar.h | 2 + src/controls/QskSegmentedBarSkinlet.cpp | 34 +++++++++++-- 5 files changed, 109 insertions(+), 56 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 52d81277..3feca7d4 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -500,7 +500,6 @@ void Editor::setupFocusIndicator() void Editor::setupSegmentedBar() { - // copied from Squiek: we need something similar to a tab bar here. TODO ... using A = QskAspect; using Q = QskSegmentedBar; @@ -518,6 +517,7 @@ void Editor::setupSegmentedBar() setBoxBorderMetrics( Q::Panel, 1_dp ); setBoxBorderColors( Q::Panel, m_pal.outline ); + setBoxBorderColors( Q::Panel | Q::Disabled, m_pal.onSurface12 ); setStrutSize( Q::Panel | A::Horizontal, panelStrutSize ); @@ -529,13 +529,40 @@ void Editor::setupSegmentedBar() setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize ); setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() ); - setGradient( Q::Segment, Qt::transparent ); - setGradient( Q::Segment | Q::Hovered, m_pal.onSurface12, - { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum | Q::Selected } ); + + setBoxBorderMetrics( Q::Segment | A::Horizontal, { 0, 1_dp, 0, 1_dp } ); + setBoxBorderMetrics( Q::Segment | Q::Minimum | A::Horizontal, { 1_dp, 1_dp, 0, 1_dp } ); + setBoxBorderMetrics( Q::Segment | Q::Maximum | A::Horizontal, { 0, 1_dp, 1_dp, 1_dp } ); + + setBoxBorderMetrics( Q::Segment | A::Vertical, { 1_dp, 0, 1_dp, 0 } ); + setBoxBorderMetrics( Q::Segment | Q::Minimum | A::Vertical, { 1_dp, 1_dp, 1_dp, 0 } ); + setBoxBorderMetrics( Q::Segment | Q::Maximum | A::Vertical, { 1_dp, 0, 1_dp, 1_dp } ); + + setBoxBorderColors( Q::Segment, Qt::transparent ); + + setGradient( Q::Segment | Q::Hovered, m_pal.onSurface8, + { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + + setGradient( Q::Segment | Q::Focused, m_pal.onSurface12, + { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + + setGradient( Q::Segment | Q::Selected, m_pal.secondaryContainer, + { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + setGradient( Q::Segment | Q::Selected | Q::Hovered, + flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.hoverOpacity ), + { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + setGradient( Q::Segment | Q::Selected | Q::Focused, + flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.focusOpacity ), + { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + + setGradient( Q::Segment | Q::Selected | Q::Disabled, m_pal.onSurface12, + { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + setPadding( Q::Segment | A::Horizontal, 12_dp, 0, 12_dp, 0 ); setPadding( Q::Segment | A::Vertical, 0, 12_dp, 0, 12_dp ); setBoxShape( Q::Segment, 0 ); + setBoxShape( Q::Segment | Q::Minimum | A::Horizontal, { 100, 0, 100, 0, Qt::RelativeSize }, { QskStateCombination::CombinationNoState, Q::Disabled } ); @@ -561,34 +588,6 @@ void Editor::setupSegmentedBar() setColor( Q::Separator | Q::Disabled, m_pal.onSurface12 ); } - { - // Cursor - setBoxShape( Q::Cursor, 0 ); - - setBoxShape( Q::Cursor | Q::Minimum | A::Horizontal, - { 100, 0, 100, 0, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - - setBoxShape( Q::Cursor | Q::Maximum | A::Horizontal, - { 0, 100, 0, 100, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - - setBoxShape( Q::Cursor | Q::Minimum | A::Vertical, - { 100, 100, 0, 0, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - - setBoxShape( Q::Cursor | Q::Maximum | A::Vertical, - { 0, 0, 100, 100, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - - setGradient( Q::Cursor, m_pal.secondaryContainer ); - setGradient( Q::Cursor | Q::Disabled, m_pal.onSurface12 ); - setGradient( Q::Cursor | Q::Hovered, stateLayerColor( m_pal.onSurface, m_pal.hoverOpacity ) ); - - setBoxBorderMetrics( Q::Cursor, 1_dp ); - setBoxBorderColors( Q::Cursor, Qt::transparent ); - } - { // Splash setBoxShape( Q::Splash, 20_dp ); diff --git a/src/common/QskAspect.h b/src/common/QskAspect.h index 8503627a..4c20c13f 100644 --- a/src/common/QskAspect.h +++ b/src/common/QskAspect.h @@ -111,7 +111,7 @@ class QSK_EXPORT QskAspect NoState = 0, FirstSystemState = 1 << 0, - FirstUserState = 1 << 4, + FirstUserState = 1 << 5, LastUserState = 1 << 11, LastSystemState = 1 << 15, diff --git a/src/controls/QskSegmentedBar.cpp b/src/controls/QskSegmentedBar.cpp index 493f1b4e..abea3ba2 100644 --- a/src/controls/QskSegmentedBar.cpp +++ b/src/controls/QskSegmentedBar.cpp @@ -24,10 +24,10 @@ QSK_SUBCONTROL( QskSegmentedBar, Cursor ) QSK_SUBCONTROL( QskSegmentedBar, Text ) QSK_SUBCONTROL( QskSegmentedBar, Icon ) -QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState ) -QSK_SYSTEM_STATE( QskSegmentedBar, Pressed, QskAspect::FirstSystemState << 1 ) -QSK_SYSTEM_STATE( QskSegmentedBar, Minimum, QskAspect::FirstSystemState << 2 ) -QSK_SYSTEM_STATE( QskSegmentedBar, Maximum, QskAspect::FirstSystemState << 3 ) +QSK_SYSTEM_STATE( QskSegmentedBar, Minimum, QskAspect::FirstSystemState << 1 ) +QSK_SYSTEM_STATE( QskSegmentedBar, Maximum, QskAspect::FirstSystemState << 2 ) +QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState << 3 ) +QSK_SYSTEM_STATE( QskSegmentedBar, Pressed, QskAspect::FirstSystemState << 4 ) class QskSegmentedBar::PrivateData { @@ -42,6 +42,7 @@ class QskSegmentedBar::PrivateData int selectedIndex = -1; int currentIndex = -1; + int focusedIndex = -1; Qt::Orientation orientation; bool isPressed = false; @@ -166,7 +167,10 @@ void QskSegmentedBar::mousePressEvent( QMouseEvent* event ) if( !QGuiApplication::styleHints()->setFocusOnTouchRelease() ) { if( index != m_data->currentIndex ) + { setCurrentIndex( index ); + setFocusedIndex( index ); + } } } } @@ -226,11 +230,12 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event ) else forwards = ( event->key() == Qt::Key_Right ); - const int index = nextIndex( m_data->selectedIndex, forwards ); - if ( index != m_data->selectedIndex ) + const int index = nextIndex( m_data->focusedIndex, forwards ); + + if ( index != m_data->focusedIndex ) { if ( index >= 0 && index < count() ) - setSelectedIndex( index ); + setFocusedIndex( index ); } return; @@ -238,9 +243,11 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event ) case Qt::Key_Select: case Qt::Key_Space: - + { + setCurrentIndex( m_data->focusedIndex ); // stop further processing return; + } default: { @@ -248,10 +255,10 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event ) if( steps != 0 ) { - const int index = nextIndex( m_data->currentIndex, steps > 0 ); + const int index = nextIndex( m_data->focusedIndex, steps > 0 ); - if( index != m_data->currentIndex ) - setCurrentIndex( index ); + if( index != m_data->focusedIndex ) + setFocusedIndex( index ); if( index >= 0 ) return; @@ -279,7 +286,7 @@ void QskSegmentedBar::hoverEnterEvent( QHoverEvent* event ) { using A = QskAspect; - setSkinHint( Segment | A::Metric | A::Position, qskHoverPosition( event ) ); + setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); update(); } @@ -287,21 +294,21 @@ void QskSegmentedBar::hoverMoveEvent( QHoverEvent* event ) { using A = QskAspect; - setSkinHint( Segment | A::Metric | A::Position, qskHoverPosition( event ) ); + setSkinHint( Segment | Hovered | A::Metric | A::Position, qskHoverPosition( event ) ); update(); } -void QskSegmentedBar::hoverLeaveEvent( QHoverEvent* event ) +void QskSegmentedBar::hoverLeaveEvent( QHoverEvent* ) { using A = QskAspect; - setSkinHint( Segment | A::Metric | A::Position, QPointF() ); + setSkinHint( Segment | Hovered | A::Metric | A::Position, QPointF() ); update(); } void QskSegmentedBar::focusInEvent( QFocusEvent* event ) { - int index = m_data->currentIndex; + int index = m_data->focusedIndex; switch( event->reason() ) { @@ -324,12 +331,20 @@ void QskSegmentedBar::focusInEvent( QFocusEvent* event ) } } - if( index != m_data->currentIndex ) - setCurrentIndex( index ); + if( index != m_data->focusedIndex ) + setFocusedIndex( index ); Inherited::focusInEvent( event ); } +void QskSegmentedBar::focusOutEvent( QFocusEvent* event ) +{ + setFocusedIndex( -1 ); + update(); + + Inherited::focusOutEvent( event ); +} + void QskSegmentedBar::clear() { if( count() == 0 ) @@ -495,4 +510,17 @@ QRectF QskSegmentedBar::focusIndicatorRect() const return Inherited::focusIndicatorRect(); } +void QskSegmentedBar::setFocusedIndex( int index ) +{ + if ( m_data->focusedIndex == index ) + return; + + m_data->focusedIndex = index; + setPositionHint( Segment | Focused, index ); + + update(); + + Q_EMIT focusIndicatorRectChanged(); +} + #include "moc_QskSegmentedBar.cpp" diff --git a/src/controls/QskSegmentedBar.h b/src/controls/QskSegmentedBar.h index 790de3c2..e932d058 100644 --- a/src/controls/QskSegmentedBar.h +++ b/src/controls/QskSegmentedBar.h @@ -99,9 +99,11 @@ class QSK_EXPORT QskSegmentedBar : public QskControl void hoverLeaveEvent( QHoverEvent* ) override; void focusInEvent( QFocusEvent* ) override; + void focusOutEvent( QFocusEvent* ) override; private: int nextIndex( int index, bool forward ) const; + void setFocusedIndex( int ); class PrivateData; std::unique_ptr< PrivateData > m_data; diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index 5905263a..80595f4a 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -196,7 +196,7 @@ QRectF QskSegmentedBarSkinlet::separatorRect( if( bar->orientation() == Qt::Horizontal ) { - rect.setLeft( rect.right() ); // ### *0.5 or so? + rect.setLeft( rect.right() ); rect.setSize( { strutSize.width(), sh.height() } ); } else @@ -361,9 +361,19 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates( const auto* bar = static_cast< const QskSegmentedBar* >( skinnable ); - if ( subControl == Q::Segment ) + if ( subControl == Q::Segment || subControl == Q::Cursor ) { - const auto cursorPos = bar->effectiveSkinHint( Q::Segment | A::Metric | A::Position ).toPointF(); + if ( bar->isSegmentEnabled( index ) ) + { + if ( bar->selectedIndex() == index ) + states |= Q::Selected; + } + else + { + states |= Q::Disabled; + } + + const auto cursorPos = bar->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); if( !cursorPos.isNull() && bar->indexAtPosition( cursorPos ) == index ) { @@ -374,6 +384,20 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates( states &= ~Q::Hovered; } + const auto focusIndex = bar->positionHint( Q::Segment | Q::Focused ); + + if( focusIndex >= 0 && focusIndex < bar->count() ) + { + if( focusIndex == index ) + { + states |= Q::Focused; + } + else + { + states &= ~Q::Focused; + } + } + if( bar->count() > 0 ) { if( index == 0 ) @@ -393,7 +417,7 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates( } } } - else if( subControl == Q::Icon || subControl == Q::Text || subControl == Q::Cursor ) + else if( subControl == Q::Icon || subControl == Q::Text ) { if ( bar->isSegmentEnabled( index ) ) { @@ -418,7 +442,7 @@ QSGNode* QskSegmentedBarSkinlet::updateSampleNode( const QskSkinnable* skinnable const auto rect = sampleRect( bar, bar->contentsRect(), subControl, index ); - if ( subControl == Q::Segment || subControl == Q::Separator ) + if ( subControl == Q::Segment || subControl == Q::Separator || subControl == Q::Cursor ) { return updateBoxNode( skinnable, node, rect, subControl ); } From 824802a1dc193a9692a72278d2ecef6a425263a4 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 10 Apr 2023 12:17:01 +0200 Subject: [PATCH 37/60] segmented bar: use Minimum / Maximum states only for subcontrols --- src/controls/QskSegmentedBar.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/controls/QskSegmentedBar.cpp b/src/controls/QskSegmentedBar.cpp index abea3ba2..9b3e7980 100644 --- a/src/controls/QskSegmentedBar.cpp +++ b/src/controls/QskSegmentedBar.cpp @@ -408,9 +408,6 @@ void QskSegmentedBar::setSelectedIndex( int index ) Q_EMIT selectedIndexChanged( index ); - setSkinStateFlag( Minimum, ( m_data->selectedIndex == 0 ) ); - setSkinStateFlag( Maximum, ( m_data->selectedIndex == count() - 1 ) ); - const auto states = skinStates(); if ( oldIndex >= 0 ) From bfa8df85d5c630f52538ae5fb6680e0f70a67956 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Wed, 12 Apr 2023 16:31:35 +0200 Subject: [PATCH 38/60] segmented bar: Improve splash --- skins/material3/QskMaterial3Skin.cpp | 33 +++++++++++++------------ src/controls/QskSegmentedBarSkinlet.cpp | 22 +++++++++++++++-- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 3feca7d4..f466ca41 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -525,7 +525,7 @@ void Editor::setupSegmentedBar() } { - // Segment + // Segment / Splash setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize ); setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() ); @@ -561,21 +561,22 @@ void Editor::setupSegmentedBar() setPadding( Q::Segment | A::Horizontal, 12_dp, 0, 12_dp, 0 ); setPadding( Q::Segment | A::Vertical, 0, 12_dp, 0, 12_dp ); - setBoxShape( Q::Segment, 0 ); + for( const auto subcontrol : { Q::Segment, Q::Splash } ) + { + setBoxShape( subcontrol | Q::Minimum | A::Horizontal, + { 100, 0, 100, 0, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Disabled } ); + setBoxShape( subcontrol | Q::Maximum | A::Horizontal, + { 0, 100, 0, 100, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Disabled } ); - setBoxShape( Q::Segment | Q::Minimum | A::Horizontal, - { 100, 0, 100, 0, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - setBoxShape( Q::Segment | Q::Maximum | A::Horizontal, - { 0, 100, 0, 100, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - - setBoxShape( Q::Segment | Q::Minimum | A::Vertical, - { 100, 100, 0, 0, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - setBoxShape( Q::Segment | Q::Maximum | A::Vertical, - { 0, 0, 100, 100, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); + setBoxShape( subcontrol | Q::Minimum | A::Vertical, + { 100, 100, 0, 0, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Disabled } ); + setBoxShape( subcontrol | Q::Maximum | A::Vertical, + { 0, 0, 100, 100, Qt::RelativeSize }, + { QskStateCombination::CombinationNoState, Q::Disabled } ); + } } { @@ -590,7 +591,7 @@ void Editor::setupSegmentedBar() { // Splash - setBoxShape( Q::Splash, 20_dp ); + setGradient( Q::Splash, stateLayerColor( m_pal.onSecondaryContainer, m_pal.pressedOpacity ) ); setAnimation( Q::Splash | A::Color, qskDuration ); } diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index 80595f4a..fd0afff1 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -12,7 +12,7 @@ #include "QskFunctions.h" #include "QskSGNode.h" #include "QskSkin.h" -#include "QskStandardSymbol.h" +#include "QskSkinStateChanger.h" #include "QskSubcontrolLayoutEngine.h" #include @@ -144,7 +144,20 @@ QRectF QskSegmentedBarSkinlet::splashRect( { const auto sr = segmentRect( bar, contentsRect, index ); rect = sr; - rect.setSize( { 2.0 * rect.width() * ratio, rect.height() * 2.0 } ); + qreal w, h; + + if( bar->orientation() == Qt::Horizontal ) + { + w = 2.0 * rect.width() * ratio; + h = 2.0 * rect.height(); + } + else + { + w = 2.0 * rect.width(); + h = 2.0 * rect.height() * ratio; + } + + rect.setSize( { w, h } ); rect.moveCenter( pos ); rect = rect.intersected( sr ); } @@ -487,6 +500,11 @@ QSGNode* QskSegmentedBarSkinlet::updateSplashNode( { using Q = QskSegmentedBar; + // get Minimum / Maximum right: + QskSkinStateChanger stateChanger( bar ); + const auto states = sampleStates( bar, Q::Segment, bar->selectedIndex() ); + stateChanger.setStates( states ); + const auto splashRect = bar->subControlRect( Q::Splash ); if ( splashRect.isEmpty() ) return nullptr; From d33e1f1a90f3c74243669de7fa182d474a9a7113 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 5 Jul 2023 14:51:18 +0200 Subject: [PATCH 39/60] focus handling fixed --- src/controls/QskSegmentedBar.cpp | 46 +++++++++----------------------- src/controls/QskSegmentedBar.h | 1 - 2 files changed, 13 insertions(+), 34 deletions(-) diff --git a/src/controls/QskSegmentedBar.cpp b/src/controls/QskSegmentedBar.cpp index 9b3e7980..c2632b06 100644 --- a/src/controls/QskSegmentedBar.cpp +++ b/src/controls/QskSegmentedBar.cpp @@ -42,7 +42,6 @@ class QskSegmentedBar::PrivateData int selectedIndex = -1; int currentIndex = -1; - int focusedIndex = -1; Qt::Orientation orientation; bool isPressed = false; @@ -167,10 +166,7 @@ void QskSegmentedBar::mousePressEvent( QMouseEvent* event ) if( !QGuiApplication::styleHints()->setFocusOnTouchRelease() ) { if( index != m_data->currentIndex ) - { setCurrentIndex( index ); - setFocusedIndex( index ); - } } } } @@ -230,12 +226,11 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event ) else forwards = ( event->key() == Qt::Key_Right ); - const int index = nextIndex( m_data->focusedIndex, forwards ); - - if ( index != m_data->focusedIndex ) + const int index = nextIndex( m_data->selectedIndex, forwards ); + if ( index != m_data->selectedIndex ) { if ( index >= 0 && index < count() ) - setFocusedIndex( index ); + setSelectedIndex( index ); } return; @@ -243,11 +238,9 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event ) case Qt::Key_Select: case Qt::Key_Space: - { - setCurrentIndex( m_data->focusedIndex ); + // stop further processing return; - } default: { @@ -255,10 +248,10 @@ void QskSegmentedBar::keyPressEvent( QKeyEvent* event ) if( steps != 0 ) { - const int index = nextIndex( m_data->focusedIndex, steps > 0 ); + const int index = nextIndex( m_data->currentIndex, steps > 0 ); - if( index != m_data->focusedIndex ) - setFocusedIndex( index ); + if( index != m_data->currentIndex ) + setCurrentIndex( index ); if( index >= 0 ) return; @@ -308,7 +301,7 @@ void QskSegmentedBar::hoverLeaveEvent( QHoverEvent* ) void QskSegmentedBar::focusInEvent( QFocusEvent* event ) { - int index = m_data->focusedIndex; + int index = m_data->currentIndex; switch( event->reason() ) { @@ -331,17 +324,15 @@ void QskSegmentedBar::focusInEvent( QFocusEvent* event ) } } - if( index != m_data->focusedIndex ) - setFocusedIndex( index ); + if( index != m_data->currentIndex ) + setCurrentIndex( index ); Inherited::focusInEvent( event ); } void QskSegmentedBar::focusOutEvent( QFocusEvent* event ) { - setFocusedIndex( -1 ); - update(); - + setCurrentIndex( -1 ); Inherited::focusOutEvent( event ); } @@ -376,6 +367,8 @@ void QskSegmentedBar::setCurrentIndex( int index ) if( index != m_data->currentIndex ) { m_data->currentIndex = index; + setPositionHint( Segment | Focused, index ); + Q_EMIT currentIndexChanged( index ); } } @@ -507,17 +500,4 @@ QRectF QskSegmentedBar::focusIndicatorRect() const return Inherited::focusIndicatorRect(); } -void QskSegmentedBar::setFocusedIndex( int index ) -{ - if ( m_data->focusedIndex == index ) - return; - - m_data->focusedIndex = index; - setPositionHint( Segment | Focused, index ); - - update(); - - Q_EMIT focusIndicatorRectChanged(); -} - #include "moc_QskSegmentedBar.cpp" diff --git a/src/controls/QskSegmentedBar.h b/src/controls/QskSegmentedBar.h index e932d058..67582faf 100644 --- a/src/controls/QskSegmentedBar.h +++ b/src/controls/QskSegmentedBar.h @@ -103,7 +103,6 @@ class QSK_EXPORT QskSegmentedBar : public QskControl private: int nextIndex( int index, bool forward ) const; - void setFocusedIndex( int ); class PrivateData; std::unique_ptr< PrivateData > m_data; From 4bf1b019c7f3cb6b5f63099e0f6a42bc0a884df7 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 5 Jul 2023 18:28:57 +0200 Subject: [PATCH 40/60] QskSegmentedBarSkinlet fixes --- skins/fluent2/QskFluent2Skin.cpp | 4 +- skins/material3/QskMaterial3Skin.cpp | 49 ++-------- src/controls/QskSegmentedBar.cpp | 6 +- src/controls/QskSegmentedBar.h | 2 +- src/controls/QskSegmentedBarSkinlet.cpp | 121 ++++++++++++++++++------ 5 files changed, 105 insertions(+), 77 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 3ea8864d..09dbda04 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -1180,7 +1180,7 @@ void Editor::setupSegmentedBarColors( graphicRole = W::GraphicRoleFillColorTextPrimary; } - else if ( states & Q::Hovered ) + else if ( states == Q::Hovered ) { segmentColor = pal.fillColor.control.secondary; borderColor1 = pal.elevation.control.border[0]; @@ -1206,7 +1206,7 @@ void Editor::setupSegmentedBarColors( graphicRole = W::GraphicRoleFillColorTextOnAccentPrimary; } - else if ( states == Q::Disabled ) + else if ( states & Q::Disabled ) { segmentColor = pal.fillColor.control.disabled; borderColor1 = borderColor2 = pal.strokeColor.control.defaultColor; diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index f466ca41..c59f83fd 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -522,6 +522,8 @@ void Editor::setupSegmentedBar() setStrutSize( Q::Panel | A::Horizontal, panelStrutSize ); setStrutSize( Q::Panel | A::Vertical, panelStrutSize.transposed() ); + + setFlag( Q::Panel | A::Option, true ); // adjust segments to the panel radius } { @@ -530,53 +532,20 @@ void Editor::setupSegmentedBar() setStrutSize( Q::Segment | A::Horizontal, segmentStrutSize ); setStrutSize( Q::Segment | A::Vertical, segmentStrutSize.transposed() ); - setBoxBorderMetrics( Q::Segment | A::Horizontal, { 0, 1_dp, 0, 1_dp } ); - setBoxBorderMetrics( Q::Segment | Q::Minimum | A::Horizontal, { 1_dp, 1_dp, 0, 1_dp } ); - setBoxBorderMetrics( Q::Segment | Q::Maximum | A::Horizontal, { 0, 1_dp, 1_dp, 1_dp } ); + setGradient( Q::Segment | Q::Hovered, m_pal.onSurface8 ); + setGradient( Q::Segment | Q::Focused, m_pal.onSurface12 ); + setGradient( Q::Segment | Q::Selected, m_pal.secondaryContainer ); - setBoxBorderMetrics( Q::Segment | A::Vertical, { 1_dp, 0, 1_dp, 0 } ); - setBoxBorderMetrics( Q::Segment | Q::Minimum | A::Vertical, { 1_dp, 1_dp, 1_dp, 0 } ); - setBoxBorderMetrics( Q::Segment | Q::Maximum | A::Vertical, { 1_dp, 0, 1_dp, 1_dp } ); - - setBoxBorderColors( Q::Segment, Qt::transparent ); - - setGradient( Q::Segment | Q::Hovered, m_pal.onSurface8, - { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); - - setGradient( Q::Segment | Q::Focused, m_pal.onSurface12, - { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); - - setGradient( Q::Segment | Q::Selected, m_pal.secondaryContainer, - { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); setGradient( Q::Segment | Q::Selected | Q::Hovered, - flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.hoverOpacity ), - { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.hoverOpacity ) ); + setGradient( Q::Segment | Q::Selected | Q::Focused, - flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.focusOpacity ), - { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.focusOpacity ) ); - setGradient( Q::Segment | Q::Selected | Q::Disabled, m_pal.onSurface12, - { QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } ); + setGradient( Q::Segment | Q::Selected | Q::Disabled, m_pal.onSurface12 ); setPadding( Q::Segment | A::Horizontal, 12_dp, 0, 12_dp, 0 ); setPadding( Q::Segment | A::Vertical, 0, 12_dp, 0, 12_dp ); - - for( const auto subcontrol : { Q::Segment, Q::Splash } ) - { - setBoxShape( subcontrol | Q::Minimum | A::Horizontal, - { 100, 0, 100, 0, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - setBoxShape( subcontrol | Q::Maximum | A::Horizontal, - { 0, 100, 0, 100, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - - setBoxShape( subcontrol | Q::Minimum | A::Vertical, - { 100, 100, 0, 0, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - setBoxShape( subcontrol | Q::Maximum | A::Vertical, - { 0, 0, 100, 100, Qt::RelativeSize }, - { QskStateCombination::CombinationNoState, Q::Disabled } ); - } } { diff --git a/src/controls/QskSegmentedBar.cpp b/src/controls/QskSegmentedBar.cpp index c2632b06..058b728f 100644 --- a/src/controls/QskSegmentedBar.cpp +++ b/src/controls/QskSegmentedBar.cpp @@ -24,10 +24,8 @@ QSK_SUBCONTROL( QskSegmentedBar, Cursor ) QSK_SUBCONTROL( QskSegmentedBar, Text ) QSK_SUBCONTROL( QskSegmentedBar, Icon ) -QSK_SYSTEM_STATE( QskSegmentedBar, Minimum, QskAspect::FirstSystemState << 1 ) -QSK_SYSTEM_STATE( QskSegmentedBar, Maximum, QskAspect::FirstSystemState << 2 ) -QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState << 3 ) -QSK_SYSTEM_STATE( QskSegmentedBar, Pressed, QskAspect::FirstSystemState << 4 ) +QSK_SYSTEM_STATE( QskSegmentedBar, Selected, QskAspect::FirstSystemState << 1 ) +QSK_SYSTEM_STATE( QskSegmentedBar, Pressed, QskAspect::FirstSystemState << 2 ) class QskSegmentedBar::PrivateData { diff --git a/src/controls/QskSegmentedBar.h b/src/controls/QskSegmentedBar.h index 67582faf..d65735a7 100644 --- a/src/controls/QskSegmentedBar.h +++ b/src/controls/QskSegmentedBar.h @@ -37,7 +37,7 @@ class QSK_EXPORT QskSegmentedBar : public QskControl public: QSK_SUBCONTROLS( Panel, Splash, Segment, Separator, Cursor, Text, Icon ) - QSK_STATES( Selected, Pressed, Minimum, Maximum ) + QSK_STATES( Selected, Pressed ) QskSegmentedBar( QQuickItem* parent = nullptr ); QskSegmentedBar( Qt::Orientation, QQuickItem* parent = nullptr ); diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index fd0afff1..1feaa9b8 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -14,19 +14,81 @@ #include "QskSkin.h" #include "QskSkinStateChanger.h" #include "QskSubcontrolLayoutEngine.h" +#include "QskBoxHints.h" #include #include namespace { + QskBoxHints effectiveBoxHints( QskAspect::Subcontrol subControl, + const QskSegmentedBar* bar, int index ) + { + using Q = QskSegmentedBar; + + auto boxHints = bar->boxHints( subControl ); + + const bool leading = ( index == 0 ); + const bool trailing = ( index == bar->count() - 1 ); + + if ( !( leading || trailing ) ) + return boxHints; + + // something more expressive than just a boolean. TODO ... + if ( !bar->flagHint< bool >( Q::Panel | QskAspect::Option, false ) ) + return boxHints; + + const auto panelShape = bar->boxShapeHint( Q::Panel ); + auto& shape = boxHints.shape; + + // when there is only 1 segment we have to fit both ends + + if ( leading ) + { + Qt::Corner corners[2]; + + corners[0] = Qt::TopLeftCorner; + + if ( bar->orientation() == Qt::Vertical ) + corners[1] = Qt::TopRightCorner; + else + corners[1] = Qt::BottomLeftCorner; + + shape.setSizeMode( panelShape.sizeMode() ); + shape.setRadius( corners[0], panelShape.radius( corners[0] ) ); + shape.setRadius( corners[1], panelShape.radius( corners[1] ) ); + } + + if ( trailing ) + { + Qt::Corner corners[2]; + + corners[0] = Qt::BottomRightCorner; + + if ( bar->orientation() == Qt::Vertical ) + corners[1] = Qt::BottomLeftCorner; + else + corners[1] = Qt::TopRightCorner; + + shape.setSizeMode( panelShape.sizeMode() ); + shape.setRadius( corners[0], panelShape.radius( corners[0] ) ); + shape.setRadius( corners[1], panelShape.radius( corners[1] ) ); + } + + boxHints.borderMetrics = bar->boxBorderMetricsHint( Q::Panel ); + boxHints.borderColors = QColor(); + + return boxHints; + } + + QskGraphic iconAt( const QskSegmentedBar* bar, const int index ) { using Q = QskSegmentedBar; if ( bar->selectedIndex() == index ) { - /* + /* Material 3 replaces the icon of the selected element by a checkmark, when icon and text are set. So this code is actually not correct as it also replaces the icon when there is no text @@ -386,7 +448,8 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates( states |= Q::Disabled; } - const auto cursorPos = bar->effectiveSkinHint( Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); + const auto cursorPos = bar->effectiveSkinHint( + Q::Segment | Q::Hovered | A::Metric | A::Position ).toPointF(); if( !cursorPos.isNull() && bar->indexAtPosition( cursorPos ) == index ) { @@ -410,25 +473,6 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates( states &= ~Q::Focused; } } - - if( bar->count() > 0 ) - { - if( index == 0 ) - { - states &= ~Q::Maximum; - states |= Q::Minimum; - } - else if( index == bar->count() - 1 ) - { - states &= ~Q::Minimum; - states |= Q::Maximum; - } - else - { - states &= ~Q::Minimum; - states &= ~Q::Maximum; - } - } } else if( subControl == Q::Icon || subControl == Q::Text ) { @@ -455,11 +499,17 @@ QSGNode* QskSegmentedBarSkinlet::updateSampleNode( const QskSkinnable* skinnable const auto rect = sampleRect( bar, bar->contentsRect(), subControl, index ); - if ( subControl == Q::Segment || subControl == Q::Separator || subControl == Q::Cursor ) + if ( subControl == Q::Separator ) { return updateBoxNode( skinnable, node, rect, subControl ); } + if ( subControl == Q::Segment ) + { + const auto boxHints = effectiveBoxHints( subControl, bar, index ); + return updateBoxNode( bar, node, rect, boxHints ); + } + const auto alignment = bar->alignmentHint( subControl, Qt::AlignCenter ); if ( subControl == Q::Text ) @@ -509,23 +559,34 @@ QSGNode* QskSegmentedBarSkinlet::updateSplashNode( if ( splashRect.isEmpty() ) return nullptr; - auto clipNode = updateBoxClipNode( bar, node, - bar->subControlRect( Q::Cursor ), Q::Cursor ); + auto panelClipNode = updateBoxClipNode( + bar, node, bar->subControlRect( Q::Panel ), Q::Panel ); - if ( clipNode ) + if ( panelClipNode ) { - auto boxNode = QskSGNode::findChildNode( clipNode, SplashRole ); + const auto segmentRect = sampleRect( + bar, bar->contentsRect(), Q::Segment, bar->selectedIndex() ); + + auto segmentClipNode = updateBoxClipNode( + bar, panelClipNode->firstChild(), segmentRect, Q::Segment ); + + if ( segmentClipNode == nullptr ) + return nullptr; + + if ( segmentClipNode->parent() == nullptr ) + panelClipNode->appendChildNode( segmentClipNode ); + + auto boxNode = segmentClipNode->firstChild(); boxNode = updateBoxNode( bar, boxNode, splashRect, Q::Splash ); if ( boxNode == nullptr ) return nullptr; - QskSGNode::setNodeRole( boxNode, SplashRole ); - if ( boxNode->parent() != clipNode ) - clipNode->appendChildNode( boxNode ); + if ( boxNode->parent() == nullptr ) + segmentClipNode->appendChildNode( boxNode ); } - return clipNode; + return panelClipNode; } #include "moc_QskSegmentedBarSkinlet.cpp" From 56c3481c42bb52bd7c632130639e6714d39027e2 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 5 Jul 2023 19:00:16 +0200 Subject: [PATCH 41/60] splash node clipping fixed --- src/controls/QskSegmentedBarSkinlet.cpp | 32 ++++--------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index 1feaa9b8..319d97ff 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -550,43 +550,21 @@ QSGNode* QskSegmentedBarSkinlet::updateSplashNode( { using Q = QskSegmentedBar; - // get Minimum / Maximum right: - QskSkinStateChanger stateChanger( bar ); - const auto states = sampleStates( bar, Q::Segment, bar->selectedIndex() ); - stateChanger.setStates( states ); - const auto splashRect = bar->subControlRect( Q::Splash ); if ( splashRect.isEmpty() ) return nullptr; - auto panelClipNode = updateBoxClipNode( + auto clipNode = updateBoxClipNode( bar, node, bar->subControlRect( Q::Panel ), Q::Panel ); - if ( panelClipNode ) + if ( clipNode ) { - const auto segmentRect = sampleRect( - bar, bar->contentsRect(), Q::Segment, bar->selectedIndex() ); - - auto segmentClipNode = updateBoxClipNode( - bar, panelClipNode->firstChild(), segmentRect, Q::Segment ); - - if ( segmentClipNode == nullptr ) - return nullptr; - - if ( segmentClipNode->parent() == nullptr ) - panelClipNode->appendChildNode( segmentClipNode ); - - auto boxNode = segmentClipNode->firstChild(); - boxNode = updateBoxNode( bar, boxNode, splashRect, Q::Splash ); - - if ( boxNode == nullptr ) - return nullptr; - + auto boxNode = updateBoxNode( bar, clipNode->firstChild(), splashRect, Q::Splash ); if ( boxNode->parent() == nullptr ) - segmentClipNode->appendChildNode( boxNode ); + clipNode->appendChildNode( boxNode ); } - return panelClipNode; + return clipNode; } #include "moc_QskSegmentedBarSkinlet.cpp" From 3fee4907c0f2a88b8bf5008ae18e94a61663d109 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 5 Jul 2023 19:04:57 +0200 Subject: [PATCH 42/60] Cursor is no series node --- src/controls/QskSegmentedBarSkinlet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controls/QskSegmentedBarSkinlet.cpp b/src/controls/QskSegmentedBarSkinlet.cpp index 319d97ff..17dc78ec 100644 --- a/src/controls/QskSegmentedBarSkinlet.cpp +++ b/src/controls/QskSegmentedBarSkinlet.cpp @@ -436,7 +436,7 @@ QskAspect::States QskSegmentedBarSkinlet::sampleStates( const auto* bar = static_cast< const QskSegmentedBar* >( skinnable ); - if ( subControl == Q::Segment || subControl == Q::Cursor ) + if ( subControl == Q::Segment ) { if ( bar->isSegmentEnabled( index ) ) { From f251a5f1ec7a6260b83d55eb1e99d3a29d474fc1 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 17 Jul 2023 13:15:31 +0200 Subject: [PATCH 43/60] setting row/columnCount to 0 when clearing the layout --- src/layouts/QskGridLayoutEngine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/layouts/QskGridLayoutEngine.cpp b/src/layouts/QskGridLayoutEngine.cpp index d851dee6..cc56af13 100644 --- a/src/layouts/QskGridLayoutEngine.cpp +++ b/src/layouts/QskGridLayoutEngine.cpp @@ -524,6 +524,8 @@ bool QskGridLayoutEngine::clear() m_data->rowSettings.clear(); m_data->columnSettings.clear(); + m_data->rowCount = m_data->columnCount = 0; + invalidate(); return true; } From 2ec50ad238f3d6166fa6a990cfe9edef80e53497 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Mon, 17 Jul 2023 13:27:25 +0200 Subject: [PATCH 44/60] missing Hovered settings for QskTextInput fixed --- skins/fluent2/QskFluent2Skin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 09dbda04..8aa735ed 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -1596,7 +1596,7 @@ void Editor::setupTextInputColors( borderColor2 = pal.elevation.textControl.border[1]; textColor = pal.fillColor.text.secondary; } - else if ( state == Q::Disabled ) + else if ( state == Q::Hovered ) { panelColor = pal.fillColor.control.secondary; borderColor1 = pal.elevation.textControl.border[0]; From 0c1bb727817f0020543a5a87e76d12bc32787a92 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 18 Jul 2023 14:01:45 +0200 Subject: [PATCH 45/60] QskMenu paddings --- skins/fluent2/QskFluent2Skin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 8aa735ed..e8e2be85 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -708,7 +708,7 @@ void Editor::setupMenuMetrics() setBoxBorderMetrics( Q::Panel, 1 ); setBoxShape( Q::Panel, 7 ); - setPadding( Q::Segment, { 0, 10, 0, 10 } ); + setPadding( Q::Segment, { 0, 10, 10, 10 } ); setSpacing( Q::Segment, 15 ); setBoxBorderMetrics( Q::Segment | Q::Selected, { 3, 0, 0, 0 } ); From f0a2803df7969a27387ec66e2b040105e4362322 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 18 Jul 2023 14:02:06 +0200 Subject: [PATCH 46/60] scrollbar handle metrics --- skins/material3/QskMaterial3Skin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index c59f83fd..22fb2ed7 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -1129,7 +1129,7 @@ void Editor::setupScrollView() for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) { - setMetric( subControl | A::Size, 10_dp ); + setMetric( subControl | A::Size, 6_dp ); setPadding( subControl, 0 ); } @@ -1139,9 +1139,9 @@ void Editor::setupScrollView() for ( auto subControl : { Q::HorizontalScrollHandle, Q::VerticalScrollHandle } ) { - setBoxShape( subControl, 3_dp ); + setBoxShape( subControl, { 100, Qt::RelativeSize } ); setBoxBorderMetrics( subControl, 0 ); - setGradient( subControl, m_pal.primary ); + setGradient( subControl, m_pal.secondary ); setAnimation( subControl | A::Color, qskDuration ); } From 881a60742809bc45790d1f6fe16e934d4f734473 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 18 Jul 2023 16:18:36 +0200 Subject: [PATCH 47/60] focusIndicator around the current row --- src/controls/QskListView.cpp | 40 ++++++++++++++++++++++++++--- src/controls/QskListView.h | 2 ++ src/controls/QskListViewSkinlet.cpp | 30 +++++++++++++++++----- src/controls/QskListViewSkinlet.h | 3 +++ 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/controls/QskListView.cpp b/src/controls/QskListView.cpp index ad23e8ca..69845c1a 100644 --- a/src/controls/QskListView.cpp +++ b/src/controls/QskListView.cpp @@ -7,6 +7,7 @@ #include "QskAspect.h" #include "QskColorFilter.h" #include "QskEvent.h" +#include "QskSkinlet.h" #include #include @@ -24,20 +25,26 @@ class QskListView::PrivateData PrivateData() : preferredWidthFromColumns( false ) , selectionMode( QskListView::SingleSelection ) - , selectedRow( -1 ) { } + /* + Currently we only support single selection. We can't navigate + the current item ( = focus ) without changing the selection. + So for the moment the selected row is always the currentRow. + */ + bool preferredWidthFromColumns : 1; SelectionMode selectionMode : 4; - int selectedRow; + int selectedRow = -1; }; QskListView::QskListView( QQuickItem* parent ) : QskScrollView( parent ) , m_data( new PrivateData() ) { + connect( this, &QskScrollView::scrollPosChanged, &QskControl::focusIndicatorRectChanged ); } QskListView::~QskListView() @@ -123,6 +130,7 @@ void QskListView::setSelectedRow( int row ) { m_data->selectedRow = row; Q_EMIT selectedRowChanged( row ); + Q_EMIT focusIndicatorRectChanged(); update(); } @@ -159,6 +167,19 @@ QskColorFilter QskListView::graphicFilterAt( int row, int col ) const return QskColorFilter(); } +QRectF QskListView::focusIndicatorRect() const +{ + if( m_data->selectedRow >= 0 ) + { + const auto rect = effectiveSkinlet()->sampleRect( + this, contentsRect(), Cell, m_data->selectedRow ); + + return rect.translated( -scrollPos() ); + } + + return Inherited::focusIndicatorRect(); +} + void QskListView::keyPressEvent( QKeyEvent* event ) { if ( m_data->selectionMode == NoSelection ) @@ -206,8 +227,19 @@ void QskListView::keyPressEvent( QKeyEvent* event ) } default: { - Inherited::keyPressEvent( event ); - return; + if ( const int steps = qskFocusChainIncrement( event ) ) + { + row += steps; + + if( row < 0 ) + { + row += rowCount(); + } + else if( row >= rowCount() ) + { + row %= rowCount(); + } + } } } diff --git a/src/controls/QskListView.h b/src/controls/QskListView.h index b05f7736..6b79bd73 100644 --- a/src/controls/QskListView.h +++ b/src/controls/QskListView.h @@ -75,6 +75,8 @@ class QSK_EXPORT QskListView : public QskScrollView virtual QskColorFilter graphicFilterAt( int row, int col ) const; #endif + QRectF focusIndicatorRect() const override; + public Q_SLOTS: void setSelectedRow( int row ); diff --git a/src/controls/QskListViewSkinlet.cpp b/src/controls/QskListViewSkinlet.cpp index 0a26ccf4..6b44f6e1 100644 --- a/src/controls/QskListViewSkinlet.cpp +++ b/src/controls/QskListViewSkinlet.cpp @@ -127,8 +127,6 @@ void QskListViewSkinlet::updateBackgroundNodes( rowMax = listView->rowCount() - 1; const int rowSelected = listView->selectedRow(); - const double x0 = viewRect.left() + scrolledPos.x(); - const double y0 = viewRect.top(); auto rowNode = backgroundNode->firstChild(); @@ -138,8 +136,7 @@ void QskListViewSkinlet::updateBackgroundNodes( { if ( row % 2 ) { - const QRectF rect( x0, y0 + row * cellHeight, - viewRect.width(), cellHeight ); + const auto rect = sampleRect( listView, listView->contentsRect(), Q::Cell, row ); auto newNode = updateBoxNode( listView, rowNode, rect, Q::Cell ); if ( newNode ) @@ -158,8 +155,7 @@ void QskListViewSkinlet::updateBackgroundNodes( QskSkinStateChanger stateChanger( listView ); stateChanger.setStates( listView->skinStates() | QskListView::Selected ); - const QRectF rect( x0, y0 + rowSelected * cellHeight, - viewRect.width(), cellHeight ); + const auto rect = sampleRect( listView, listView->contentsRect(), Q::Cell, rowSelected ); rowNode = updateBoxNode( listView, rowNode, rect, Q::Cell ); if ( rowNode && rowNode->parent() != backgroundNode ) @@ -490,4 +486,26 @@ QSizeF QskListViewSkinlet::sizeHint( const QskSkinnable* skinnable, return QSizeF( w, -1.0 ); } +QRectF QskListViewSkinlet::sampleRect( const QskSkinnable* skinnable, + const QRectF& contentsRect, QskAspect::Subcontrol subControl, int index ) const +{ + using Q = QskListView; + const auto listView = static_cast< const QskListView* >( skinnable ); + + if ( subControl == Q::Cell ) + { + const auto cellHeight = listView->rowHeight(); + const auto viewRect = listView->viewContentsRect(); + const auto scrolledPos = listView->scrollPos(); + + const double x0 = viewRect.left() + scrolledPos.x(); + const double y0 = viewRect.top(); + + const QRectF rect( x0, y0 + index * cellHeight, viewRect.width(), cellHeight ); + return rect; + } + + return Inherited::sampleRect( skinnable, contentsRect, subControl, index ); +} + #include "moc_QskListViewSkinlet.cpp" diff --git a/src/controls/QskListViewSkinlet.h b/src/controls/QskListViewSkinlet.h index 7f2f9d88..4f174962 100644 --- a/src/controls/QskListViewSkinlet.h +++ b/src/controls/QskListViewSkinlet.h @@ -37,6 +37,9 @@ class QSK_EXPORT QskListViewSkinlet : public QskScrollViewSkinlet QSizeF sizeHint( const QskSkinnable*, Qt::SizeHint, const QSizeF& ) const override; + QRectF sampleRect( const QskSkinnable*, + const QRectF&, QskAspect::Subcontrol, int index ) const override; + protected: QSGNode* updateContentsNode( const QskScrollView*, QSGNode* ) const override; From 86726e988f878d3123128225bf36a4f25160bebc Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Tue, 18 Jul 2023 16:29:35 +0200 Subject: [PATCH 48/60] item statistics fixed --- src/common/QskObjectCounter.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/common/QskObjectCounter.cpp b/src/common/QskObjectCounter.cpp index d3618799..c26b80fd 100644 --- a/src/common/QskObjectCounter.cpp +++ b/src/common/QskObjectCounter.cpp @@ -12,6 +12,7 @@ QSK_QT_PRIVATE_BEGIN #include +#include QSK_QT_PRIVATE_END #define QSK_OBJECT_INFO 0 @@ -20,19 +21,8 @@ QSK_QT_PRIVATE_END #include #endif -#if QT_VERSION < QT_VERSION_CHECK( 6, 4, 0 ) - -QSK_QT_PRIVATE_BEGIN -#include -QSK_QT_PRIVATE_END - -#endif - static inline bool qskIsItem( const QObject* object ) { -#if QT_VERSION >= QT_VERSION_CHECK( 6, 4, 0 ) - return object->isQuickItemType(); -#else /* The addObject hook is called from the constructor of QObject, where we don't have the derived class constructed yet. @@ -42,7 +32,6 @@ static inline bool qskIsItem( const QObject* object ) auto o_p = QObjectPrivate::get( const_cast< QObject* >( object ) ); return dynamic_cast< QQuickItemPrivate* >( o_p ) != nullptr; -#endif } namespace From 23f970650fa44edfc18706c277ce87000fd12632 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 19 Jul 2023 15:10:25 +0200 Subject: [PATCH 49/60] always use stencil clipping - unfortunately the batch renderer introduces rounding errors for the significantly faster scissor clips --- src/nodes/QskBoxClipNode.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/nodes/QskBoxClipNode.cpp b/src/nodes/QskBoxClipNode.cpp index 759717a8..fe1fe4fc 100644 --- a/src/nodes/QskBoxClipNode.cpp +++ b/src/nodes/QskBoxClipNode.cpp @@ -39,7 +39,25 @@ void QskBoxClipNode::setBox( const QRectF& rect, m_rect = rect; m_hash = hash; + bool isRectangular = false; + +#if 0 + /* + Depending on isRectangular the "renderer can use scissoring instead of stencil, + which is significantly faster." + + However the batch renderer ( qsgbatchrenderer.cpp ) is rounding the clip rectangle + to integers and the clip might become too small/large. + + So we always have to use stencil clipping - even if it might have a negative + impact on the performance. TODO ... + */ + if ( shape.isRectangle() ) + isRectangular = true; +#endif + + if ( isRectangular ) { if ( m_geometry.vertexCount() > 0 ) m_geometry.allocate( 0 ); From c40457fbeaf177300bce09dcaebeafc9e3beff49 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 19 Jul 2023 15:18:04 +0200 Subject: [PATCH 50/60] QskListView updates needed for M3 skins --- skins/material3/QskMaterial3Skin.cpp | 12 ++--- skins/squiek/QskSquiekSkin.cpp | 8 ++-- src/controls/QskListView.cpp | 17 -------- src/controls/QskListView.h | 9 ---- src/controls/QskListViewSkinlet.cpp | 63 +++++++++++++++------------ src/controls/QskScrollView.cpp | 6 +-- src/controls/QskScrollViewSkinlet.cpp | 6 ++- 7 files changed, 53 insertions(+), 68 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 22fb2ed7..ccdb2e21 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -1124,7 +1124,6 @@ void Editor::setupScrollView() using Q = QskScrollView; setGradient( Q::Panel, m_pal.background ); - setGradient( Q::Viewport, m_pal.secondaryContainer ); for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) @@ -1153,13 +1152,14 @@ void Editor::setupListView() { using Q = QskListView; + setStrutSize( Q::Cell, { -1, 56 } ); setPadding( Q::Cell, { 16_dp, 12_dp, 16_dp, 12_dp } ); - setBoxBorderMetrics( Q::Cell, { 0, 0, 0, 1_dp } ); - setBoxBorderColors( Q::Cell, m_pal.outline ); - setColor( Q::Cell, m_pal.surface ); - setColor( Q::Cell | Q::Selected, m_pal.primary12 ); - setColor( Q::Text, m_pal.onSurfaceVariant ); + setBoxBorderColors( Q::Cell, m_pal.outline ); + setGradient( Q::Cell, m_pal.surface ); + setGradient( Q::Cell | Q::Selected, m_pal.primary12 ); + + setColor( Q::Text, m_pal.onSurface ); } void Editor::setupSubWindow() diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 11c2d3e6..3bb258e6 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -1041,18 +1041,20 @@ void Editor::setupScrollView() void Editor::setupListView() { + using A = QskAspect; using Q = QskListView; // padding for each cell setPadding( Q::Cell, QskMargins( 4, 8 ) ); setColor( Q::Text, m_pal.themeForeground ); - setColor( Q::Cell, m_pal.contrasted ); + + // alternating row colors + setColor( Q::Cell | A::Lower, Qt::white ); + setColor( Q::Cell | A::Upper, m_pal.contrasted ); setColor( Q::Cell | Q::Selected, m_pal.highlighted ); setColor( Q::Text | Q::Selected, m_pal.highlightedText ); - - setFlag( Q::Cell | QskAspect::Style, true ); // alternating colors } void Editor::setupSubWindow() diff --git a/src/controls/QskListView.cpp b/src/controls/QskListView.cpp index 69845c1a..e1f71498 100644 --- a/src/controls/QskListView.cpp +++ b/src/controls/QskListView.cpp @@ -67,23 +67,6 @@ bool QskListView::preferredWidthFromColumns() const return m_data->preferredWidthFromColumns; } -void QskListView::setAlternatingRowColors( bool on ) -{ - if ( setFlagHint( Cell | QskAspect::Style, on ) ) - Q_EMIT alternatingRowColorsChanged(); -} - -bool QskListView::alternatingRowColors() const -{ - return flagHint< bool >( Cell | QskAspect::Style, false ); -} - -void QskListView::resetAlternatingRowColors() -{ - if ( resetSkinHint( Cell | QskAspect::Style ) ) - Q_EMIT alternatingRowColorsChanged(); -} - void QskListView::setTextOptions( const QskTextOptions& textOptions ) { if ( setTextOptionsHint( Text, textOptions ) ) diff --git a/src/controls/QskListView.h b/src/controls/QskListView.h index 6b79bd73..a8de657c 100644 --- a/src/controls/QskListView.h +++ b/src/controls/QskListView.h @@ -13,10 +13,6 @@ class QSK_EXPORT QskListView : public QskScrollView { Q_OBJECT - Q_PROPERTY( bool alternatingRowColors READ alternatingRowColors - WRITE setAlternatingRowColors RESET resetAlternatingRowColors - NOTIFY alternatingRowColorsChanged FINAL ) - Q_PROPERTY( SelectionMode selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged FINAL ) @@ -50,10 +46,6 @@ class QSK_EXPORT QskListView : public QskScrollView void setPreferredWidthFromColumns( bool ); bool preferredWidthFromColumns() const; - void setAlternatingRowColors( bool ); - void resetAlternatingRowColors(); - bool alternatingRowColors() const; - void setSelectionMode( SelectionMode ); SelectionMode selectionMode() const; @@ -84,7 +76,6 @@ class QSK_EXPORT QskListView : public QskScrollView void selectedRowChanged( int row ); void selectionModeChanged(); - void alternatingRowColorsChanged(); void preferredWidthFromColumnsChanged(); void textOptionsChanged(); diff --git a/src/controls/QskListViewSkinlet.cpp b/src/controls/QskListViewSkinlet.cpp index 6b44f6e1..236d66cb 100644 --- a/src/controls/QskListViewSkinlet.cpp +++ b/src/controls/QskListViewSkinlet.cpp @@ -8,6 +8,7 @@ #include "QskColorFilter.h" #include "QskGraphic.h" +#include "QskBoxHints.h" #include "QskSGNode.h" #include "QskSkinStateChanger.h" @@ -113,49 +114,56 @@ void QskListViewSkinlet::updateBackgroundNodes( const QskListView* listView, QskListViewNode* listViewNode ) const { using Q = QskListView; + using A = QskAspect; - QSGNode* backgroundNode = listViewNode->backgroundNode(); + auto backgroundNode = listViewNode->backgroundNode(); - const qreal cellHeight = listView->rowHeight(); + const auto cellHeight = listView->rowHeight(); const auto viewRect = listView->viewContentsRect(); - const QPointF scrolledPos = listView->scrollPos(); + const auto scrolledPos = listView->scrollPos(); const int rowMin = qFloor( scrolledPos.y() / cellHeight ); int rowMax = qCeil( ( scrolledPos.y() + viewRect.height() ) / cellHeight ); if ( rowMax >= listView->rowCount() ) rowMax = listView->rowCount() - 1; - const int rowSelected = listView->selectedRow(); + const auto x0 = viewRect.left() + scrolledPos.x(); + const auto y0 = viewRect.top(); auto rowNode = backgroundNode->firstChild(); - if ( listView->alternatingRowColors() ) - { - for ( int row = rowMin; row <= rowMax; row++ ) - { - if ( row % 2 ) - { - const auto rect = sampleRect( listView, listView->contentsRect(), Q::Cell, row ); + const auto boxHints1 = listView->boxHints( Q::Cell | A::Lower ); + const auto boxHints2 = listView->boxHints( Q::Cell | A::Upper ); - auto newNode = updateBoxNode( listView, rowNode, rect, Q::Cell ); - if ( newNode ) - { - if ( newNode->parent() != backgroundNode ) - backgroundNode->appendChildNode( newNode ); - else - rowNode = newNode->nextSibling(); - } - } + for ( int row = rowMin; row <= rowMax; row++ ) + { + /* + We do not use sampleRect to avoid doing the calculation + of viewRect for each row. + */ + const QRectF rect( x0, y0 + row * cellHeight, viewRect.width(), cellHeight ); + + auto newNode = updateBoxNode( listView, rowNode, rect, + ( row % 2 ) ? boxHints2 : boxHints1 ); + + if ( newNode ) + { + if ( newNode->parent() != backgroundNode ) + backgroundNode->appendChildNode( newNode ); + else + rowNode = newNode->nextSibling(); } } + const int rowSelected = listView->selectedRow(); if ( rowSelected >= rowMin && rowSelected <= rowMax ) { QskSkinStateChanger stateChanger( listView ); stateChanger.setStates( listView->skinStates() | QskListView::Selected ); - const auto rect = sampleRect( listView, listView->contentsRect(), Q::Cell, rowSelected ); + const QRectF rect( x0, y0 + rowSelected * cellHeight, + viewRect.width(), cellHeight ); rowNode = updateBoxNode( listView, rowNode, rect, Q::Cell ); if ( rowNode && rowNode->parent() != backgroundNode ) @@ -239,8 +247,8 @@ void QskListViewSkinlet::updateForegroundNodes( // finally putting the nodes into their position auto node = parentNode->firstChild(); - const qreal rowHeight = listView->rowHeight(); - qreal y = cr.top() + rowMin * rowHeight; + const auto rowHeight = listView->rowHeight(); + auto y = cr.top() + rowMin * rowHeight; for ( int row = rowMin; row <= rowMax; row++ ) { @@ -286,11 +294,11 @@ void QskListViewSkinlet::updateVisibleForegroundNodes( for ( int row = rowMin; row <= rowMax; row++ ) { - const qreal h = listView->rowHeight() - ( margins.top() + margins.bottom() ); + const auto h = listView->rowHeight() - ( margins.top() + margins.bottom() ); for ( int col = 0; col < listView->columnCount(); col++ ) { - const qreal w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); + const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); node = updateForegroundNode( listView, parentNode, static_cast< QSGTransformNode* >( node ), @@ -313,7 +321,7 @@ void QskListViewSkinlet::updateVisibleForegroundNodes( for ( int col = listView->columnCount() - 1; col >= 0; col-- ) { - const qreal w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); + const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); node = updateForegroundNode( listView, parentNode, static_cast< QSGTransformNode* >( node ), @@ -501,8 +509,7 @@ QRectF QskListViewSkinlet::sampleRect( const QskSkinnable* skinnable, const double x0 = viewRect.left() + scrolledPos.x(); const double y0 = viewRect.top(); - const QRectF rect( x0, y0 + index * cellHeight, viewRect.width(), cellHeight ); - return rect; + return QRectF( x0, y0 + index * cellHeight, viewRect.width(), cellHeight ); } return Inherited::sampleRect( skinnable, contentsRect, subControl, index ); diff --git a/src/controls/QskScrollView.cpp b/src/controls/QskScrollView.cpp index 8fd03456..ecfcc3fc 100644 --- a/src/controls/QskScrollView.cpp +++ b/src/controls/QskScrollView.cpp @@ -48,7 +48,6 @@ class QskScrollView::PrivateData qSwap( oldStates, newStates ); scrollView->startHintTransitions( { subControl }, oldStates, newStates ); - } Qt::ScrollBarPolicy horizontalScrollBarPolicy = Qt::ScrollBarAsNeeded; @@ -122,11 +121,10 @@ QskAspect::States QskScrollView::scrollHandleStates( Qt::Orientation orientation QRectF QskScrollView::viewContentsRect() const { - // This code should be done in the skinlet. TODO ... - const qreal bw = boxBorderMetricsHint( Viewport ).widthAt( Qt::TopEdge ); + const auto borderMetrics = boxBorderMetricsHint( Viewport ); const QRectF r = subControlRect( Viewport ); - return r.adjusted( bw, bw, -bw, -bw ); + return r.marginsRemoved( borderMetrics.widths() ); } void QskScrollView::mousePressEvent( QMouseEvent* event ) diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index b1f2d7e5..65c32ba7 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -123,9 +123,13 @@ QSGNode* QskScrollViewSkinlet::updateSubNode( } case HorizontalScrollBarRole: + { + return updateBoxNode( skinnable, node, Q::HorizontalScrollBar ); + } + case VerticalScrollBarRole: { - return nullptr; + return updateBoxNode( skinnable, node, Q::VerticalScrollBar ); } } From 4e2a069c140d11494c4d52912cad46330eedac4e Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 19 Jul 2023 17:43:51 +0200 Subject: [PATCH 51/60] Fluent2 scrollbar updates --- skins/fluent2/QskFluent2Skin.cpp | 35 ++++++++++++++++++++++---------- src/controls/QskScrollView.cpp | 18 ++++++++++++---- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index e8e2be85..51db94c3 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -1102,11 +1102,31 @@ void Editor::setupScrollViewMetrics() using Q = QskScrollView; for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) - setMetric( subControl | A::Size, 2 ); + { + const auto aspect = subControl | A::Size; + + setMetric( aspect, 2 ); + setMetric( aspect | Q::Hovered, 6 ); + setMetric( aspect | Q::Pressed, 6 ); + } + + /* + The scroll bars are actually above the viewport, what is not + supported by the skinlet. Do we want to have this. TODO ... + */ + + setAlignment( Q::VerticalScrollBar, Qt::AlignHCenter ); + setAlignment( Q::HorizontalScrollBar, Qt::AlignVCenter ); + + setBoxShape( Q::HorizontalScrollHandle, 100, Qt::RelativeSize ); + setBoxShape( Q::VerticalScrollHandle, 100, Qt::RelativeSize ); const auto handleExtent = 40.0; setStrutSize( Q::HorizontalScrollHandle, handleExtent, 0.0 ); setStrutSize( Q::VerticalScrollHandle, 0.0, handleExtent ); + + for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) + setAnimation( subControl | A::Metric, 100 ); } void Editor::setupScrollViewColors( @@ -1114,17 +1134,10 @@ void Editor::setupScrollViewColors( { using Q = QskScrollView; - const auto& pal = theme.palette; + const auto fillColor = theme.palette.fillColor.controlStrong.defaultColor; -#if 1 - setGradient( Q::Panel, QColor() ); - setGradient( Q::Viewport, QColor() ); -#endif - - for ( auto subControl : { Q::HorizontalScrollHandle, Q::VerticalScrollHandle } ) - { - setGradient( subControl | section, pal.fillColor.controlStrong.defaultColor ); - } + setGradient( Q::HorizontalScrollHandle | section, fillColor ); + setGradient( Q::VerticalScrollHandle | section, fillColor ); } void Editor::setupSegmentedBarMetrics() diff --git a/src/controls/QskScrollView.cpp b/src/controls/QskScrollView.cpp index ecfcc3fc..828b2d40 100644 --- a/src/controls/QskScrollView.cpp +++ b/src/controls/QskScrollView.cpp @@ -30,11 +30,12 @@ class QskScrollView::PrivateData if ( isScrolling == scrolling ) return; - QskAspect::Subcontrol subControl; + Qt::Orientation orientation; + if ( ( isScrolling == Qt::Horizontal ) || ( scrolling == Qt::Horizontal ) ) - subControl = HorizontalScrollHandle; + orientation = Qt::Horizontal; else - subControl = VerticalScrollHandle; + orientation = Qt::Vertical; this->isScrolling = scrolling; this->scrollPressPos = pos; @@ -47,7 +48,16 @@ class QskScrollView::PrivateData if ( scrolling == 0 ) qSwap( oldStates, newStates ); - scrollView->startHintTransitions( { subControl }, oldStates, newStates ); + if ( orientation == Qt::Horizontal ) + { + scrollView->startHintTransitions( { HorizontalScrollHandle }, oldStates, newStates ); + scrollView->startHintTransitions( { HorizontalScrollBar }, oldStates, newStates ); + } + else + { + scrollView->startHintTransitions( { VerticalScrollHandle }, oldStates, newStates ); + scrollView->startHintTransitions( { VerticalScrollBar }, oldStates, newStates ); + } } Qt::ScrollBarPolicy horizontalScrollBarPolicy = Qt::ScrollBarAsNeeded; From d43d6bfce2129712aa05e44f73e3f89ec365c5a0 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 20 Jul 2023 08:29:32 +0200 Subject: [PATCH 52/60] missing forward declaration added --- src/nodes/QskScaleRenderer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nodes/QskScaleRenderer.h b/src/nodes/QskScaleRenderer.h index 313653ef..3b185d21 100644 --- a/src/nodes/QskScaleRenderer.h +++ b/src/nodes/QskScaleRenderer.h @@ -23,6 +23,7 @@ class QskColorFilter; class QSGNode; class QVariant; class QRectF; +class QSizeF; class QSK_EXPORT QskScaleRenderer { From eb0bac4927b58d5773ca97d4eed6c8c96c88928f Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 20 Jul 2023 08:36:07 +0200 Subject: [PATCH 53/60] using std::as_const to avoid deprecation warnings --- src/common/QskGradient.h | 2 +- src/common/QskObjectCounter.cpp | 4 ++-- src/controls/QskFocusIndicator.cpp | 2 +- src/controls/QskGestureRecognizer.cpp | 4 ++-- src/controls/QskQuick.cpp | 2 +- src/controls/QskShortcutMap.cpp | 4 ++-- src/controls/QskSkinManager.cpp | 2 +- src/controls/QskSkinlet.cpp | 2 +- src/dialogs/QskDialogButtonBox.cpp | 2 +- src/graphic/QskGraphic.cpp | 4 ++-- src/layouts/QskStackBox.cpp | 4 ++-- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/common/QskGradient.h b/src/common/QskGradient.h index 5df88b8c..441aaa4f 100644 --- a/src/common/QskGradient.h +++ b/src/common/QskGradient.h @@ -230,7 +230,7 @@ inline const QskGradientStops& QskGradient::stops() const noexcept #if 1 /* Returning a const& so that it is possible to write: - for ( const auto& stop : qAsConst( gradient.stops() ) ) + for ( const auto& stop : gradient.stops() ) Once we have changed QskGradientStop from QColor to QRgb we should check if there is a better solution possible diff --git a/src/common/QskObjectCounter.cpp b/src/common/QskObjectCounter.cpp index c26b80fd..0ec9ee4c 100644 --- a/src/common/QskObjectCounter.cpp +++ b/src/common/QskObjectCounter.cpp @@ -162,7 +162,7 @@ void CounterHook::addObject( QObject* object ) { const bool isItem = qskIsItem( object ); - for ( auto counterData : qAsConst( m_counterDataSet ) ) + for ( auto counterData : std::as_const( m_counterDataSet ) ) { counterData->counter[ QskObjectCounter::Objects ].increment(); @@ -182,7 +182,7 @@ void CounterHook::removeObject( QObject* object ) { const bool isItem = qskIsItem( object ); - for ( auto counterData : qAsConst( m_counterDataSet ) ) + for ( auto counterData : std::as_const( m_counterDataSet ) ) { counterData->counter[ QskObjectCounter::Objects ].decrement(); diff --git a/src/controls/QskFocusIndicator.cpp b/src/controls/QskFocusIndicator.cpp index c688dffb..34380e34 100644 --- a/src/controls/QskFocusIndicator.cpp +++ b/src/controls/QskFocusIndicator.cpp @@ -57,7 +57,7 @@ class QskFocusIndicator::PrivateData public: void resetConnections() { - for ( const auto& connection : qAsConst( connections ) ) + for ( const auto& connection : std::as_const( connections ) ) QObject::disconnect( connection ); connections.clear(); diff --git a/src/controls/QskGestureRecognizer.cpp b/src/controls/QskGestureRecognizer.cpp index a5c376b2..fea738a1 100644 --- a/src/controls/QskGestureRecognizer.cpp +++ b/src/controls/QskGestureRecognizer.cpp @@ -132,7 +132,7 @@ namespace { Timer* timer = nullptr; - for ( auto t : qAsConst( m_table ) ) + for ( auto t : std::as_const( m_table ) ) { if ( t->recognizer() == nullptr || t->recognizer() == recognizer ) @@ -153,7 +153,7 @@ namespace void stopTimer( const QskGestureRecognizer* recognizer ) { - for ( auto timer : qAsConst( m_table ) ) + for ( auto timer : std::as_const( m_table ) ) { if ( timer->recognizer() == recognizer ) { diff --git a/src/controls/QskQuick.cpp b/src/controls/QskQuick.cpp index d333b9e5..07d23196 100644 --- a/src/controls/QskQuick.cpp +++ b/src/controls/QskQuick.cpp @@ -463,7 +463,7 @@ void qskItemUpdateRecursive( QQuickItem* item ) static const QQuickPointerTouchEvent* qskPointerPressEvent( const QQuickWindowPrivate* wd ) { - for ( const auto event : qAsConst( wd->pointerEventInstances ) ) + for ( const auto event : std::as_const( wd->pointerEventInstances ) ) { if ( auto touchEvent = event->asPointerTouchEvent() ) { diff --git a/src/controls/QskShortcutMap.cpp b/src/controls/QskShortcutMap.cpp index 6bd058f0..c7d518ec 100644 --- a/src/controls/QskShortcutMap.cpp +++ b/src/controls/QskShortcutMap.cpp @@ -173,7 +173,7 @@ void QskShortcutHandler::remove( int id ) Finally let's check if we can disconnect from the destroyed signals */ - for ( const auto& entry : qAsConst( m_invokeDataMap ) ) + for ( const auto& entry : std::as_const( m_invokeDataMap ) ) { if ( item == nullptr && receiver == nullptr ) break; @@ -276,7 +276,7 @@ bool QskShortcutHandler::invoke( QQuickItem* item, const QKeySequence& sequence { bool found = false; - for ( const auto& entry : qAsConst( m_invokeDataMap ) ) + for ( const auto& entry : std::as_const( m_invokeDataMap ) ) { auto& data = entry.second; diff --git a/src/controls/QskSkinManager.cpp b/src/controls/QskSkinManager.cpp index a41fcfca..218d2747 100644 --- a/src/controls/QskSkinManager.cpp +++ b/src/controls/QskSkinManager.cpp @@ -365,7 +365,7 @@ class QskSkinManager::PrivateData { if ( !pluginsRegistered ) { - for ( const auto& path : qAsConst( pluginPaths ) ) + for ( const auto& path : std::as_const( pluginPaths ) ) registerPlugins( path + QStringLiteral( "/skins" ) ); pluginsRegistered = true; diff --git a/src/controls/QskSkinlet.cpp b/src/controls/QskSkinlet.cpp index b1e73ace..d19a1e93 100644 --- a/src/controls/QskSkinlet.cpp +++ b/src/controls/QskSkinlet.cpp @@ -368,7 +368,7 @@ void QskSkinlet::updateNode( QskSkinnable* skinnable, QSGNode* parentNode ) cons replaceChildNode( DebugRole, parentNode, oldNode, newNode ); } - for ( const auto nodeRole : qAsConst( m_data->nodeRoles ) ) + for ( const auto nodeRole : std::as_const( m_data->nodeRoles ) ) { Q_ASSERT( nodeRole < FirstReservedRole ); diff --git a/src/dialogs/QskDialogButtonBox.cpp b/src/dialogs/QskDialogButtonBox.cpp index d189ab74..47cfc75a 100644 --- a/src/dialogs/QskDialogButtonBox.cpp +++ b/src/dialogs/QskDialogButtonBox.cpp @@ -118,7 +118,7 @@ QskDialogButtonBox::~QskDialogButtonBox() { for ( int i = 0; i < QskDialog::NActionRoles; i++ ) { - for ( auto button : qAsConst( m_data->buttons[ i ] ) ) + for ( auto button : std::as_const( m_data->buttons[ i ] ) ) { /* The destructor of QQuickItem sets the parentItem of diff --git a/src/graphic/QskGraphic.cpp b/src/graphic/QskGraphic.cpp index 3541da83..c6326790 100644 --- a/src/graphic/QskGraphic.cpp +++ b/src/graphic/QskGraphic.cpp @@ -568,7 +568,7 @@ QRectF QskGraphic::scaledBoundingRect( qreal sx, qreal sy ) const QRectF rect = transform.mapRect( m_data->pointRect ); - for ( const auto& info : qAsConst( m_data->pathInfos ) ) + for ( const auto& info : std::as_const( m_data->pathInfos ) ) rect |= info.scaledBoundingRect( sx, sy, scalePens ); return rect; @@ -681,7 +681,7 @@ void QskGraphic::render( QPainter* painter, const QRectF& rect, const bool scalePens = !( m_data->renderHints & RenderPensUnscaled ); - for ( const auto& info : qAsConst( m_data->pathInfos ) ) + for ( const auto& info : std::as_const( m_data->pathInfos ) ) { const qreal ssx = info.scaleFactorX( m_data->pointRect, rect, m_data->boundingRect, scalePens ); diff --git a/src/layouts/QskStackBox.cpp b/src/layouts/QskStackBox.cpp index 156a71e0..2b3eaf54 100644 --- a/src/layouts/QskStackBox.cpp +++ b/src/layouts/QskStackBox.cpp @@ -318,7 +318,7 @@ void QskStackBox::autoRemoveItem( QQuickItem* item ) void QskStackBox::clear( bool autoDelete ) { - for ( const auto item : qAsConst( m_data->items ) ) + for ( const auto item : std::as_const( m_data->items ) ) { if( autoDelete && ( item->parent() == this ) ) delete item; @@ -380,7 +380,7 @@ QSizeF QskStackBox::layoutSizeHint( qreal w = -1.0; qreal h = -1.0; - for ( const auto item : qAsConst( m_data->items ) ) + for ( const auto item : std::as_const( m_data->items ) ) { /* We ignore the retainSizeWhenVisible flag and include all From bdef864bf323809cbcee3aac8a074a97ee64168b Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 20 Jul 2023 10:41:49 +0200 Subject: [PATCH 54/60] fluent2 scrollbars improved --- skins/fluent2/QskFluent2Skin.cpp | 46 ++++++++++++++++--- skins/fluent2/QskFluent2Theme.cpp | 4 ++ skins/fluent2/QskFluent2Theme.h | 5 ++ src/controls/QskScrollViewSkinlet.cpp | 66 +++++++++++++-------------- src/controls/QskScrollViewSkinlet.h | 2 + 5 files changed, 84 insertions(+), 39 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 51db94c3..66bbbe5a 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -1108,6 +1108,9 @@ void Editor::setupScrollViewMetrics() setMetric( aspect, 2 ); setMetric( aspect | Q::Hovered, 6 ); setMetric( aspect | Q::Pressed, 6 ); + + setBoxShape( subControl, 100, Qt::RelativeSize ); + setAnimation( subControl | A::Metric, 100 ); } /* @@ -1118,26 +1121,57 @@ void Editor::setupScrollViewMetrics() setAlignment( Q::VerticalScrollBar, Qt::AlignHCenter ); setAlignment( Q::HorizontalScrollBar, Qt::AlignVCenter ); + // handles + setBoxShape( Q::HorizontalScrollHandle, 100, Qt::RelativeSize ); setBoxShape( Q::VerticalScrollHandle, 100, Qt::RelativeSize ); const auto handleExtent = 40.0; setStrutSize( Q::HorizontalScrollHandle, handleExtent, 0.0 ); setStrutSize( Q::VerticalScrollHandle, 0.0, handleExtent ); - - for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) - setAnimation( subControl | A::Metric, 100 ); } void Editor::setupScrollViewColors( QskAspect::Section section, const QskFluent2Theme& theme ) { + using A = QskAspect; using Q = QskScrollView; - const auto fillColor = theme.palette.fillColor.controlStrong.defaultColor; + const auto& pal = theme.palette; - setGradient( Q::HorizontalScrollHandle | section, fillColor ); - setGradient( Q::VerticalScrollHandle | section, fillColor ); + { + const auto fillColor = pal.fillColor.controlStrong.defaultColor; + + setGradient( Q::HorizontalScrollHandle | section, fillColor ); + setGradient( Q::VerticalScrollHandle | section, fillColor ); + } + + for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) + { + auto fillColor = pal.fillColor.acrylic.background; + +#if 1 + /* + With Fluent2 the scroll bar is supposed to be on top of scrollable + item. QskScrollViewSkinlet does not support this yet and we + always have the scrollbar on top of the panel. For the light + scheme this leads to white on white, so we better shade the scrollbar + for the moment: TODO ... + */ + const auto v = qBlue( fillColor ); + if ( v > 250 ) + { + if ( v == qRed( fillColor ) && v == qGreen( fillColor ) ) + fillColor = qRgba( 240, 240, 240, qAlpha( fillColor ) ); + } +#endif + + setGradient( subControl, QskRgb::toTransparent( fillColor, 0 ) ); + setGradient( subControl | Q::Hovered, fillColor ); + setGradient( subControl | Q::Pressed, fillColor ); + + setAnimation( subControl | A::Color, 100 ); + } } void Editor::setupSegmentedBarMetrics() diff --git a/skins/fluent2/QskFluent2Theme.cpp b/skins/fluent2/QskFluent2Theme.cpp index 402d86cf..f7c20d30 100644 --- a/skins/fluent2/QskFluent2Theme.cpp +++ b/skins/fluent2/QskFluent2Theme.cpp @@ -77,6 +77,8 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, colors.accent.tertiary = toTransparentF( accentColors.secondary, 0.80 ); colors.accent.disabled = rgbGray( 0, 0.2169 ); colors.accent.selectedTextBackground = accentColors.primary; + + colors.acrylic.background = rgbGray( 252, 0.85 ); } #if 0 @@ -198,6 +200,8 @@ QskFluent2Theme::QskFluent2Theme( QskSkin::ColorScheme colorScheme, colors.accent.tertiary = toTransparentF( accentColors.tertiary, 0.80 ); colors.accent.disabled = rgbGray( 255, 0.1581 ); colors.accent.selectedTextBackground = accentColors.primary; + + colors.acrylic.background = rgbGray( 44, 0.96 ); } #if 0 diff --git a/skins/fluent2/QskFluent2Theme.h b/skins/fluent2/QskFluent2Theme.h index 8aba499b..a4d18feb 100644 --- a/skins/fluent2/QskFluent2Theme.h +++ b/skins/fluent2/QskFluent2Theme.h @@ -107,6 +107,11 @@ class QSK_FLUENT2_EXPORT QskFluent2Theme QRgb disabled; QRgb selectedTextBackground; } accent; + + struct + { + QRgb background; + } acrylic; }; struct Elevation diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index 65c32ba7..70d2ba40 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -39,6 +39,16 @@ static void qskAlignedHandle( qreal start, qreal end, } } +static inline Qt::Orientation qskSubcontrolOrientation( QskAspect::Subcontrol subControl ) +{ + using Q = QskScrollView; + + if ( subControl == Q::HorizontalScrollBar || subControl == Q::HorizontalScrollHandle ) + return Qt::Horizontal; + else + return Qt::Vertical; +} + QskScrollViewSkinlet::QskScrollViewSkinlet( QskSkin* skin ) : Inherited( skin ) { @@ -87,55 +97,45 @@ QSGNode* QskScrollViewSkinlet::updateSubNode( switch ( nodeRole ) { case PanelRole: - { return updateBoxNode( skinnable, node, Q::Panel ); - } + case ViewportRole: - { return updateBoxNode( skinnable, node, Q::Viewport ); - } case HorizontalScrollHandleRole: - { - const auto rect = subControlRect( skinnable, - scrollView->contentsRect(), Q::HorizontalScrollHandle ); - - QskSkinStateChanger stateChanger( scrollView ); - stateChanger.setStates( scrollView->scrollHandleStates( Qt::Horizontal ) ); - - return updateBoxNode( skinnable, node, rect, Q::HorizontalScrollHandle ); - } + return updateScrollBarNode( scrollView, Q::HorizontalScrollHandle, node ); case VerticalScrollHandleRole: - { - const auto rect = subControlRect( skinnable, - scrollView->contentsRect(), Q::VerticalScrollHandle ); - - QskSkinStateChanger stateChanger( scrollView ); - stateChanger.setStates( scrollView->scrollHandleStates( Qt::Vertical ) ); - - return updateBoxNode( skinnable, node, rect, Q::VerticalScrollHandle ); - } - - case ContentsRootRole: - { - return updateContentsRootNode( scrollView, node ); - } + return updateScrollBarNode( scrollView, Q::VerticalScrollHandle, node ); case HorizontalScrollBarRole: - { - return updateBoxNode( skinnable, node, Q::HorizontalScrollBar ); - } + return updateScrollBarNode( scrollView, Q::HorizontalScrollBar, node ); case VerticalScrollBarRole: - { - return updateBoxNode( skinnable, node, Q::VerticalScrollBar ); - } + return updateScrollBarNode( scrollView, Q::VerticalScrollBar, node ); + + case ContentsRootRole: + return updateContentsRootNode( scrollView, node ); + } return Inherited::updateSubNode( skinnable, nodeRole, node ); } +QSGNode* QskScrollViewSkinlet::updateScrollBarNode( const QskScrollView* scrollView, + QskAspect::Subcontrol subControl, QSGNode* node ) const +{ + const auto rect = subControlRect( scrollView, + scrollView->contentsRect(), subControl ); + + const auto orientation = qskSubcontrolOrientation( subControl ); + + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + + return updateBoxNode( scrollView, node, rect, subControl ); +} + QSGNode* QskScrollViewSkinlet::updateContentsRootNode( const QskScrollView* scrollView, QSGNode* node ) const { diff --git a/src/controls/QskScrollViewSkinlet.h b/src/controls/QskScrollViewSkinlet.h index 94fe24e1..16c6c81f 100644 --- a/src/controls/QskScrollViewSkinlet.h +++ b/src/controls/QskScrollViewSkinlet.h @@ -47,6 +47,8 @@ class QSK_EXPORT QskScrollViewSkinlet : public QskSkinlet private: QSGNode* updateContentsRootNode( const QskScrollView*, QSGNode* ) const; + QSGNode* updateScrollBarNode( + const QskScrollView*, QskAspect::Subcontrol, QSGNode* ) const; QRectF viewportRect( const QskScrollView*, const QRectF& ) const; QRectF scrollBarRect( const QskScrollView*, const QRectF&, Qt::Orientation ) const; From c6fb2f81c96bd73fbee9fdc85ec2a6c7c72b9580 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 20 Jul 2023 16:46:21 +0200 Subject: [PATCH 55/60] scrollbar hover events --- skins/squiek/QskSquiekSkin.cpp | 10 +- src/controls/QskScrollView.cpp | 155 +++++++++++++++++++++----- src/controls/QskScrollView.h | 6 +- src/controls/QskScrollViewSkinlet.cpp | 34 +++--- 4 files changed, 154 insertions(+), 51 deletions(-) diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index 3bb258e6..f3afbcb6 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -1012,9 +1012,13 @@ void Editor::setupScrollView() // scroll bars for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) { - setMetric( subControl | A::Size, 12_dp ); - setPadding( subControl, 0 ); + setMetric( subControl | A::Size, 14 ); + setPadding( subControl, 2 ); setMargin( subControl, 0 ); + + setPanel( subControl, Sunken ); + setBoxShape( subControl, 100, Qt::RelativeSize ); + setBoxBorderMetrics( subControl, 1 ); } // scrollbar handles @@ -1024,6 +1028,8 @@ void Editor::setupScrollView() setButton( subControl, Raised, bw ); setButton( subControl | Q::Pressed, Sunken, bw ); + setBoxShape( subControl, 100, Qt::RelativeSize ); + setBoxShape( subControl | Q::Pressed, 100, Qt::RelativeSize ); const auto extent = 40_dp; diff --git a/src/controls/QskScrollView.cpp b/src/controls/QskScrollView.cpp index 828b2d40..34622005 100644 --- a/src/controls/QskScrollView.cpp +++ b/src/controls/QskScrollView.cpp @@ -17,60 +17,132 @@ QSK_SUBCONTROL( QskScrollView, VerticalScrollHandle ) QSK_SYSTEM_STATE( QskScrollView, Pressed, QskAspect::FirstSystemState << 1 ) +static inline QskAspect::Subcontrol qskSubControlAt( + const QskScrollView* scrollView, const QPointF& pos ) +{ + using Q = QskScrollView; + + const auto rect = scrollView->contentsRect(); + + // order is important as the handles are inside the bars ! + + for ( auto subControl : { Q::VerticalScrollHandle, Q::VerticalScrollBar, + Q::HorizontalScrollHandle, Q::HorizontalScrollBar } ) + { + if ( scrollView->subControlRect( rect, subControl ).contains( pos ) ) + return subControl; + } + + return QskAspect::NoSubcontrol; +} + class QskScrollView::PrivateData { public: inline void resetScrolling( QskScrollView* scrollView ) { - setScrolling( scrollView, 0, 0.0 ); + setScrolling( scrollView, QskAspect::NoSubcontrol, 0.0 ); } - inline void setScrolling( QskScrollView* scrollView, int scrolling, qreal pos ) + inline void setScrolling( QskScrollView* scrollView, + QskAspect::Subcontrol subControl, qreal pos ) { - if ( isScrolling == scrolling ) + if ( subControl == pressedSubControl ) return; - Qt::Orientation orientation; - - if ( ( isScrolling == Qt::Horizontal ) || ( scrolling == Qt::Horizontal ) ) - orientation = Qt::Horizontal; + QskAspect::Subcontrol subControls[2]; + if ( subControl == VerticalScrollHandle || pressedSubControl == VerticalScrollHandle ) + { + subControls[0] = VerticalScrollHandle; + subControls[1] = VerticalScrollBar; + } else - orientation = Qt::Vertical; + { + subControls[0] = HorizontalScrollHandle;; + subControls[1] = HorizontalScrollBar; + } - this->isScrolling = scrolling; - this->scrollPressPos = pos; + pressedSubControl = subControl; + scrollPressPos = pos; scrollView->update(); - auto oldStates = scrollView->skinStates(); + auto oldStates = scrollView->skinStates() | scrollView->scrollBarStates( subControl ); auto newStates = oldStates | QskScrollView::Pressed; - if ( scrolling == 0 ) + if ( pressedSubControl == QskAspect::NoSubcontrol ) qSwap( oldStates, newStates ); - if ( orientation == Qt::Horizontal ) + scrollView->startHintTransitions( { subControls[0] }, oldStates, newStates ); + scrollView->startHintTransitions( { subControls[1] }, oldStates, newStates ); + } + + void setHovered( QskScrollView* scrollView, QskAspect::Subcontrol subControl ) + { + if ( subControl == this->hoveredSubControl ) + return; + + QskAspect::Subcontrol subControls[2]; + if ( subControl == VerticalScrollHandle + || hoveredSubControl == VerticalScrollHandle + || subControl == VerticalScrollBar + || hoveredSubControl == VerticalScrollBar ) { - scrollView->startHintTransitions( { HorizontalScrollHandle }, oldStates, newStates ); - scrollView->startHintTransitions( { HorizontalScrollBar }, oldStates, newStates ); + subControls[0] = VerticalScrollHandle; + subControls[1] = VerticalScrollBar; } else { - scrollView->startHintTransitions( { VerticalScrollHandle }, oldStates, newStates ); - scrollView->startHintTransitions( { VerticalScrollBar }, oldStates, newStates ); + subControls[0] = HorizontalScrollHandle;; + subControls[1] = HorizontalScrollBar; } + + hoveredSubControl = subControl; + + auto oldStates = scrollView->skinStates(); + auto newStates = oldStates | QskScrollView::Hovered; + + if ( hoveredSubControl == QskAspect::NoSubcontrol ) + qSwap( oldStates, newStates ); + + scrollView->startHintTransitions( { subControls[0] }, oldStates, newStates ); + scrollView->startHintTransitions( { subControls[1] }, oldStates, newStates ); + } + + bool hasState( QskAspect::Subcontrol subControl, QskAspect::State state ) const + { + if ( subControl == QskAspect::NoSubcontrol ) + return false; + + const auto stateSubcontrol = + ( state == QskControl::Hovered ) ? hoveredSubControl : pressedSubControl; + + if ( subControl == stateSubcontrol ) + return true; + + if ( subControl == VerticalScrollBar ) + return stateSubcontrol == VerticalScrollHandle; + + if ( subControl == HorizontalScrollBar ) + return stateSubcontrol == HorizontalScrollHandle; + + return false; } Qt::ScrollBarPolicy horizontalScrollBarPolicy = Qt::ScrollBarAsNeeded; Qt::ScrollBarPolicy verticalScrollBarPolicy = Qt::ScrollBarAsNeeded; - qreal scrollPressPos; - int isScrolling = 0; + qreal scrollPressPos = 0.0; + + QskAspect::Subcontrol pressedSubControl = QskAspect::NoSubcontrol; + QskAspect::Subcontrol hoveredSubControl = QskAspect::NoSubcontrol; }; QskScrollView::QskScrollView( QQuickItem* parent ) : Inherited( parent ) , m_data( new PrivateData() ) { + setAcceptHoverEvents( true ); } QskScrollView::~QskScrollView() @@ -117,15 +189,23 @@ Qt::ScrollBarPolicy QskScrollView::horizontalScrollBarPolicy() const bool QskScrollView::isScrolling( Qt::Orientation orientation ) const { - return m_data->isScrolling == orientation; + if ( orientation == Qt::Vertical ) + return m_data->pressedSubControl == VerticalScrollHandle; + else + return m_data->pressedSubControl == HorizontalScrollHandle; } -QskAspect::States QskScrollView::scrollHandleStates( Qt::Orientation orientation ) const +QskAspect::States QskScrollView::scrollBarStates( + QskAspect::Subcontrol subControl ) const { auto states = skinStates(); - if ( m_data->isScrolling == orientation ) + + if ( m_data->hasState( subControl, Pressed ) ) states |= Pressed; + if ( m_data->hasState( subControl, Hovered ) ) + states |= Hovered; + return states; } @@ -143,11 +223,11 @@ void QskScrollView::mousePressEvent( QMouseEvent* event ) if ( subControlRect( VerticalScrollBar ).contains( mousePos ) ) { - const QRectF handleRect = subControlRect( VerticalScrollHandle ); + const auto handleRect = subControlRect( VerticalScrollHandle ); if ( handleRect.contains( mousePos ) ) { - m_data->setScrolling( this, Qt::Vertical, mousePos.y() ); + m_data->setScrolling( this, VerticalScrollHandle, mousePos.y() ); } else { @@ -172,7 +252,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event ) if ( handleRect.contains( mousePos ) ) { - m_data->setScrolling( this, Qt::Horizontal, mousePos.x() ); + m_data->setScrolling( this, HorizontalScrollHandle, mousePos.x() ); } else { @@ -196,7 +276,7 @@ void QskScrollView::mousePressEvent( QMouseEvent* event ) void QskScrollView::mouseMoveEvent( QMouseEvent* event ) { - if ( !m_data->isScrolling ) + if ( m_data->pressedSubControl == QskAspect::NoSubcontrol ) { Inherited::mouseMoveEvent( event ); return; @@ -205,7 +285,7 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event ) const auto mousePos = qskMousePosition( event ); QPointF pos = scrollPos(); - if ( m_data->isScrolling == Qt::Horizontal ) + if ( m_data->pressedSubControl == HorizontalScrollHandle ) { const qreal dx = mousePos.x() - m_data->scrollPressPos; const qreal w = subControlRect( HorizontalScrollBar ).width(); @@ -213,7 +293,7 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event ) pos.rx() += dx / w * scrollableSize().width(); m_data->scrollPressPos = mousePos.x(); } - else if ( m_data->isScrolling == Qt::Vertical ) + else { const qreal dy = mousePos.y() - m_data->scrollPressPos; const qreal h = subControlRect( VerticalScrollBar ).height(); @@ -228,7 +308,7 @@ void QskScrollView::mouseMoveEvent( QMouseEvent* event ) void QskScrollView::mouseReleaseEvent( QMouseEvent* event ) { - if ( !m_data->isScrolling ) + if ( m_data->pressedSubControl == QskAspect::NoSubcontrol ) { Inherited::mouseReleaseEvent( event ); return; @@ -242,6 +322,23 @@ void QskScrollView::mouseUngrabEvent() m_data->resetScrolling( this ); } +void QskScrollView::hoverEnterEvent( QHoverEvent* event ) +{ + const auto subControl = qskSubControlAt( this, qskHoverPosition( event ) ); + m_data->setHovered( this, subControl ); +} + +void QskScrollView::hoverMoveEvent( QHoverEvent* event ) +{ + const auto subControl = qskSubControlAt( this, qskHoverPosition( event ) ); + m_data->setHovered( this, subControl ); +} + +void QskScrollView::hoverLeaveEvent( QHoverEvent* ) +{ + m_data->setHovered( this, QskAspect::NoSubcontrol ); +} + #ifndef QT_NO_WHEELEVENT QPointF QskScrollView::scrollOffset( const QWheelEvent* event ) const diff --git a/src/controls/QskScrollView.h b/src/controls/QskScrollView.h index fe0dfa38..4771b394 100644 --- a/src/controls/QskScrollView.h +++ b/src/controls/QskScrollView.h @@ -39,7 +39,7 @@ class QSK_EXPORT QskScrollView : public QskScrollBox Qt::Orientations scrollableOrientations() const; bool isScrolling( Qt::Orientation ) const; - QskAspect::States scrollHandleStates( Qt::Orientation ) const; + QskAspect::States scrollBarStates( QskAspect::Subcontrol ) const; QRectF viewContentsRect() const override; QskAnimationHint flickHint() const override; @@ -54,6 +54,10 @@ class QSK_EXPORT QskScrollView : public QskScrollBox void mouseReleaseEvent( QMouseEvent* ) override; void mouseUngrabEvent() override; + void hoverEnterEvent( QHoverEvent* ) override; + void hoverMoveEvent( QHoverEvent* ) override; + void hoverLeaveEvent( QHoverEvent* ) override; + #ifndef QT_NO_WHEELEVENT QPointF scrollOffset( const QWheelEvent* ) const override; #endif diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index 70d2ba40..3bc10a11 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -39,14 +39,16 @@ static void qskAlignedHandle( qreal start, qreal end, } } -static inline Qt::Orientation qskSubcontrolOrientation( QskAspect::Subcontrol subControl ) +static qreal qskScrollBarExtent( + const QskScrollView* scrollView, Qt::Orientation orientation ) { - using Q = QskScrollView; + const auto subControl = ( orientation == Qt::Horizontal ) + ? QskScrollView::HorizontalScrollBar : QskScrollView::VerticalScrollBar; - if ( subControl == Q::HorizontalScrollBar || subControl == Q::HorizontalScrollHandle ) - return Qt::Horizontal; - else - return Qt::Vertical; + QskSkinStateChanger stateChanger( scrollView ); + stateChanger.setStates( scrollView->scrollBarStates( subControl ) ); + + return scrollView->metric( subControl | QskAspect::Size ); } QskScrollViewSkinlet::QskScrollViewSkinlet( QskSkin* skin ) @@ -128,10 +130,8 @@ QSGNode* QskScrollViewSkinlet::updateScrollBarNode( const QskScrollView* scrollV const auto rect = subControlRect( scrollView, scrollView->contentsRect(), subControl ); - const auto orientation = qskSubcontrolOrientation( subControl ); - QskSkinStateChanger stateChanger( scrollView ); - stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + stateChanger.setStates( scrollView->scrollBarStates( subControl ) ); return updateBoxNode( scrollView, node, rect, subControl ); } @@ -254,7 +254,7 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, const auto sbRect = subControlRect( scrollView, contentsRect, Q::VerticalScrollBar ); QskSkinStateChanger stateChanger( scrollView ); - stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + stateChanger.setStates( scrollView->scrollBarStates( Q::VerticalScrollBar ) ); const auto padding = scrollView->paddingHint( Q::VerticalScrollBar ); const auto strut = scrollView->strutSizeHint( Q::VerticalScrollHandle ); @@ -275,7 +275,7 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, const auto sbRect = subControlRect( scrollView, contentsRect, Q::HorizontalScrollBar ); QskSkinStateChanger stateChanger( scrollView ); - stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); + stateChanger.setStates( scrollView->scrollBarStates( Q::HorizontalScrollBar ) ); const auto padding = scrollView->paddingHint( Q::HorizontalScrollBar ); @@ -299,7 +299,6 @@ QRectF QskScrollViewSkinlet::scrollHandleRect( const QskScrollView* scrollView, QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView, const QRectF& contentsRect, Qt::Orientation orientation ) const { - using A = QskAspect; using Q = QskScrollView; const auto scrollOrientations = scrollView->scrollableOrientations(); @@ -308,28 +307,25 @@ QRectF QskScrollViewSkinlet::scrollBarRect( const QskScrollView* scrollView, auto r = subControlRect( scrollView, contentsRect, Q::Panel ); - QskSkinStateChanger stateChanger( scrollView ); - stateChanger.setStates( scrollView->scrollHandleStates( orientation ) ); - if ( orientation == Qt::Horizontal ) { - const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size ); + const qreal h = qskScrollBarExtent( scrollView, Qt::Horizontal ); r.setTop( r.bottom() - h ); if ( scrollOrientations & Qt::Vertical ) { - const qreal w = scrollView->metric( Q::VerticalScrollBar | A::Size ); + const qreal w = qskScrollBarExtent( scrollView, Qt::Vertical ); r.setRight( r.right() - w ); } } else { - const qreal w = scrollView->metric( Q::VerticalScrollBar | A::Size ); + const qreal w = qskScrollBarExtent( scrollView, Qt::Vertical ); r.setLeft( r.right() - w ); if ( scrollOrientations & Qt::Horizontal ) { - const qreal h = scrollView->metric( Q::HorizontalScrollBar | A::Size ); + const qreal h = qskScrollBarExtent( scrollView, Qt::Horizontal ); r.setBottom( r.bottom() - h ); } } From 4270b0f7bafdf145ffb4374b2c76832c1743e5c4 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 21 Jul 2023 11:35:24 +0200 Subject: [PATCH 56/60] making QskMainView a tab fence, so that the tab chain does not stop at the end --- src/controls/QskMainView.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controls/QskMainView.cpp b/src/controls/QskMainView.cpp index ddf55ec4..ced25d56 100644 --- a/src/controls/QskMainView.cpp +++ b/src/controls/QskMainView.cpp @@ -27,6 +27,7 @@ QskMainView::QskMainView( QQuickItem* parent ) setPanel( true ); setFlag( QQuickItem::ItemIsFocusScope, true ); + setTabFence( true ); setFocusPolicy( Qt::StrongFocus ); } From e9ed10ac82597fd15de57dbfb1f078fbc56496c1 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 21 Jul 2023 12:59:50 +0200 Subject: [PATCH 57/60] Qt::NoFocus policy for the scrollarea, that usually has no scrollbars --- examples/gallery/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/gallery/main.cpp b/examples/gallery/main.cpp index fd2f41ad..b074c299 100644 --- a/examples/gallery/main.cpp +++ b/examples/gallery/main.cpp @@ -100,6 +100,14 @@ namespace auto scrollArea = new QskScrollArea(); scrollArea->setMargins( 5 ); +#if 1 + /* + We need a mode, where the focus policy gets adjusted + when a scroll bar becomes visible. TODO ... + */ + scrollArea->setFocusPolicy( Qt::NoFocus ); +#endif + // hiding the viewport scrollArea->setGradientHint( QskScrollView::Viewport, QskGradient() ); scrollArea->setBoxShapeHint( QskScrollView::Viewport, 0 ); From 75b64d049a93deb1f07edacf755c87f5708ad14c Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 21 Jul 2023 13:01:06 +0200 Subject: [PATCH 58/60] do not use focus navigation for the list entries --- src/controls/QskListView.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/controls/QskListView.cpp b/src/controls/QskListView.cpp index e1f71498..0dbe237a 100644 --- a/src/controls/QskListView.cpp +++ b/src/controls/QskListView.cpp @@ -19,6 +19,8 @@ QSK_SUBCONTROL( QskListView, Text ) QSK_STATE( QskListView, Selected, QskAspect::FirstUserState ) +#define FOCUS_ON_CURRENT 1 + class QskListView::PrivateData { public: @@ -44,7 +46,9 @@ QskListView::QskListView( QQuickItem* parent ) : QskScrollView( parent ) , m_data( new PrivateData() ) { +#if FOCUS_ON_CURRENT connect( this, &QskScrollView::scrollPosChanged, &QskControl::focusIndicatorRectChanged ); +#endif } QskListView::~QskListView() @@ -152,13 +156,17 @@ QskColorFilter QskListView::graphicFilterAt( int row, int col ) const QRectF QskListView::focusIndicatorRect() const { +#if FOCUS_ON_CURRENT if( m_data->selectedRow >= 0 ) { - const auto rect = effectiveSkinlet()->sampleRect( + auto rect = effectiveSkinlet()->sampleRect( this, contentsRect(), Cell, m_data->selectedRow ); - return rect.translated( -scrollPos() ); + rect = rect.translated( -scrollPos() ); + if ( rect.intersects( viewContentsRect() ) ) + return rect; } +#endif return Inherited::focusIndicatorRect(); } @@ -210,19 +218,8 @@ void QskListView::keyPressEvent( QKeyEvent* event ) } default: { - if ( const int steps = qskFocusChainIncrement( event ) ) - { - row += steps; - - if( row < 0 ) - { - row += rowCount(); - } - else if( row >= rowCount() ) - { - row %= rowCount(); - } - } + Inherited::keyPressEvent( event ); + return; } } From 638ee038aa95b1631004102679cdb5807e828ccf Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Thu, 27 Jul 2023 17:03:34 +0200 Subject: [PATCH 59/60] trying to reorganize QskListViewSkinlet to be able to make use of updateSeriesNode and friends --- skins/squiek/QskSquiekSkin.cpp | 6 +- src/controls/QskListView.cpp | 33 +- src/controls/QskListView.h | 6 +- src/controls/QskListViewSkinlet.cpp | 461 +++++++++++++------------- src/controls/QskListViewSkinlet.h | 21 +- src/controls/QskScrollViewSkinlet.cpp | 20 +- src/controls/QskScrollViewSkinlet.h | 1 - 7 files changed, 263 insertions(+), 285 deletions(-) diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index f3afbcb6..65fa848d 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -1057,9 +1057,11 @@ void Editor::setupListView() // alternating row colors setColor( Q::Cell | A::Lower, Qt::white ); - setColor( Q::Cell | A::Upper, m_pal.contrasted ); + setColor( Q::Cell | Q::Selected | A::Lower, m_pal.highlighted ); + + setColor( Q::Cell | A::Upper, m_pal.contrasted ); + setColor( Q::Cell | Q::Selected | A::Upper, m_pal.highlighted ); - setColor( Q::Cell | Q::Selected, m_pal.highlighted ); setColor( Q::Text | Q::Selected, m_pal.highlightedText ); } diff --git a/src/controls/QskListView.cpp b/src/controls/QskListView.cpp index 0dbe237a..08e5cf44 100644 --- a/src/controls/QskListView.cpp +++ b/src/controls/QskListView.cpp @@ -16,11 +16,27 @@ QSK_SUBCONTROL( QskListView, Cell ) QSK_SUBCONTROL( QskListView, Text ) +QSK_SUBCONTROL( QskListView, Graphic ) QSK_STATE( QskListView, Selected, QskAspect::FirstUserState ) #define FOCUS_ON_CURRENT 1 +static inline int qskRowAt( const QskListView* listView, const QPointF& pos ) +{ + const auto rect = listView->viewContentsRect(); + if ( rect.contains( pos ) ) + { + const auto y = pos.y() - rect.top() + listView->scrollPos().y(); + + const int row = y / listView->rowHeight(); + if ( row >= 0 && row < listView->rowCount() ) + return row; + } + + return -1; +} + class QskListView::PrivateData { public: @@ -146,14 +162,6 @@ QskListView::SelectionMode QskListView::selectionMode() const return m_data->selectionMode; } -QskColorFilter QskListView::graphicFilterAt( int row, int col ) const -{ - Q_UNUSED( row ) - Q_UNUSED( col ) - - return QskColorFilter(); -} - QRectF QskListView::focusIndicatorRect() const { #if FOCUS_ON_CURRENT @@ -269,13 +277,10 @@ void QskListView::mousePressEvent( QMouseEvent* event ) { if ( m_data->selectionMode != NoSelection ) { - const QRectF vr = viewContentsRect(); - if ( vr.contains( event->pos() ) ) + const int row = qskRowAt( this, qskMousePosition( event ) ); + if ( row >= 0 ) { - const int row = ( event->pos().y() - vr.top() + scrollPos().y() ) / rowHeight(); - if ( row >= 0 && row < rowCount() ) - setSelectedRow( row ); - + setSelectedRow( row ); return; } } diff --git a/src/controls/QskListView.h b/src/controls/QskListView.h index a8de657c..13fe8055 100644 --- a/src/controls/QskListView.h +++ b/src/controls/QskListView.h @@ -29,7 +29,7 @@ class QSK_EXPORT QskListView : public QskScrollView using Inherited = QskScrollView; public: - QSK_SUBCONTROLS( Cell, Text ) + QSK_SUBCONTROLS( Cell, Text, Graphic ) QSK_STATES( Selected ) enum SelectionMode @@ -63,10 +63,6 @@ class QSK_EXPORT QskListView : public QskScrollView Q_INVOKABLE virtual QVariant valueAt( int row, int col ) const = 0; -#if 1 - virtual QskColorFilter graphicFilterAt( int row, int col ) const; -#endif - QRectF focusIndicatorRect() const override; public Q_SLOTS: diff --git a/src/controls/QskListViewSkinlet.cpp b/src/controls/QskListViewSkinlet.cpp index 236d66cb..91d8f226 100644 --- a/src/controls/QskListViewSkinlet.cpp +++ b/src/controls/QskListViewSkinlet.cpp @@ -11,78 +11,165 @@ #include "QskBoxHints.h" #include "QskSGNode.h" #include "QskSkinStateChanger.h" +#include "QskQuick.h" #include #include #include -class QskListViewNode final : public QSGTransformNode +namespace { - public: - inline QskListViewNode( int columnCount ) - : m_columnCount( columnCount ) + class ForegroundNode : public QSGNode { - m_backgroundNode.setFlag( QSGNode::OwnedByParent, false ); - appendChildNode( &m_backgroundNode ); + public: + void invalidate() + { + removeAllChildNodes(); + m_columnCount = m_oldRowMin = m_oldRowMax = -1; + } - m_foregroundNode.setFlag( QSGNode::OwnedByParent, false ); - appendChildNode( &m_foregroundNode ); + void rearrangeNodes( int rowMin, int rowMax, int columnCount ) + { + const bool doReorder = ( columnCount == m_columnCount ) + && ( rowMin <= m_oldRowMax ) && ( rowMax >= m_oldRowMin ); + + if ( doReorder ) + { + /* + We have nodes that will be at a different position in the + list of child nodes - however their content might be unchanged. + + This is a common situation, when resizing or scrolling the list. + + To avoid that the text/graphic nodes have to be updated we + try to rearrange the nodes, so that they are in increasing + row order for further processing. + + To avoid delete/new calls we append the leading and prepend + the trailing nodes, so that they might be used later. + */ + + if ( rowMin >= m_oldRowMin ) + { + for ( int row = m_oldRowMin; row < rowMin; row++ ) + { + for ( int col = 0; col < columnCount; col++ ) + { + auto childNode = firstChild(); + removeChildNode( childNode ); + appendChildNode( childNode ); + } + } + } + else + { + for ( int row = rowMin; row < m_oldRowMin; row++ ) + { + for ( int col = 0; col < columnCount; col++ ) + { + auto childNode = lastChild(); + removeChildNode( childNode ); + prependChildNode( childNode ); + } + } + } + } + + m_oldRowMin = rowMin; + m_oldRowMax = rowMax; + m_columnCount = columnCount; + } + + private: + /* + When scrolling the majority of the child nodes are simply translated + while only few rows appear/disappear. To implement this in an efficient + way we store how the nodes were related to the rows in the previous update, + */ + + int m_oldRowMin = -1; + int m_oldRowMax = -1; + int m_columnCount = -1; + }; + + class ListViewNode final : public QSGTransformNode + { + public: + inline ListViewNode() + { + m_backgroundNode.setFlag( QSGNode::OwnedByParent, false ); + appendChildNode( &m_backgroundNode ); + + m_foregroundNode.setFlag( QSGNode::OwnedByParent, false ); + appendChildNode( &m_foregroundNode ); + } + + void initialize( const QskListView* listView ) + { + const auto scrollPos = listView->scrollPos(); + setMatrix( QTransform::fromTranslate( -scrollPos.x(), -scrollPos.y() ) ); + + m_clipRect = listView->viewContentsRect(); + m_rowHeight = listView->rowHeight(); + + m_rowMin = qFloor( scrollPos.y() / m_rowHeight ); + + const auto rowMax = ( scrollPos.y() + m_clipRect.height() ) / m_rowHeight; + m_rowMax = qFloor( rowMax - 10e-6 ); + + if ( m_rowMax >= listView->rowCount() ) + m_rowMax = listView->rowCount() - 1; + } + + QRectF clipRect() const { return m_clipRect; } + + int rowMin() const { return m_rowMin; } + int rowMax() const { return m_rowMax; } + int rowCount() const { return m_rowMax - m_rowMin + 1; } + + int rowHeight() const { return m_rowHeight; } + + QSGNode* backgroundNode() { return &m_backgroundNode; } + ForegroundNode* foregroundNode() { return &m_foregroundNode; } + + private: + // caching some calculations to speed things up + + QRectF m_clipRect; + qreal m_rowHeight; + + int m_rowMin, m_rowMax; + + QSGNode m_backgroundNode; + ForegroundNode m_foregroundNode; + }; +} + +static inline ListViewNode* qskListViewNode( const QskListView* listView ) +{ + if ( auto node = const_cast< QSGNode* >( qskPaintNode( listView ) ) ) + { + using namespace QskSGNode; + + node = findChildNode( node, QskScrollViewSkinlet::ContentsRootRole ); + if ( node ) + { + node = node->firstChild(); + if ( node ) + { + Q_ASSERT( node->type() == QSGNode::TransformNodeType ); + return static_cast< ListViewNode* >( node ); + } + } } - QSGNode* backgroundNode() - { - return &m_backgroundNode; - } + return nullptr; +} - QSGNode* foregroundNode() - { - return &m_foregroundNode; - } - - inline void resetRows( int rowMin, int rowMax ) - { - m_rowMin = rowMin; - m_rowMax = rowMax; - } - - inline int rowMin() const - { - return m_rowMin; - } - - inline int rowMax() const - { - return m_rowMax; - } - - inline bool intersects( int rowMin, int rowMax ) const - { - return ( rowMin <= m_rowMax ) && ( rowMax >= m_rowMin ); - } - - inline int nodeCount() const - { - return ( m_rowMin >= 0 ) ? ( m_rowMax - m_rowMin + 1 ) * m_columnCount : 0; - } - - inline int columnCount() const - { - return m_columnCount; - } - - inline void invalidate() - { - m_rowMin = m_rowMax = -1; - } - - private: - int m_columnCount; - int m_rowMin = -1; - int m_rowMax = -1; - - QSGNode m_backgroundNode; - QSGNode m_foregroundNode; -}; +static inline ListViewNode* qskListViewNode( const QskSkinnable* skinnable ) +{ + return qskListViewNode( static_cast< const QskListView* >( skinnable ) ); +} QskListViewSkinlet::QskListViewSkinlet( QskSkin* skin ) : Inherited( skin ) @@ -96,57 +183,36 @@ QSGNode* QskListViewSkinlet::updateContentsNode( { const auto listView = static_cast< const QskListView* >( scrollView ); - auto listViewNode = static_cast< QskListViewNode* >( node ); - if ( listViewNode == nullptr ) - listViewNode = new QskListViewNode( listView->columnCount() ); + auto listViewNode = QskSGNode::ensureNode< ListViewNode >( node ); + listViewNode->initialize( listView ); - QTransform transform; - transform.translate( -listView->scrollPos().x(), -listView->scrollPos().y() ); - listViewNode->setMatrix( transform ); - - updateBackgroundNodes( listView, listViewNode ); - updateForegroundNodes( listView, listViewNode ); + updateBackgroundNodes( listView, listViewNode->backgroundNode() ); + updateForegroundNodes( listView, listViewNode->foregroundNode() ); return listViewNode; } void QskListViewSkinlet::updateBackgroundNodes( - const QskListView* listView, QskListViewNode* listViewNode ) const + const QskListView* listView, QSGNode* backgroundNode ) const { using Q = QskListView; using A = QskAspect; - auto backgroundNode = listViewNode->backgroundNode(); - - const auto cellHeight = listView->rowHeight(); - const auto viewRect = listView->viewContentsRect(); - - const auto scrolledPos = listView->scrollPos(); - const int rowMin = qFloor( scrolledPos.y() / cellHeight ); - - int rowMax = qCeil( ( scrolledPos.y() + viewRect.height() ) / cellHeight ); - if ( rowMax >= listView->rowCount() ) - rowMax = listView->rowCount() - 1; - - const auto x0 = viewRect.left() + scrolledPos.x(); - const auto y0 = viewRect.top(); + auto listViewNode = static_cast< const ListViewNode* >( backgroundNode->parent() ); auto rowNode = backgroundNode->firstChild(); - const auto boxHints1 = listView->boxHints( Q::Cell | A::Lower ); - const auto boxHints2 = listView->boxHints( Q::Cell | A::Upper ); - - for ( int row = rowMin; row <= rowMax; row++ ) + for ( int row = listViewNode->rowMin(); row <= listViewNode->rowMax(); row++ ) { - /* - We do not use sampleRect to avoid doing the calculation - of viewRect for each row. - */ - const QRectF rect( x0, y0 + row * cellHeight, viewRect.width(), cellHeight ); + QskSkinStateChanger stateChanger( listView ); + stateChanger.setStates( sampleStates( listView, Q::Cell, row ) ); - auto newNode = updateBoxNode( listView, rowNode, rect, - ( row % 2 ) ? boxHints2 : boxHints1 ); + const auto rect = sampleRect( listView, listView->contentsRect(), Q::Cell, row ); + const QskAspect aspect = Q::Cell | ( ( row % 2 ) ? A::Upper : A::Lower ); + const auto boxHints = listView->boxHints( aspect ); + + auto newNode = updateBoxNode( listView, rowNode, rect, boxHints ); if ( newNode ) { if ( newNode->parent() != backgroundNode ) @@ -156,45 +222,28 @@ void QskListViewSkinlet::updateBackgroundNodes( } } - const int rowSelected = listView->selectedRow(); - if ( rowSelected >= rowMin && rowSelected <= rowMax ) - { - QskSkinStateChanger stateChanger( listView ); - stateChanger.setStates( listView->skinStates() | QskListView::Selected ); - - const QRectF rect( x0, y0 + rowSelected * cellHeight, - viewRect.width(), cellHeight ); - - rowNode = updateBoxNode( listView, rowNode, rect, Q::Cell ); - if ( rowNode && rowNode->parent() != backgroundNode ) - backgroundNode->appendChildNode( rowNode ); - } - - QskSGNode::removeAllChildNodesAfter( backgroundNode, rowNode ); + QskSGNode::removeAllChildNodesFrom( backgroundNode, rowNode ); } void QskListViewSkinlet::updateForegroundNodes( - const QskListView* listView, QskListViewNode* listViewNode ) const + const QskListView* listView, QSGNode* parentNode ) const { - auto parentNode = listViewNode->foregroundNode(); + auto foregroundNode = static_cast< ForegroundNode* >( parentNode ); if ( listView->rowCount() <= 0 || listView->columnCount() <= 0 ) { - parentNode->removeAllChildNodes(); - listViewNode->invalidate(); + foregroundNode->invalidate(); return; } - const auto margins = listView->paddingHint( QskListView::Cell ); + auto listViewNode = static_cast< const ListViewNode* >( parentNode->parent() ); - const auto cr = listView->viewContentsRect(); - const auto scrolledPos = listView->scrollPos(); + const auto clipRect = listViewNode->clipRect(); - const int rowMin = qFloor( scrolledPos.y() / listView->rowHeight() ); + const int rowMin = listViewNode->rowMin(); + const int rowMax = listViewNode->rowMax(); - int rowMax = rowMin + qCeil( cr.height() / listView->rowHeight() ); - if ( rowMax >= listView->rowCount() ) - rowMax = listView->rowCount() - 1; + foregroundNode->rearrangeNodes( rowMin, rowMax, listView->columnCount() ); #if 1 // should be optimized for visible columns only @@ -202,67 +251,28 @@ void QskListViewSkinlet::updateForegroundNodes( const int colMax = listView->columnCount() - 1; #endif - bool forwards = true; + const auto margins = listView->paddingHint( QskListView::Cell ); - if ( listViewNode->intersects( rowMin, rowMax ) ) - { - /* - We try to avoid reallcations when scrolling, by reusing - the nodes of the cells leaving the viewport for those becoming visible. - */ - - forwards = ( rowMin >= listViewNode->rowMin() ); - - if ( forwards ) - { - // usually scrolling down - for ( int row = listViewNode->rowMin(); row < rowMin; row++ ) - { - for ( int col = 0; col < listView->columnCount(); col++ ) - { - QSGNode* childNode = parentNode->firstChild(); - parentNode->removeChildNode( childNode ); - parentNode->appendChildNode( childNode ); - } - } - } - else - { - // usually scrolling up - for ( int row = rowMax; row < listViewNode->rowMax(); row++ ) - { - for ( int col = 0; col < listView->columnCount(); col++ ) - { - QSGNode* childNode = parentNode->lastChild(); - parentNode->removeChildNode( childNode ); - parentNode->prependChildNode( childNode ); - } - } - } - } - - updateVisibleForegroundNodes( listView, listViewNode, - rowMin, rowMax, colMin, colMax, margins, forwards ); + updateVisibleForegroundNodes( + listView, foregroundNode, rowMin, rowMax, margins ); // finally putting the nodes into their position - auto node = parentNode->firstChild(); + auto node = foregroundNode->firstChild(); const auto rowHeight = listView->rowHeight(); - auto y = cr.top() + rowMin * rowHeight; + auto y = clipRect.top() + rowMin * rowHeight; for ( int row = rowMin; row <= rowMax; row++ ) { - qreal x = cr.left(); + qreal x = clipRect.left(); for ( int col = colMin; col <= colMax; col++ ) { Q_ASSERT( node->type() == QSGNode::TransformNodeType ); auto transformNode = static_cast< QSGTransformNode* >( node ); - QTransform transform; - transform.translate( x + margins.left(), y + margins.top() ); - - transformNode->setMatrix( transform ); + transformNode->setMatrix( + QTransform::fromTranslate( x + margins.left(), y + margins.top() ) ); node = node->nextSibling(); x += listView->columnWidth( col ); @@ -270,72 +280,36 @@ void QskListViewSkinlet::updateForegroundNodes( y += rowHeight; } - - listViewNode->resetRows( rowMin, rowMax ); } void QskListViewSkinlet::updateVisibleForegroundNodes( - const QskListView* listView, QskListViewNode* listViewNode, - int rowMin, int rowMax, int colMin, int colMax, const QMarginsF& margins, - bool forward ) const + const QskListView* listView, QSGNode* parentNode, + int rowMin, int rowMax, const QMarginsF& margins ) const { - auto parentNode = listViewNode->foregroundNode(); + auto node = parentNode->firstChild(); - const int rowCount = rowMax - rowMin + 1; - const int colCount = colMax - colMin + 1; - const int obsoleteNodesCount = listViewNode->nodeCount() - rowCount * colCount; - - if ( forward ) + for ( int row = rowMin; row <= rowMax; row++ ) { - for ( int i = 0; i < obsoleteNodesCount; i++ ) - delete parentNode->lastChild(); + const auto h = listView->rowHeight() - ( margins.top() + margins.bottom() ); - auto node = parentNode->firstChild(); - - for ( int row = rowMin; row <= rowMax; row++ ) + for ( int col = 0; col < listView->columnCount(); col++ ) { - const auto h = listView->rowHeight() - ( margins.top() + margins.bottom() ); + const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); - for ( int col = 0; col < listView->columnCount(); col++ ) - { - const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); + node = updateForegroundNode( listView, + parentNode, static_cast< QSGTransformNode* >( node ), + row, col, QSizeF( w, h ) ); - node = updateForegroundNode( listView, - parentNode, static_cast< QSGTransformNode* >( node ), - row, col, QSizeF( w, h ), forward ); - - node = node->nextSibling(); - } + node = node->nextSibling(); } } - else - { - for ( int i = 0; i < obsoleteNodesCount; i++ ) - delete parentNode->firstChild(); - auto* node = parentNode->lastChild(); - - for ( int row = rowMax; row >= rowMin; row-- ) - { - const qreal h = listView->rowHeight() - ( margins.top() + margins.bottom() ); - - for ( int col = listView->columnCount() - 1; col >= 0; col-- ) - { - const auto w = listView->columnWidth( col ) - ( margins.left() + margins.right() ); - - node = updateForegroundNode( listView, - parentNode, static_cast< QSGTransformNode* >( node ), - row, col, QSizeF( w, h ), forward ); - - node = node->previousSibling(); - } - } - } + QskSGNode::removeAllChildNodesFrom( parentNode, node ); } QSGTransformNode* QskListViewSkinlet::updateForegroundNode( const QskListView* listView, QSGNode* parentNode, QSGTransformNode* cellNode, - int row, int col, const QSizeF& size, bool forward ) const + int row, int col, const QSizeF& size ) const { const QRectF cellRect( 0.0, 0.0, size.width(), size.height() ); @@ -407,10 +381,7 @@ QSGTransformNode* QskListViewSkinlet::updateForegroundNode( } else { - if ( forward ) - parentNode->appendChildNode( newCellNode ); - else - parentNode->prependChildNode( newCellNode ); + parentNode->appendChildNode( newCellNode ); } } @@ -420,14 +391,11 @@ QSGTransformNode* QskListViewSkinlet::updateForegroundNode( QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView, QSGNode* contentNode, const QRectF& rect, int row, int col ) const { + using Q = QskListView; using namespace QskSGNode; - auto rowStates = listView->skinStates(); - if ( row == listView->selectedRow() ) - rowStates |= QskListView::Selected; - QskSkinStateChanger stateChanger( listView ); - stateChanger.setStates( rowStates ); + stateChanger.setStates( sampleStates( listView, Q::Cell, row ) ); QSGNode* newNode = nullptr; @@ -439,7 +407,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView, */ #endif const auto alignment = listView->alignmentHint( - QskListView::Cell, Qt::AlignVCenter | Qt::AlignLeft ); + Q::Cell, Qt::AlignVCenter | Qt::AlignLeft ); const auto value = listView->valueAt( row, col ); @@ -448,7 +416,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView, if ( nodeRole( contentNode ) == GraphicRole ) newNode = contentNode; - const auto colorFilter = listView->graphicFilterAt( row, col ); + const auto colorFilter = listView->effectiveGraphicFilter( Q::Graphic ); newNode = updateGraphicNode( listView, newNode, value.value< QskGraphic >(), colorFilter, rect, alignment ); @@ -462,7 +430,7 @@ QSGNode* QskListViewSkinlet::updateCellNode( const QskListView* listView, newNode = contentNode; newNode = updateTextNode( listView, newNode, rect, alignment, - value.toString(), QskListView::Text ); + value.toString(), Q::Text ); if ( newNode ) setNodeRole( newNode, TextRole ); @@ -494,22 +462,43 @@ QSizeF QskListViewSkinlet::sizeHint( const QskSkinnable* skinnable, return QSizeF( w, -1.0 ); } +QskAspect::States QskListViewSkinlet::sampleStates( const QskSkinnable* skinnable, + QskAspect::Subcontrol subControl, int index ) const +{ + using Q = QskListView; + + if ( subControl == Q::Cell || subControl == Q::Text || subControl == Q::Graphic ) + { + const auto listView = static_cast< const QskListView* >( skinnable ); + + auto states = listView->skinStates(); + if ( index == listView->selectedRow() ) + states |= Q::Selected; + + return states; + } + + return Inherited::sampleStates( skinnable, subControl, index ); +} + QRectF QskListViewSkinlet::sampleRect( const QskSkinnable* skinnable, const QRectF& contentsRect, QskAspect::Subcontrol subControl, int index ) const { using Q = QskListView; + const auto listView = static_cast< const QskListView* >( skinnable ); if ( subControl == Q::Cell ) { - const auto cellHeight = listView->rowHeight(); - const auto viewRect = listView->viewContentsRect(); - const auto scrolledPos = listView->scrollPos(); + auto node = qskListViewNode( listView ); + const auto clipRect = node ? node->clipRect() : listView->viewContentsRect(); - const double x0 = viewRect.left() + scrolledPos.x(); - const double y0 = viewRect.top(); + const auto w = clipRect.width(); + const auto h = listView->rowHeight(); + const auto x = clipRect.left() + listView->scrollPos().x(); + const auto y = clipRect.top() + index * h; - return QRectF( x0, y0 + index * cellHeight, viewRect.width(), cellHeight ); + return QRectF( x, y, w, h ); } return Inherited::sampleRect( skinnable, contentsRect, subControl, index ); diff --git a/src/controls/QskListViewSkinlet.h b/src/controls/QskListViewSkinlet.h index 4f174962..e26f4cb1 100644 --- a/src/controls/QskListViewSkinlet.h +++ b/src/controls/QskListViewSkinlet.h @@ -9,7 +9,6 @@ #include "QskScrollViewSkinlet.h" class QskListView; -class QskListViewNode; class QMarginsF; class QSizeF; @@ -40,25 +39,27 @@ class QSK_EXPORT QskListViewSkinlet : public QskScrollViewSkinlet QRectF sampleRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol, int index ) const override; + QskAspect::States sampleStates( const QskSkinnable*, + QskAspect::Subcontrol, int index ) const override; + protected: QSGNode* updateContentsNode( const QskScrollView*, QSGNode* ) const override; - virtual QSGNode* updateCellNode( const QskListView*, - QSGNode*, const QRectF&, int row, int col ) const; - private: - void updateForegroundNodes( const QskListView*, QskListViewNode* ) const; - void updateBackgroundNodes( const QskListView*, QskListViewNode* ) const; + void updateForegroundNodes( const QskListView*, QSGNode* ) const; + void updateBackgroundNodes( const QskListView*, QSGNode* ) const; void updateVisibleForegroundNodes( - const QskListView*, QskListViewNode*, - int rowMin, int rowMax, int colMin, int colMax, - const QMarginsF& margin, bool forward ) const; + const QskListView*, QSGNode*, + int rowMin, int rowMax, const QMarginsF& margin ) const; QSGTransformNode* updateForegroundNode( const QskListView*, QSGNode* parentNode, QSGTransformNode* cellNode, - int row, int col, const QSizeF&, bool forward ) const; + int row, int col, const QSizeF& ) const; + + QSGNode* updateCellNode( const QskListView*, + QSGNode*, const QRectF&, int row, int col ) const; }; #endif diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index 3bc10a11..3ab7848e 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -17,7 +17,9 @@ static void qskAlignedHandle( qreal start, qreal end, qreal scrollBarLength, qreal minHandleLength, qreal& handleStart, qreal& handleEnd ) { - minHandleLength = qBound( 4.0, minHandleLength, scrollBarLength ); + // no qBound: scrollBarLength might be < 4.0 + minHandleLength = qMax( 4.0, minHandleLength ); + minHandleLength = qMin( minHandleLength, scrollBarLength ); handleStart = start * scrollBarLength; handleEnd = end * scrollBarLength; @@ -178,22 +180,6 @@ QSGNode* QskScrollViewSkinlet::updateContentsNode( return nullptr; } -QSGNode* QskScrollViewSkinlet::contentsNode( const QskScrollView* scrollView ) -{ - if ( auto node = const_cast< QSGNode* >( qskPaintNode( scrollView ) ) ) - { - node = QskSGNode::findChildNode( node, ContentsRootRole ); - if ( node ) - { - node = node->firstChild(); - if ( node ) - return node->firstChild(); - } - } - - return nullptr; -} - QRectF QskScrollViewSkinlet::viewportRect( const QskScrollView* scrollView, const QRectF& contentsRect ) const { diff --git a/src/controls/QskScrollViewSkinlet.h b/src/controls/QskScrollViewSkinlet.h index 16c6c81f..0bc9d190 100644 --- a/src/controls/QskScrollViewSkinlet.h +++ b/src/controls/QskScrollViewSkinlet.h @@ -43,7 +43,6 @@ class QSK_EXPORT QskScrollViewSkinlet : public QskSkinlet quint8 nodeRole, QSGNode* ) const override; virtual QSGNode* updateContentsNode( const QskScrollView*, QSGNode* ) const; - QSGNode* contentsNode( const QskScrollView* ); private: QSGNode* updateContentsRootNode( const QskScrollView*, QSGNode* ) const; From a7aef1a8a0a44204364d57ef7f0beac5ff90e233 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 28 Jul 2023 07:43:50 +0200 Subject: [PATCH 60/60] using the padding for expanding the scrollbars to avoid having an impact on the viewport size --- skins/fluent2/QskFluent2Skin.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/skins/fluent2/QskFluent2Skin.cpp b/skins/fluent2/QskFluent2Skin.cpp index 66bbbe5a..3a47da77 100644 --- a/skins/fluent2/QskFluent2Skin.cpp +++ b/skins/fluent2/QskFluent2Skin.cpp @@ -26,13 +26,8 @@ - QskPageIndicator - - QskScrollView - - The extended mode of the scrollbar needs to be implemented - - QskListView - - hover state is not implemented - Indicator subcontrol might be better than using the border of the selection box - cell padding unclear @@ -1103,11 +1098,19 @@ void Editor::setupScrollViewMetrics() for ( auto subControl : { Q::HorizontalScrollBar, Q::VerticalScrollBar } ) { - const auto aspect = subControl | A::Size; + setMetric( subControl | A::Size, 6 ); - setMetric( aspect, 2 ); - setMetric( aspect | Q::Hovered, 6 ); - setMetric( aspect | Q::Pressed, 6 ); + // The scrollbar is expanding, when being hovered/pressed + + const qreal padding = 4; + + if ( subControl == Q::HorizontalScrollBar ) + setPadding( Q::HorizontalScrollBar, 0, padding, 0, 0 ); + else + setPadding( Q::VerticalScrollBar, padding, 0, 0, 0 ); + + setPadding( subControl | Q::Hovered, 0 ); + setPadding( subControl | Q::Pressed, 0 ); setBoxShape( subControl, 100, Qt::RelativeSize ); setAnimation( subControl | A::Metric, 100 ); @@ -1118,9 +1121,6 @@ void Editor::setupScrollViewMetrics() supported by the skinlet. Do we want to have this. TODO ... */ - setAlignment( Q::VerticalScrollBar, Qt::AlignHCenter ); - setAlignment( Q::HorizontalScrollBar, Qt::AlignVCenter ); - // handles setBoxShape( Q::HorizontalScrollHandle, 100, Qt::RelativeSize );