From 72190aee9168d97369317c4208e262908b1b6861 Mon Sep 17 00:00:00 2001 From: Clemens Manert Date: Sat, 25 Feb 2023 22:25:43 +0100 Subject: [PATCH] Fix alighnment if sizes of symbol and button differ --- skins/material3/QskMaterial3Skin.cpp | 7 ++- skins/squiek/QskSquiekSkin.cpp | 1 + src/controls/QskRadioBoxSkinlet.cpp | 90 +++++++++++++++++++++------- src/controls/QskRadioBoxSkinlet.h | 3 + 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/skins/material3/QskMaterial3Skin.cpp b/skins/material3/QskMaterial3Skin.cpp index 104272d6..e41a653b 100644 --- a/skins/material3/QskMaterial3Skin.cpp +++ b/skins/material3/QskMaterial3Skin.cpp @@ -54,6 +54,7 @@ #include #include +#include static const int qskDuration = 150; @@ -479,10 +480,11 @@ void Editor::setupRadioBox() setStrutSize( Q::Symbol, { 10_dp, 10_dp }); setStrutSize( Q::Ripple, { 40_dp, 40_dp }); - setMargin( Q::Button, QskMargins( 10_dp, 0, 10, 0)); - setMargin( Q::Text, QskMargins( 10_dp, 0, 0, 0 )); + setAlignment( Q::Symbol, Qt::AlignCenter ); setAlignment( Q::Text, Qt::AlignBottom ); + setMargin( Q::Text, QskMargins( 10_dp, 0, 10_dp, 0)); + setBoxShape(Q::Button, 20_dp); setBoxShape(Q::Ripple, 40_dp); setBoxBorderMetrics( Q::Button, 2_dp ); @@ -501,7 +503,6 @@ void Editor::setupRadioBox() setBoxBorderColors( Q::Button | Q::Disabled | Q::Selected, m_pal.onSurface38 ); setColor( Q::Text | Q::Disabled, m_pal.onSurface38 ); setColor( Q::Symbol | Q::Disabled, m_pal.onSurface38 ); - } void Editor::setupFocusIndicator() diff --git a/skins/squiek/QskSquiekSkin.cpp b/skins/squiek/QskSquiekSkin.cpp index c93525e8..58ca99d1 100644 --- a/skins/squiek/QskSquiekSkin.cpp +++ b/skins/squiek/QskSquiekSkin.cpp @@ -639,6 +639,7 @@ void Editor::setupRadioBox() setMargin( Q::Text, QskMargins( qskDpiScaled( 10 ), 0, qskDpiScaled( 10 ), 0 )); + setAlignment( Q::Symbol, Qt::AlignCenter ); setAlignment( Q::Text, Qt::AlignBottom ); } diff --git a/src/controls/QskRadioBoxSkinlet.cpp b/src/controls/QskRadioBoxSkinlet.cpp index 18091e1c..79573679 100644 --- a/src/controls/QskRadioBoxSkinlet.cpp +++ b/src/controls/QskRadioBoxSkinlet.cpp @@ -9,6 +9,7 @@ #include "QskGraphic.h" #include "QskFunctions.h" #include "QskSkin.h" +#include #include namespace { @@ -48,36 +49,36 @@ QRectF QskRadioBoxSkinlet::subControlRect( const QskSkinnable* skinnable, auto radio = static_cast( skinnable ); if( subcontrol == Q::Ripple ) { - return buttonRect(radio, Q::Ripple, contentsRect, radio->positionHint(Q::Ripple)); + return rippleRect(radio, contentsRect); } return contentsRect; } QSizeF QskRadioBoxSkinlet::sizeHint( const QskSkinnable* skinnable, - Qt::SizeHint, const QSizeF& ) const + Qt::SizeHint, const QSizeF& ) const { auto radio = static_cast( skinnable ); - const auto font = skinnable->effectiveFont( Q::Text ); + const auto font = skinnable->effectiveFont( Q::Text ); const auto textMargins = skinnable->marginHint( Q::Text ); const auto buttonMargins = skinnable->marginHint( Q::Button ); const auto symbolMargins = skinnable->marginHint( Q::Symbol ); - + qreal maxTextWidth = 0; for(auto& item : radio->items() ) { maxTextWidth = std::max( maxTextWidth, qskHorizontalAdvance( font, item ) ); } - auto radioWidth = radio->strutSizeHint(Q::Button).width(); + auto buttonWidth = radio->strutSizeHint(Q::Button).width(); auto symbolWidth = radio->strutSizeHint(Q::Symbol).width(); maxTextWidth += textMargins.left() + textMargins.right(); - radioWidth += buttonMargins.left() + buttonMargins.right(); + buttonWidth += buttonMargins.left() + buttonMargins.right(); symbolWidth += symbolMargins.left() + symbolMargins.right(); auto spacing = radio->spacingHint(Q::Panel); - return QSizeF( maxTextWidth + qMax(radioWidth, symbolWidth), + return QSizeF( maxTextWidth + qMax(buttonWidth, symbolWidth), ( lineHeight( radio ) + spacing ) * radio->items().size() - spacing ); } @@ -123,13 +124,40 @@ qreal QskRadioBoxSkinlet::lineHeight(const QskRadioBox* target) const { return qMax( strutHight, fontHeight ); } - int QskRadioBoxSkinlet::sampleCount( const QskSkinnable* skinnable, QskAspect::Subcontrol ) const { const auto radio = static_cast< const QskRadioBox* >( skinnable ); return radio->items().count(); } +QSizeF QskRadioBoxSkinlet::buttonSymbolSize( const QskRadioBox* radio ) const { + auto buttonStrut = radio->strutSizeHint( Q::Button ); + auto symbolStrut = radio->strutSizeHint( Q::Symbol ); + + buttonStrut = buttonStrut.grownBy( radio->marginHint( Q::Button ) ); + symbolStrut = symbolStrut.grownBy( radio->marginHint( Q::Symbol ) ); + + return QSizeF( + qMax( buttonStrut.width(), symbolStrut.width() ), + qMax( buttonStrut.height(), symbolStrut.height() ) ); +} + +QRectF QskRadioBoxSkinlet::rippleRect( const QskRadioBox* radio, + const QRectF& rect ) const { + auto ripplePosition = radio->positionHint( Q::Ripple ); + + if( ripplePosition < 0 ) { + return QRectF(); + } + + auto button = buttonRect( radio, Q::Button, rect, ripplePosition ); + auto rippleSize = radio->strutSizeHint( Q::Ripple ); + button.moveLeft( button.x() - ( rippleSize.width() - button.width() ) / 2 ); + button.moveTop( button.y() - ( rippleSize.height() - button.height() ) / 2 ); + button.setSize( rippleSize ); + return button; +} + QRectF QskRadioBoxSkinlet::buttonRect( const QskRadioBox* radio, const QskAspect::Subcontrol target, const QRectF& rect, double index ) const { @@ -138,19 +166,38 @@ QRectF QskRadioBoxSkinlet::buttonRect( const QskRadioBox* radio, } auto result = rect; - result.setSize( radio->strutSizeHint( target ) ); + result.setSize( radio->strutSizeHint( target )); auto spacing = radio->spacingHint(Q::Panel); - result.moveTop( ( lineHeight( radio ) + spacing ) * index - + (lineHeight(radio) - result.size().height()) / 2); + result.moveTop( ( lineHeight( radio ) + spacing ) * index ); + + auto margins = radio->marginHint( target ); + auto withMargins = result.size().grownBy( margins ); + + auto maxSize = buttonSymbolSize( radio ); + auto alignment = radio->alignmentHint( target ); + + // Vertical positioning + auto alignHeight = maxSize.height() - withMargins.height(); + if( alignment.testFlag( Qt::AlignVCenter )) { + result.moveTop( result.top() + alignHeight / 2); + } else if( alignment.testFlag( Qt::AlignBottom ) ) { + result.moveTop( result.top() + alignHeight ); + } + result.moveTop( result.top() + margins.top()); + + // Horizontal positioning + auto alignWidth = 0; + if( alignment.testFlag( Qt::AlignHCenter ) ) { + alignWidth = (maxSize.width() - withMargins.width()) / 2; + } else if ( alignment.testFlag( Qt::AlignRight )) { + alignWidth = maxSize.width() - withMargins.width(); + } - auto maxWidth = qMax(radio->strutSizeHint( Q::Button ).width(), - radio->strutSizeHint( Q::Symbol ).width()); - if( radio->layoutMirroring() ) { - result.moveRight( rect.width() - (maxWidth - result.width())/2); + result.moveRight( rect.width() - (alignWidth + margins.right() )); } else { - result.moveLeft((maxWidth - result.width()) / 2); + result.moveLeft( margins.left() + alignWidth ); } return result; @@ -175,16 +222,17 @@ QRectF QskRadioBoxSkinlet::textRect( const QskRadioBox* radio, + textMargins.top()); result.setHeight( lh ); - result.setWidth( qskHorizontalAdvance( font, radio->items()[index] ) ); + result.setWidth( qskHorizontalAdvance( font, text ) ); - auto buttonWidth = buttonRect( radio, Q::Button, rect, index ).width(); + auto button = buttonRect( radio, Q::Button, rect, index ); auto buttonsMargins = radio->marginHint( Q::Button ); + auto buttonWidth = button.marginsAdded( buttonsMargins ).width(); + if( radio->layoutMirroring() ) { result.moveLeft( rect.width() - textMargins.right() - - result.width() - buttonWidth - buttonsMargins.left()); + - result.width() - buttonWidth); } else { - result.moveLeft( buttonWidth + textMargins.left() - + radio->marginHint( Q::Button ).right()); + result.moveLeft( buttonWidth + textMargins.left() ); } return result; diff --git a/src/controls/QskRadioBoxSkinlet.h b/src/controls/QskRadioBoxSkinlet.h index a258125d..831cacca 100644 --- a/src/controls/QskRadioBoxSkinlet.h +++ b/src/controls/QskRadioBoxSkinlet.h @@ -37,8 +37,11 @@ class QSK_EXPORT QskRadioBoxSkinlet : public QskSkinlet QRectF sampleRect( const QskSkinnable*, const QRectF&, QskAspect::Subcontrol, int index ) const override; + QSizeF buttonSymbolSize( const QskRadioBox* radio ) const; QRectF textRect( const QskRadioBox*, const QRectF&, int ) const; QRectF buttonRect( const QskRadioBox*, const QskAspect::Subcontrol target, const QRectF&, double ) const; + QRectF rippleRect( const QskRadioBox*, const QRectF& ) const; + QskAspect::States sampleStates( const QskSkinnable*, QskAspect::Subcontrol, int index ) const override;