formal adjustments

This commit is contained in:
Uwe Rathmann 2023-02-26 17:04:47 +01:00
parent c4efbf65f0
commit 2e667f3ff2
7 changed files with 412 additions and 338 deletions

View File

@ -119,6 +119,8 @@ namespace
: QskLinearBox( Qt::Horizontal, parent ) : QskLinearBox( Qt::Horizontal, parent )
{ {
setSpacing( 20 ); setSpacing( 20 );
setSizePolicy( Qt::Vertical, QskSizePolicy::Fixed );
setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge ); setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge );
for ( auto orientation : { Qt::Vertical, Qt::Horizontal } ) for ( auto orientation : { Qt::Vertical, Qt::Horizontal } )
@ -144,7 +146,7 @@ namespace
CheckButtonBox( QQuickItem* parent = nullptr ) CheckButtonBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, 2, parent ) : QskLinearBox( Qt::Horizontal, 2, parent )
{ {
setSpacing( 40 ); setSpacing( 20 );
setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge ); setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge );
auto button1 = new QskCheckBox( "Options 1", this ); auto button1 = new QskCheckBox( "Options 1", this );
@ -155,10 +157,22 @@ namespace
auto button3 = new QskCheckBox( "Error", this ); auto button3 = new QskCheckBox( "Error", this );
button3->setSkinStateFlag( QskCheckBox::Error ); button3->setSkinStateFlag( QskCheckBox::Error );
}
};
class RadioButtonBox : public QskLinearBox
{
public:
RadioButtonBox( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, parent )
{
setSpacing( 20 );
setExtraSpacingAt( Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge );
new QskRadioBox( { "One", "Two", "Three" }, this ); new QskRadioBox( { "One", "Two", "Three" }, this );
auto radios = new QskRadioBox( { "One", "Two", "Three" }, this );
radios->setLayoutMirroring(true); auto radioBox = new QskRadioBox( { "One", "Two", "Three" }, this );
radioBox->setLayoutMirroring( true );
} }
}; };
} }
@ -176,5 +190,8 @@ void ButtonPage::populate()
new QskSeparator( Qt::Horizontal, this ); new QskSeparator( Qt::Horizontal, this );
new SwitchButtonBox( this ); new SwitchButtonBox( this );
new QskSeparator( Qt::Horizontal, this ); new QskSeparator( Qt::Horizontal, this );
new CheckButtonBox( this );
auto hBox = new QskLinearBox( Qt::Horizontal, this );
new CheckButtonBox( hBox );
new RadioButtonBox( hBox );
} }

View File

@ -14,51 +14,39 @@ namespace
{ {
class Box : public QskGridBox class Box : public QskGridBox
{ {
public: public:
Box( QQuickItem* parent ) Box( QQuickItem* parent )
: QskGridBox( parent ) : QskGridBox( parent )
{ {
auto* messageButton = new QskPushButton( "message", this ); auto* messageButton = new QskPushButton( "message", this );
connect( messageButton, &QskPushButton::clicked, this, []() connect( messageButton, &QskPushButton::clicked, this,
{ []() { qskDialog->message( "message", "text", QskStandardSymbol::Ok ); } );
qskDialog->message( "message", "text", QskStandardSymbol::Ok );
} );
auto* informationButton = new QskPushButton( "information", this ); auto* informationButton = new QskPushButton( "information", this );
connect( informationButton, &QskPushButton::clicked, this, []() connect( informationButton, &QskPushButton::clicked, this,
{ []() { qskDialog->information( "information", "text" ); } );
qskDialog->information( "information", "text" );
} );
auto* warningButton = new QskPushButton( "warning", this ); auto* warningButton = new QskPushButton( "warning", this );
connect( warningButton, &QskPushButton::clicked, this, []() connect( warningButton, &QskPushButton::clicked, this,
{ []() { qskDialog->warning( "warning", "text" ); } );
qskDialog->warning( "warning", "text" );
} );
auto* criticalButton = new QskPushButton( "critical", this ); auto* criticalButton = new QskPushButton( "critical", this );
connect( criticalButton, &QskPushButton::clicked, this, []() connect( criticalButton, &QskPushButton::clicked, this,
{ []() { qskDialog->critical( "critical", "text" ); } );
qskDialog->critical( "critical", "text" );
} );
auto* questionButton = new QskPushButton( "question", this ); auto* questionButton = new QskPushButton( "question", this );
connect( questionButton, &QskPushButton::clicked, this, []() connect( questionButton, &QskPushButton::clicked, this,
{ []() { qskDialog->question( "question", "text" ); } );
qskDialog->question( "question", "text" );
} );
auto* selectButton = new QskPushButton( "select", this ); auto* selectButton = new QskPushButton( "select", this );
connect( selectButton, &QskPushButton::clicked, this, []() connect( selectButton, &QskPushButton::clicked, this,
{ []() { qskDialog->select( "select", "text", { "yes", "no", "maybe" } ); } );
qskDialog->select( "select", "text", { "yes", "no", "maybe" } );
} );
addItem( messageButton, 0, 0 ); addItem( messageButton, 0, 0 );
addItem( informationButton, 0, 1 ); addItem( informationButton, 0, 1 );

View File

@ -32,7 +32,7 @@ namespace
{ {
auto bar = new QskSegmentedBar( orientation, this ); auto bar = new QskSegmentedBar( orientation, this );
for ( const auto text: texts ) for ( const auto text : texts )
bar->addOption( {}, text ); bar->addOption( {}, text );
} }

View File

@ -1,3 +1,8 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskRadioBox.h" #include "QskRadioBox.h"
#include "QskEvent.h" #include "QskEvent.h"
#include "QskAnimationHint.h" #include "QskAnimationHint.h"
@ -13,175 +18,194 @@ QSK_STATE( QskRadioBox, Selected, QskAspect::FirstUserState << 1 )
QSK_STATE( QskRadioBox, Pressed, QskAspect::FirstUserState << 2 ) QSK_STATE( QskRadioBox, Pressed, QskAspect::FirstUserState << 2 )
QSK_STATE( QskRadioBox, Focused, QskAspect::FirstUserState << 3 ) QSK_STATE( QskRadioBox, Focused, QskAspect::FirstUserState << 3 )
class QskRadioBox::PrivateData { class QskRadioBox::PrivateData
public: {
public:
QStringList items; QStringList items;
int selectedIndex = -1; int selectedIndex = -1;
int focusedIndex = -1; int focusedIndex = -1;
int pressedIndex = -1; int pressedIndex = -1;
}; };
QskRadioBox::QskRadioBox( QQuickItem* parent ) : QskRadioBox::QskRadioBox( QQuickItem* parent )
Inherited( parent ), : Inherited( parent )
m_data( new PrivateData{} ) { , m_data( new PrivateData() )
{
setFocusPolicy( Qt::NoFocus ); setFocusPolicy( Qt::NoFocus );
setAcceptedMouseButtons( Qt::LeftButton ); setAcceptedMouseButtons( Qt::LeftButton );
connect(this, &QskRadioBox::itemsChanged, this, connect(this, &QskRadioBox::itemsChanged, this,
[this]( const QStringList& items ) { [this]( const QStringList& items )
if( items.count() > 0 ) { {
setFocusPolicy( Qt::StrongFocus ); setFocusPolicy( items.count() > 0 ? Qt::StrongFocus : Qt::NoFocus );
} else { }
setFocusPolicy( Qt::NoFocus ); );
}
});
setFocusedIndex( -1 ); setFocusedIndex( -1 );
} }
QskRadioBox::QskRadioBox( const QStringList& list, QQuickItem* parent ) : QskRadioBox::QskRadioBox( const QStringList& list, QQuickItem* parent )
QskRadioBox( parent ) { : QskRadioBox( parent )
{
setItems( list ); setItems( list );
} }
QskRadioBox::QskRadioBox( const QStringList& items, QskRadioBox::QskRadioBox( const QStringList& items,
int selectedIndex, QQuickItem* parent ) : int selectedIndex, QQuickItem* parent )
QskRadioBox( items, parent ) { : QskRadioBox( items, parent )
{
if( selectedIndex >= 0 && selectedIndex < items.count() ) if( selectedIndex >= 0 && selectedIndex < items.count() )
{ m_data->selectedIndex = selectedIndex;
m_data->selectedIndex = selectedIndex;
}
} }
QRectF QskRadioBox::focusIndicatorRect() const { QskRadioBox::~QskRadioBox()
if( m_data->focusedIndex > -1) { {
auto textRect = effectiveSkinlet()->sampleRect( this, }
contentsRect(), QskRadioBox::Text, m_data->focusedIndex );
auto buttonRect = effectiveSkinlet()->sampleRect( this, QRectF QskRadioBox::focusIndicatorRect() const
contentsRect(), QskRadioBox::Button, m_data->focusedIndex ); {
if( m_data->focusedIndex > -1)
{
auto skinlet = effectiveSkinlet();
if( textRect == QRectF() ) { auto textRect = skinlet->sampleRect( this,
return buttonRect; contentsRect(), QskRadioBox::Text, m_data->focusedIndex );
}
auto result = QRectF( auto buttonRect = skinlet->sampleRect( this,
qMin( textRect.x(), buttonRect.x() ), contentsRect(), QskRadioBox::Button, m_data->focusedIndex );
if( textRect == QRectF() )
return buttonRect;
auto result = QRectF(
qMin( textRect.x(), buttonRect.x() ),
qMin( textRect.y(), buttonRect.y() ), qMin( textRect.y(), buttonRect.y() ),
buttonRect.width() + textRect.width(), buttonRect.width() + textRect.width(),
qMax( buttonRect.height(), textRect.height() )); qMax( buttonRect.height(), textRect.height() ) );
if( layoutMirroring() ) { if( layoutMirroring() )
result.setWidth( {
result.width() + marginHint( Text ).right() result.setWidth(
+ marginHint( Button ).left() ); result.width() + marginHint( Text ).right()
} else { + marginHint( Button ).left() );
result.setWidth( }
result.width() + marginHint( Text ).left() else
+ marginHint( Button ).right() ); {
} result.setWidth(
result.width() + marginHint( Text ).left()
+ marginHint( Button ).right() );
}
return result; return result;
} }
return QRectF(); return QRectF();
} }
int QskRadioBox::selectedIndex() const { int QskRadioBox::selectedIndex() const
{
return m_data->selectedIndex; return m_data->selectedIndex;
} }
const QStringList& QskRadioBox::items() const { const QStringList& QskRadioBox::items() const
{
return m_data->items; return m_data->items;
} }
int QskRadioBox::pressedIndex() const { int QskRadioBox::pressedIndex() const
{
return m_data->pressedIndex; return m_data->pressedIndex;
} }
void QskRadioBox::setSelectedIndex( int index ) { void QskRadioBox::setSelectedIndex( int index )
if( index == m_data->selectedIndex {
|| index >= m_data->items.count() ) { if( index == m_data->selectedIndex || index >= m_data->items.count() )
return; return;
}
if( index < 0 ) { if( index < 0 )
m_data->selectedIndex = -1; m_data->selectedIndex = -1;
} else { else
m_data->selectedIndex = index; m_data->selectedIndex = index;
}
selectedIndexChanged( m_data->selectedIndex ); selectedIndexChanged( m_data->selectedIndex );
} }
void QskRadioBox::setItems( const QStringList& items ){ void QskRadioBox::setItems( const QStringList& items )
if( m_data->items == items ) { {
return; if( m_data->items == items )
} return;
m_data->items = items; m_data->items = items;
itemsChanged( items ); itemsChanged( items );
setSelectedIndex( m_data->selectedIndex ); setSelectedIndex( m_data->selectedIndex );
if( m_data->focusedIndex > items.size() ) { if( m_data->focusedIndex > items.size() )
setFocusedIndex( 0 ); setFocusedIndex( 0 );
}
} }
void QskRadioBox::keyPressEvent( QKeyEvent* event ) void QskRadioBox::keyPressEvent( QKeyEvent* event )
{ {
switch ( event->key() ) switch ( event->key() )
{ {
case Qt::Key_Up: case Qt::Key_Up:
case Qt::Key_Left: case Qt::Key_Left:
m_data->selectedIndex = qMax( m_data->selectedIndex - 1, 0 ); {
setFocusedIndex( m_data->selectedIndex ); m_data->selectedIndex = qMax( m_data->selectedIndex - 1, 0 );
event->setAccepted( true ); setFocusedIndex( m_data->selectedIndex );
update(); update();
return;
case Qt::Key_Down: return;
case Qt::Key_Right: }
m_data->selectedIndex = qMin( m_data->selectedIndex + 1, case Qt::Key_Down:
items().size() - 1 ); case Qt::Key_Right:
setFocusedIndex( m_data->selectedIndex ); {
event->setAccepted( true ); m_data->selectedIndex = qMin( m_data->selectedIndex + 1,
update(); items().size() - 1 );
return; setFocusedIndex( m_data->selectedIndex );
case Qt::Key_Select: update();
case Qt::Key_Return:
case Qt::Key_Space: return;
m_data->selectedIndex = m_data->focusedIndex; }
event->setAccepted( true ); case Qt::Key_Select:
update(); case Qt::Key_Return:
return; case Qt::Key_Space:
{
m_data->selectedIndex = m_data->focusedIndex;
update();
return;
}
} }
auto currentTabIndex = m_data->focusedIndex; const auto currentTabIndex = m_data->focusedIndex;
auto nextTabIndex = currentTabIndex + qskFocusChainIncrement( event ); const auto nextTabIndex = currentTabIndex + qskFocusChainIncrement( event );
if( nextTabIndex >= items().size()
|| nextTabIndex < 0 ) { if( nextTabIndex >= items().size() || nextTabIndex < 0 )
Inherited::keyPressEvent( event ); {
setFocusedIndex( -1 ); Inherited::keyPressEvent( event );
update(); setFocusedIndex( -1 );
} else { }
event->setAccepted( true ); else
{
setFocusedIndex( ( float ) nextTabIndex ); setFocusedIndex( ( float ) nextTabIndex );
const auto aspect = Ripple | QskAspect::Metric | QskAspect::Position; const auto aspect = Ripple | QskAspect::Metric | QskAspect::Position;
auto hint = animationHint(aspect | skinStates()); const auto hint = animationHint( aspect | skinStates() );
if( hint.isValid()) {
startTransition( aspect, hint,
( float ) currentTabIndex, ( float ) nextTabIndex );
}
update();
if( hint.isValid() )
{
startTransition( aspect, hint,
( float ) currentTabIndex, ( float ) nextTabIndex );
}
} }
update();
} }
void QskRadioBox::keyReleaseEvent( QKeyEvent* e ) void QskRadioBox::keyReleaseEvent( QKeyEvent* )
{ {
e->setAccepted( true );
} }
void QskRadioBox::mousePressEvent( QMouseEvent* e ) void QskRadioBox::mousePressEvent( QMouseEvent* e )
@ -192,52 +216,54 @@ void QskRadioBox::mousePressEvent( QMouseEvent* e )
m_data->selectedIndex = -1; m_data->selectedIndex = -1;
setFocusedIndex( indexAtPosition ); setFocusedIndex( indexAtPosition );
e->setAccepted( true );
update(); update();
} }
void QskRadioBox::mouseReleaseEvent( QMouseEvent* e ) void QskRadioBox::mouseReleaseEvent( QMouseEvent* e )
{ {
auto index = indexAt( e->localPos() ); const auto index = indexAt( e->localPos() );
if( index == m_data->pressedIndex ) { if( index == m_data->pressedIndex )
setSelectedIndex( index ); setSelectedIndex( index );
}
e->setAccepted( true );
update(); update();
} }
void QskRadioBox::focusInEvent( QFocusEvent* e ) { void QskRadioBox::focusInEvent( QFocusEvent* e )
if( e->reason() == Qt::TabFocusReason ) { {
setFocusedIndex(0 ); if( e->reason() == Qt::TabFocusReason )
} else if( e->reason() == Qt::BacktabFocusReason ) { {
setFocusedIndex( items().size() - 1 ); setFocusedIndex( 0 );
}
else if( e->reason() == Qt::BacktabFocusReason )
{
setFocusedIndex( items().size() - 1 );
} }
update(); update();
Inherited::focusInEvent( e ); Inherited::focusInEvent( e );
} }
void QskRadioBox::focusOutEvent( QFocusEvent* e ) { void QskRadioBox::focusOutEvent( QFocusEvent* e )
{
setFocusedIndex( -1 ); setFocusedIndex( -1 );
update(); update();
Inherited::focusOutEvent( e ); Inherited::focusOutEvent( e );
} }
int QskRadioBox::indexAt( const QPointF& target ) const { int QskRadioBox::indexAt( const QPointF& target ) const
auto itemHeight = contentsRect().height() / items().size(); {
const auto itemHeight = contentsRect().height() / items().size();
auto index = target.y() / itemHeight; auto index = target.y() / itemHeight;
if( index < 0 || index >= items().size() ) { if( index < 0 || index >= items().size() )
return -1; return -1;
}
return index; return index;
} }
void QskRadioBox::setFocusedIndex( int index ) { void QskRadioBox::setFocusedIndex( int index )
{
m_data->focusedIndex = index; m_data->focusedIndex = index;
setPositionHint( Ripple, index ); setPositionHint( Ripple, index );
focusIndicatorRectChanged(); focusIndicatorRectChanged();

View File

@ -1,23 +1,23 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_RADIO_BOX_H #ifndef QSK_RADIO_BOX_H
#define QSK_RADIO_BOX_H #define QSK_RADIO_BOX_H
#include "QskControl.h" #include "QskControl.h"
#include <qstringlist.h>
#include <QStringList>
class QSK_EXPORT QskRadioBox : public QskControl class QSK_EXPORT QskRadioBox : public QskControl
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY( int selectedIndex Q_PROPERTY( int selectedIndex READ selectedIndex
READ selectedIndex WRITE setSelectedIndex NOTIFY selectedIndexChanged FINAL )
WRITE setSelectedIndex
NOTIFY selectedIndexChanged FINAL )
Q_PROPERTY( QStringList items Q_PROPERTY( QStringList items READ items
READ items WRITE setItems NOTIFY itemsChanged FINAL )
WRITE setItems
NOTIFY itemsChanged FINAL )
using Inherited = QskControl; using Inherited = QskControl;
@ -29,9 +29,12 @@ class QSK_EXPORT QskRadioBox : public QskControl
QskRadioBox( const QStringList&, QQuickItem* parent = nullptr ); QskRadioBox( const QStringList&, QQuickItem* parent = nullptr );
QskRadioBox( const QStringList&, int, QQuickItem* parent = nullptr ); QskRadioBox( const QStringList&, int, QQuickItem* parent = nullptr );
~QskRadioBox() override;
QRectF focusIndicatorRect() const override; QRectF focusIndicatorRect() const override;
const QStringList& items() const; const QStringList& items() const;
int selectedIndex() const; int selectedIndex() const;
int pressedIndex() const; int pressedIndex() const;
@ -57,6 +60,7 @@ class QSK_EXPORT QskRadioBox : public QskControl
private: private:
void setFocusedIndex( int index ); void setFocusedIndex( int index );
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };

View File

@ -1,3 +1,8 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskRadioBoxSkinlet.h" #include "QskRadioBoxSkinlet.h"
#include "QskAspect.h" #include "QskAspect.h"
@ -10,8 +15,42 @@
#include "QskFunctions.h" #include "QskFunctions.h"
#include "QskSkin.h" #include "QskSkin.h"
namespace { #include <qfontmetrics.h>
using Q = QskRadioBox;
namespace
{
QskAspect::States statesForIndex( const QskRadioBox* radioBox, int index )
{
using Q = QskRadioBox;
auto states = radioBox->skinStates();
if( radioBox->selectedIndex() == index )
states |= Q::Selected;
if( radioBox->pressedIndex() == index )
states |= Q::Pressed;
if( radioBox->positionHint( Q::Ripple ) == index )
states |= Q::Focused;
return states;
}
qreal lineHeight( const QskRadioBox* radioBox )
{
using Q = QskRadioBox;
auto strutHight = qMax( radioBox->strutSizeHint( Q::Button ).height(),
radioBox->strutSizeHint( Q::Text ).height() );
const auto textMargins = radioBox->marginHint( Q::Text );
auto fontHeight = radioBox->effectiveFontHeight( Q::Text );
fontHeight += textMargins.top() + textMargins.bottom();
return qMax( strutHight, fontHeight );
}
} }
QskRadioBoxSkinlet::QskRadioBoxSkinlet( QskSkin* ) QskRadioBoxSkinlet::QskRadioBoxSkinlet( QskSkin* )
@ -23,32 +62,13 @@ QskRadioBoxSkinlet::~QskRadioBoxSkinlet()
{ {
} }
QskAspect::States statesForIndex( const QskRadioBox* radio, int index ) {
auto states = radio->skinStates();
if( radio->selectedIndex() == index ) {
states |= Q::Selected;
}
if( radio->pressedIndex() == index ) {
states |= Q::Pressed;
}
if( radio->positionHint( Q::Ripple ) == index ) {
states |= Q::Focused;
}
return states;
}
QRectF QskRadioBoxSkinlet::subControlRect( const QskSkinnable* skinnable, QRectF QskRadioBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
const QRectF& contentsRect, QskAspect::Subcontrol subcontrol ) const const QRectF& contentsRect, QskAspect::Subcontrol subcontrol ) const
{ {
auto radio = static_cast< const QskRadioBox* >( skinnable ); auto radioBox = static_cast< const QskRadioBox* >( skinnable );
if( subcontrol == Q::Ripple ) { if( subcontrol == QskRadioBox::Ripple )
return rippleRect( radio, contentsRect ); return rippleRect( radioBox, contentsRect );
}
return contentsRect; return contentsRect;
} }
@ -56,7 +76,9 @@ QRectF QskRadioBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
QSizeF QskRadioBoxSkinlet::sizeHint( const QskSkinnable* skinnable, QSizeF QskRadioBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint, const QSizeF& ) const Qt::SizeHint, const QSizeF& ) const
{ {
auto radio = static_cast< const QskRadioBox* >( skinnable ); using Q = QskRadioBox;
auto radioBox = static_cast< const QskRadioBox* >( skinnable );
const auto font = skinnable->effectiveFont( Q::Text ); const auto font = skinnable->effectiveFont( Q::Text );
const auto textMargins = skinnable->marginHint( Q::Text ); const auto textMargins = skinnable->marginHint( Q::Text );
@ -64,232 +86,245 @@ QSizeF QskRadioBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
const auto symbolMargins = skinnable->marginHint( Q::Symbol ); const auto symbolMargins = skinnable->marginHint( Q::Symbol );
qreal maxTextWidth = 0; qreal maxTextWidth = 0;
for( auto& item : radio->items() ) { for( const auto& item : radioBox->items() )
maxTextWidth = std::max( maxTextWidth, qskHorizontalAdvance( font, item ) ); maxTextWidth = std::max( maxTextWidth, qskHorizontalAdvance( font, item ) );
}
auto buttonWidth = radio->strutSizeHint( Q::Button ).width(); auto buttonWidth = radioBox->strutSizeHint( Q::Button ).width();
auto symbolWidth = radio->strutSizeHint( Q::Symbol ).width(); auto symbolWidth = radioBox->strutSizeHint( Q::Symbol ).width();
maxTextWidth += textMargins.left() + textMargins.right(); maxTextWidth += textMargins.left() + textMargins.right();
buttonWidth += buttonMargins.left() + buttonMargins.right(); buttonWidth += buttonMargins.left() + buttonMargins.right();
symbolWidth += symbolMargins.left() + symbolMargins.right(); symbolWidth += symbolMargins.left() + symbolMargins.right();
auto spacing = radio->spacingHint( Q::Panel ); auto spacing = radioBox->spacingHint( Q::Panel );
return QSizeF( maxTextWidth + qMax( buttonWidth, symbolWidth ), return QSizeF( maxTextWidth + qMax( buttonWidth, symbolWidth ),
( lineHeight( radio ) + spacing ) * radio->items().size() - spacing ); ( lineHeight( radioBox ) + spacing ) * radioBox->items().size() - spacing );
} }
QSGNode* QskRadioBoxSkinlet::updateSubNode( const QskSkinnable* skinnable, QSGNode* QskRadioBoxSkinlet::updateSubNode( const QskSkinnable* skinnable,
quint8 nodeRole, QSGNode* node ) const quint8 nodeRole, QSGNode* node ) const
{ {
auto radio = static_cast< const QskRadioBox* >( skinnable ); using Q = QskRadioBox;
switch( nodeRole ) switch( nodeRole )
{ {
case PanelRole: case PanelRole:
return updateBoxNode( skinnable, node, Q::Panel ); return updateBoxNode( skinnable, node, Q::Panel );
case ButtonRole: case ButtonRole:
return updateSeriesNode( radio, Q::Button, node ); return updateSeriesNode( skinnable, Q::Button, node );
case SymbolRole: case SymbolRole:
return updateSeriesNode( radio, Q::Symbol, node ); return updateSeriesNode( skinnable, Q::Symbol, node );
case TextRole: case TextRole:
return updateSeriesNode( radio, Q::Text, node ); return updateSeriesNode( skinnable, Q::Text, node );
case RippleRole: case RippleRole:
{ {
QskSkinStateChanger changer( radio ); auto radioBox = static_cast< const QskRadioBox* >( skinnable );
auto ripplePosition = radio->positionHint( Q::Ripple );
changer.setStates( statesForIndex( radio, ripplePosition ) );
return updateBoxNode( radio, node, Q::Ripple ); QskSkinStateChanger changer( radioBox );
} auto ripplePosition = radioBox->positionHint( Q::Ripple );
changer.setStates( statesForIndex( radioBox, ripplePosition ) );
return updateBoxNode( radioBox, node, Q::Ripple );
}
}; };
return Inherited::updateSubNode( skinnable, nodeRole, node ); return Inherited::updateSubNode( skinnable, nodeRole, node );
} }
qreal QskRadioBoxSkinlet::lineHeight(const QskRadioBox* target) const { int QskRadioBoxSkinlet::sampleCount(
auto strutHight = qMax( target->strutSizeHint( Q::Button ).height(), const QskSkinnable* skinnable, QskAspect::Subcontrol ) const
target->strutSizeHint( Q::Text ).height() ); {
const auto textMargins = target->marginHint( Q::Text ); const auto radioBox = static_cast< const QskRadioBox* >( skinnable );
auto fontHeight = target->effectiveFontHeight( Q::Text ); return radioBox->items().count();
fontHeight += textMargins.top() + textMargins.bottom();
return qMax( strutHight, fontHeight );
} }
int QskRadioBoxSkinlet::sampleCount( const QskSkinnable* skinnable, QskAspect::Subcontrol ) const { QSizeF QskRadioBoxSkinlet::buttonSymbolSize( const QskRadioBox* radioBox ) const
const auto radio = static_cast< const QskRadioBox* >( skinnable ); {
return radio->items().count(); using Q = QskRadioBox;
}
QSizeF QskRadioBoxSkinlet::buttonSymbolSize( const QskRadioBox* radio ) const { auto buttonStrut = radioBox->strutSizeHint( Q::Button );
auto buttonStrut = radio->strutSizeHint( Q::Button ); auto symbolStrut = radioBox->strutSizeHint( Q::Symbol );
auto symbolStrut = radio->strutSizeHint( Q::Symbol );
buttonStrut = buttonStrut.grownBy( radio->marginHint( Q::Button ) ); buttonStrut = buttonStrut.grownBy( radioBox->marginHint( Q::Button ) );
symbolStrut = symbolStrut.grownBy( radio->marginHint( Q::Symbol ) ); symbolStrut = symbolStrut.grownBy( radioBox->marginHint( Q::Symbol ) );
return QSizeF( return QSizeF( qMax( buttonStrut.width(), symbolStrut.width() ),
qMax( buttonStrut.width(), symbolStrut.width() ),
qMax( buttonStrut.height(), symbolStrut.height() ) ); qMax( buttonStrut.height(), symbolStrut.height() ) );
} }
QRectF QskRadioBoxSkinlet::rippleRect( const QskRadioBox* radio, const QRectF& rect ) const { QRectF QskRadioBoxSkinlet::rippleRect(
auto ripplePosition = radio->positionHint( Q::Ripple ); const QskRadioBox* radioBox, const QRectF& rect ) const
{
using Q = QskRadioBox;
if( ripplePosition < 0 ) { auto ripplePosition = radioBox->positionHint( Q::Ripple );
return QRectF();
}
auto button = buttonRect( radio, Q::Button, rect, ripplePosition ); if( ripplePosition < 0 )
auto rippleSize = radio->strutSizeHint( Q::Ripple ); return QRectF();
button.moveLeft( button.x() - ( rippleSize.width() - button.width() ) / 2 );
button.moveTop( button.y() - ( rippleSize.height() - button.height() ) / 2 ); auto rippleSize = radioBox->strutSizeHint( Q::Ripple );
button.setSize( rippleSize );
return button; auto r = buttonRect( radioBox, Q::Button, rect, ripplePosition );
r.moveLeft( r.x() - ( rippleSize.width() - r.width() ) / 2 );
r.moveTop( r.y() - ( rippleSize.height() - r.height() ) / 2 );
r.setSize( rippleSize );
return r;
} }
QRectF QskRadioBoxSkinlet::buttonRect( const QskRadioBox* radio, QRectF QskRadioBoxSkinlet::buttonRect( const QskRadioBox* radioBox,
const QskAspect::Subcontrol target, const QRectF& rect, double index ) const { const QskAspect::Subcontrol target, const QRectF& rect, double index ) const
if( index < 0 ) { {
return QRectF(); using Q = QskRadioBox;
}
if( index < 0 )
return QRectF();
auto result = rect; auto result = rect;
result.setSize( radio->strutSizeHint( target ) ); result.setSize( radioBox->strutSizeHint( target ) );
auto spacing = radio->spacingHint( Q::Panel ); auto spacing = radioBox->spacingHint( Q::Panel );
result.moveTop( ( lineHeight( radio ) + spacing ) * index ); result.moveTop( ( lineHeight( radioBox ) + spacing ) * index );
auto margins = radio->marginHint( target ); auto margins = radioBox->marginHint( target );
auto withMargins = result.size().grownBy( margins ); auto withMargins = result.size().grownBy( margins );
auto maxSize = buttonSymbolSize( radio ); auto maxSize = buttonSymbolSize( radioBox );
auto alignment = radio->alignmentHint( target ); auto alignment = radioBox->alignmentHint( target );
// Vertical positioning // Vertical positioning
auto alignHeight = maxSize.height() - withMargins.height(); const auto alignHeight = maxSize.height() - withMargins.height();
if( alignment.testFlag( Qt::AlignVCenter ) ) { if( alignment.testFlag( Qt::AlignVCenter ) )
result.moveTop( result.top() + alignHeight / 2 ); result.moveTop( result.top() + alignHeight / 2 );
} else if( alignment.testFlag( Qt::AlignBottom ) ) { else if( alignment.testFlag( Qt::AlignBottom ) )
result.moveTop( result.top() + alignHeight ); result.moveTop( result.top() + alignHeight );
}
result.moveTop( result.top() + margins.top() ); result.moveTop( result.top() + margins.top() );
// Horizontal positioning // Horizontal positioning
auto alignWidth = 0; auto alignWidth = 0;
if( alignment.testFlag( Qt::AlignHCenter ) ) { if( alignment.testFlag( Qt::AlignHCenter ) )
alignWidth = ( maxSize.width() - withMargins.width() ) / 2; alignWidth = ( maxSize.width() - withMargins.width() ) / 2;
} else if ( alignment.testFlag( Qt::AlignRight )) { else if ( alignment.testFlag( Qt::AlignRight ) )
alignWidth = maxSize.width() - withMargins.width(); alignWidth = maxSize.width() - withMargins.width();
}
if( radio->layoutMirroring() ) { if( radioBox->layoutMirroring() )
result.moveRight( rect.width() - ( alignWidth + margins.right() ) ); result.moveRight( rect.width() - ( alignWidth + margins.right() ) );
} else { else
result.moveLeft( margins.left() + alignWidth ); result.moveLeft( margins.left() + alignWidth );
}
return result; return result;
} }
QRectF QskRadioBoxSkinlet::textRect( const QskRadioBox* radio, QRectF QskRadioBoxSkinlet::textRect( const QskRadioBox* radioBox,
const QRectF& rect, int index ) const { const QRectF& rect, int index ) const
auto text = radio->items()[ index ]; {
using Q = QskRadioBox;
if(text.isEmpty()) { const auto text = radioBox->items()[ index ];
return QRectF(); if( text.isEmpty() )
} return QRectF();
QRectF result = rect; QRectF result = rect;
auto spacing = radio->spacingHint( Q::Panel ); auto spacing = radioBox->spacingHint( Q::Panel );
auto lh = lineHeight( radio ); auto lh = lineHeight( radioBox );
const auto textMargins = radio->marginHint( Q::Text ); const auto textMargins = radioBox->marginHint( Q::Text );
const auto font = radio->effectiveFont( Q::Text ); const auto font = radioBox->effectiveFont( Q::Text );
result.moveTop( index * ( lh + spacing ) result.moveTop( index * ( lh + spacing )
+ lh - radio->effectiveFontHeight( Q::Text ) + lh - QFontMetricsF( font ).height() + textMargins.top() );
+ textMargins.top());
result.setHeight( lh ); result.setHeight( lh );
result.setWidth( qskHorizontalAdvance( font, text ) ); result.setWidth( qskHorizontalAdvance( font, text ) );
auto button = buttonRect( radio, Q::Button, rect, index ); const auto button = buttonRect( radioBox, Q::Button, rect, index );
auto buttonsMargins = radio->marginHint( Q::Button ); const auto buttonsMargins = radioBox->marginHint( Q::Button );
auto buttonWidth = button.marginsAdded( buttonsMargins ).width(); const auto buttonWidth = button.marginsAdded( buttonsMargins ).width();
if( radio->layoutMirroring() ) { if( radioBox->layoutMirroring() )
result.moveLeft( rect.width() - textMargins.right() {
- result.width() - buttonWidth); result.moveLeft( rect.width() - textMargins.right()
} else { - result.width() - buttonWidth);
result.moveLeft( buttonWidth + textMargins.left() ); }
else
{
result.moveLeft( buttonWidth + textMargins.left() );
} }
return result; return result;
} }
QRectF QskRadioBoxSkinlet::sampleRect( const QskSkinnable* skinnable, QRectF QskRadioBoxSkinlet::sampleRect( const QskSkinnable* skinnable,
const QRectF& rect, QskAspect::Subcontrol subcontrol, int index ) const { const QRectF& rect, QskAspect::Subcontrol subcontrol, int index ) const
{
using Q = QskRadioBox;
const auto radio = static_cast< const QskRadioBox* >( skinnable ); auto radioBox = static_cast< const QskRadioBox* >( skinnable );
if( subcontrol == Q::Text ) { if( subcontrol == Q::Text )
return textRect( radio, rect, index ); return textRect( radioBox, rect, index );
}
return buttonRect( radio, subcontrol, rect, index); return buttonRect( radioBox, subcontrol, rect, index);
} }
QskAspect::States QskRadioBoxSkinlet::sampleStates( const QskSkinnable* skinnable, QskAspect::States QskRadioBoxSkinlet::sampleStates( const QskSkinnable* skinnable,
QskAspect::Subcontrol subControl, int index ) const { QskAspect::Subcontrol subControl, int index ) const
{
auto radioBox = static_cast< const QskRadioBox* >( skinnable );
auto states = Inherited::sampleStates( skinnable, subControl, index );
auto radio = static_cast< const QskRadioBox* >( skinnable ); return states | statesForIndex( radioBox, index );
auto states = Inherited::sampleStates( skinnable, subControl, index );
return states | statesForIndex( radio, index );
} }
QSGNode* QskRadioBoxSkinlet::updateSampleNode( const QskSkinnable* skinnable, QSGNode* QskRadioBoxSkinlet::updateSampleNode( const QskSkinnable* skinnable,
QskAspect::Subcontrol subcontrol, int index, QSGNode* node ) const { QskAspect::Subcontrol subcontrol, int index, QSGNode* node ) const
{
using Q = QskRadioBox;
auto radio = static_cast< const QskRadioBox* >( skinnable ); auto radioBox = static_cast< const QskRadioBox* >( skinnable );
auto rect = sampleRect( skinnable, radio->contentsRect(), auto rect = sampleRect( skinnable, radioBox->contentsRect(), subcontrol, index );
subcontrol, index );
if( subcontrol == Q::Text ) { if( subcontrol == Q::Text )
return QskSkinlet::updateTextNode( radio, node, rect, Qt::AlignLeft, {
radio->items()[ index ], subcontrol ); return QskSkinlet::updateTextNode( radioBox, node, rect, Qt::AlignLeft,
} else if ( subcontrol == Q::Button ) { radioBox->items()[ index ], subcontrol );
return QskSkinlet::updateBoxNode( radio, node, rect, subcontrol ); }
} else if( subcontrol == Q::Symbol ) { else if ( subcontrol == Q::Button )
{
return QskSkinlet::updateBoxNode( radioBox, node, rect, subcontrol );
}
else if( subcontrol == Q::Symbol )
{
auto symbol = QskStandardSymbol::NoSymbol; auto symbol = QskStandardSymbol::NoSymbol;
auto color = radio->color( subcontrol ).rgb(); auto color = radioBox->color( subcontrol ).rgb();
if( radio->selectedIndex() == index ) { if( radioBox->selectedIndex() == index )
symbol = QskStandardSymbol::Bullet; {
color = radio->color( subcontrol | Q::Selected ).rgb(); symbol = QskStandardSymbol::Bullet;
} color = radioBox->color( subcontrol | Q::Selected ).rgb();
}
auto graphic = radio->effectiveSkin()->symbol( symbol ); auto graphic = radioBox->effectiveSkin()->symbol( symbol );
/* /*
Our default skins do not have the concept of colorRoles Our default skins do not have the concept of colorRoles
implemented. Until then we do the recoloring manually here implemented. Until then we do the recoloring manually here
*/ */
QskColorFilter filter; QskColorFilter filter;
filter.addColorSubstitution( Qt::black, color ); filter.addColorSubstitution( Qt::black, color );
auto colorSub = radio->color( subcontrol | statesForIndex( radio, index ) );
filter.addColorSubstitution( Qt::black, colorSub.rgb() );
QskGraphic::fromGraphic( graphic, filter ); auto colorSub = radioBox->color( subcontrol | statesForIndex( radioBox, index ) );
filter.addColorSubstitution( Qt::black, colorSub.rgb() );
return updateGraphicNode( radio, node, graphic, filter, rect ); QskGraphic::fromGraphic( graphic, filter );
return updateGraphicNode( radioBox, node, graphic, filter, rect );
} }
return node; return node;

View File

@ -1,3 +1,8 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_RADIO_BOX_SKINLET_H #ifndef QSK_RADIO_BOX_SKINLET_H
#define QSK_RADIO_BOX_SKINLET_H #define QSK_RADIO_BOX_SKINLET_H
@ -37,13 +42,6 @@ class QSK_EXPORT QskRadioBoxSkinlet : public QskSkinlet
QRectF sampleRect( const QskSkinnable*, QRectF sampleRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol, int index ) const override; 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::States sampleStates( const QskSkinnable*,
QskAspect::Subcontrol, int index ) const override; QskAspect::Subcontrol, int index ) const override;
@ -55,7 +53,13 @@ class QSK_EXPORT QskRadioBoxSkinlet : public QskSkinlet
QskAspect::Subcontrol, int index, QSGNode* ) const override; QskAspect::Subcontrol, int index, QSGNode* ) const override;
private: private:
qreal lineHeight( const QskRadioBox* target ) const; QRectF textRect( const QskRadioBox*, const QRectF&, int ) const;
QSizeF buttonSymbolSize( const QskRadioBox* ) const;
QRectF buttonRect( const QskRadioBox*,
const QskAspect::Subcontrol, const QRectF&, double ) const;
QRectF rippleRect( const QskRadioBox*, const QRectF& ) const;
}; };
#endif #endif