QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskPushButtonSkinlet.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskPushButtonSkinlet.h"
7#include "QskPushButton.h"
8#include "QskTextOptions.h"
9
10#include "QskAnimationHint.h"
11#include "QskGraphic.h"
12#include "QskSubcontrolLayoutEngine.h"
13#include "QskSGNode.h"
14
15static inline Qt::Orientation qskOrientation( const QskPushButton* button )
16{
17 // For the moment we only handle the orientation TODO ...
18
19 const auto direction = button->flagHint(
20 QskPushButton::Panel | QskAspect::Direction, Qsk::LeftToRight );
21
22 if ( direction == Qsk::LeftToRight || direction == Qsk::RightToLeft )
23 return Qt::Horizontal;
24 else
25 return Qt::Vertical;
26}
27
28namespace
29{
30 class LayoutEngine : public QskSubcontrolLayoutEngine
31 {
32 public:
33 LayoutEngine( const QskPushButton* button )
34 : QskSubcontrolLayoutEngine( qskOrientation( button ) )
35 {
36 setSpacing( button->spacingHint( QskPushButton::Panel ) );
37
38 setGraphicTextElements( button,
39 QskPushButton::Text, button->text(),
40 QskPushButton::Icon, button->icon().defaultSize() );
41
42 const auto alignment = button->alignmentHint(
43 QskPushButton::Panel, Qt::AlignCenter );
44
45 setFixedContent( QskPushButton::Text, Qt::Horizontal, alignment );
46 }
47 };
48}
49
50QskPushButtonSkinlet::QskPushButtonSkinlet( QskSkin* skin )
51 : Inherited( skin )
52{
53 setNodeRoles( { PanelRole, SplashRole, IconRole, TextRole } );
54}
55
56QskPushButtonSkinlet::~QskPushButtonSkinlet() = default;
57
58QRectF QskPushButtonSkinlet::subControlRect( const QskSkinnable* skinnable,
59 const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
60{
61 using Q = QskPushButton;
62
63 const auto button = static_cast< const QskPushButton* >( skinnable );
64
65 if ( subControl == Q::Panel )
66 return contentsRect;
67
68 if ( subControl == Q::Splash )
69 return splashRect( button, contentsRect );
70
71 if ( ( subControl == Q::Text ) || ( subControl == Q::Icon ) )
72 {
73 const auto r = button->subControlContentsRect( contentsRect, Q::Panel );
74
75 LayoutEngine layoutEngine( button );
76 layoutEngine.setGeometries( r );
77
78 return layoutEngine.subControlRect( subControl );
79 }
80
81 return Inherited::subControlRect( skinnable, contentsRect, subControl );
82}
83
84QSGNode* QskPushButtonSkinlet::updateSubNode(
85 const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
86{
87 using Q = QskPushButton;
88
89 const auto button = static_cast< const QskPushButton* >( skinnable );
90
91 switch ( nodeRole )
92 {
93 case PanelRole:
94 return updateBoxNode( button, node, Q::Panel );
95
96 case SplashRole:
97 return updateSplashNode( button, node );
98
99 case TextRole:
100 return updateTextNode( button, node );
101
102 case IconRole:
103 return updateGraphicNode( button, node, button->icon(), Q::Icon );
104 }
105
106 return Inherited::updateSubNode( skinnable, nodeRole, node );
107}
108
109QRectF QskPushButtonSkinlet::splashRect(
110 const QskPushButton* button, const QRectF& contentsRect ) const
111{
112 using Q = QskPushButton;
113
114 QRectF rect;
115
116 const auto ratio = button->metric( Q::Splash | QskAspect::Size );
117 if ( ratio > 0.0 )
118 {
119 rect = subControlRect( button, contentsRect, Q::Panel );
120
121 const auto pos = button->positionHint( Q::Splash );
122 const qreal w = 2.0 * rect.width() * ratio;
123
124 rect.setX( pos - 0.5 * w );
125 rect.setWidth( w );
126 }
127
128 return rect;
129}
130
131QSGNode* QskPushButtonSkinlet::updateTextNode(
132 const QskPushButton* button, QSGNode* node ) const
133{
134 using Q = QskPushButton;
135
136 const auto rect = button->subControlRect( Q::Text ).toAlignedRect();
137
138 const auto textHeight = button->effectiveFontHeight( Q::Text );
139 if ( !button->clip() && ( rect.height() < textHeight ) )
140 return nullptr;
141
142 const auto alignment = button->alignmentHint( Q::Text, Qt::AlignCenter );
143
144 return QskSkinlet::updateTextNode( button, node, rect,
145 alignment, button->text(), Q::Text );
146}
147
148QSGNode* QskPushButtonSkinlet::updateSplashNode(
149 const QskPushButton* button, QSGNode* node ) const
150{
151 using Q = QskPushButton;
152
153 const auto splashRect = button->subControlRect( Q::Splash );
154 if ( splashRect.isEmpty() )
155 return nullptr;
156
157 auto clipNode = updateBoxClipNode( button, node,
158 button->subControlRect( Q::Panel ), Q::Panel );
159
160 if ( clipNode )
161 {
162 auto boxNode = QskSGNode::findChildNode( clipNode, SplashRole );
163 boxNode = updateBoxNode( button, boxNode, splashRect, Q::Splash );
164
165 if ( boxNode == nullptr )
166 return nullptr;
167
168 QskSGNode::setNodeRole( boxNode, SplashRole );
169 if ( boxNode->parent() != clipNode )
170 clipNode->appendChildNode( boxNode );
171 }
172
173 return clipNode;
174}
175
176QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable,
177 Qt::SizeHint which, const QSizeF& ) const
178{
179 using Q = QskPushButton;
180
181 if ( which != Qt::PreferredSize )
182 return QSizeF();
183
184 const auto button = static_cast< const QskPushButton* >( skinnable );
185
186 LayoutEngine layoutEngine( button );
187
188 auto size = layoutEngine.sizeHint( which, QSizeF() );
189 size = button->outerBoxSize( Q::Panel, size );
190 size = size.expandedTo( button->strutSizeHint( Q::Panel ) );
191 size = size.grownBy( skinnable->marginHint( Q::Panel ) );
192
193 return size;
194}
195
196#include "moc_QskPushButtonSkinlet.cpp"
Subcontrol
For use within the rendering or lay-outing of a specific QskSkinnable.
Definition QskAspect.h:104
QRectF subControlRect(QskAspect::Subcontrol) const
QRectF subControlContentsRect(QskAspect::Subcontrol) const
qreal spacingHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a spacing hint.
QMarginsF marginHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a margin hint.
QSizeF strutSizeHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a strut size hint.
QSizeF outerBoxSize(QskAspect, const QSizeF &innerBoxSize) const
Calculate the size, when being expanded by paddings, indentations.
T flagHint(QskAspect, T=T()) const
Retrieves a flag hint.
qreal metric(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a metric hint.
Qt::Alignment alignmentHint(QskAspect, Qt::Alignment=Qt::Alignment()) const
Retrieves an alignment hint.
@ LeftToRight
@ RightToLeft