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"