QskSegmentedBarSkinlet fixes

This commit is contained in:
Uwe Rathmann 2023-07-05 18:28:57 +02:00
parent d33e1f1a90
commit 4bf1b019c7
5 changed files with 105 additions and 77 deletions

View File

@ -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;

View File

@ -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 } );
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.hoverOpacity ) );
setGradient( Q::Segment | Q::Selected | Q::Disabled, m_pal.onSurface12,
{ QskStateCombination::CombinationNoState, Q::Minimum | Q::Maximum } );
setGradient( Q::Segment | Q::Selected | Q::Focused,
flattenedColor( m_pal.onSurface, m_pal.secondaryContainer, m_pal.focusOpacity ) );
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 } );
}
}
{

View File

@ -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
{

View File

@ -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 );

View File

@ -14,12 +14,74 @@
#include "QskSkin.h"
#include "QskSkinStateChanger.h"
#include "QskSubcontrolLayoutEngine.h"
#include "QskBoxHints.h"
#include <qfontmetrics.h>
#include <qmath.h>
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;
@ -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"