QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskGraphicLabelSkinlet.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskGraphicLabelSkinlet.h"
7#include "QskGraphicLabel.h"
8
9#include "QskAspect.h"
10#include "QskColorFilter.h"
11#include "QskFunctions.h"
12#include "QskGraphic.h"
13
14#include <QtMath>
15
16QskGraphicLabelSkinlet::QskGraphicLabelSkinlet( QskSkin* skin )
17 : Inherited( skin )
18{
19 setNodeRoles( { PanelRole, GraphicRole } );
20}
21
22QskGraphicLabelSkinlet::~QskGraphicLabelSkinlet() = default;
23
24QRectF QskGraphicLabelSkinlet::subControlRect( const QskSkinnable* skinnable,
25 const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
26{
27 if ( subControl == QskGraphicLabel::Panel )
28 {
29 return contentsRect;
30 }
31 else if ( subControl == QskGraphicLabel::Graphic )
32 {
33 auto innerRect = contentsRect;
34
35 const auto label = static_cast< const QskGraphicLabel* >( skinnable );
36
37 if ( label->hasPanel() )
38 {
39 innerRect = label->subControlContentsRect(
40 innerRect, QskGraphicLabel::Panel );
41 }
42
43 return graphicRect( label, innerRect );
44 }
45
46 return Inherited::subControlRect( skinnable, contentsRect, subControl );
47}
48
49QSGNode* QskGraphicLabelSkinlet::updateSubNode(
50 const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
51{
52 const auto label = static_cast< const QskGraphicLabel* >( skinnable );
53
54 switch ( nodeRole )
55 {
56 case PanelRole:
57 {
58 if ( !label->hasPanel() )
59 return nullptr;
60
61 return updateBoxNode( label, node, QskGraphicLabel::Panel );
62 }
63 case GraphicRole:
64 {
65 return updateGraphicNode( label, node );
66 }
67 }
68
69 return Inherited::updateSubNode( skinnable, nodeRole, node );
70}
71
72QRect QskGraphicLabelSkinlet::graphicRect(
73 const QskGraphicLabel* label, const QRectF& contentsRect ) const
74{
75 using Q = QskGraphicLabel;
76
77 // textures are in integers, to avoid useless recalculations
78 // that finally will be rounded anyway, we calculate in integers
79
80 const auto fillMode = label->fillMode();
81
82 const QRect graphicRect = contentsRect.toAlignedRect();
83
84 if ( fillMode == Q::Stretch )
85 {
86 return graphicRect;
87 }
88
89 QSizeF sz = label->effectiveSourceSize();
90
91 if ( fillMode == Q::PreserveAspectFit )
92 {
93 sz.scale( graphicRect.size(), Qt::KeepAspectRatio );
94 }
95 else if ( fillMode == Q::PreserveAspectCrop )
96 {
97 sz.scale( graphicRect.size(), Qt::KeepAspectRatioByExpanding );
98 }
99
100 return qskAlignedRect( graphicRect,
101 qCeil( sz.width() ), qCeil( sz.height() ), label->alignment() );
102}
103
104QSGNode* QskGraphicLabelSkinlet::updateGraphicNode(
105 const QskGraphicLabel* label, QSGNode* node ) const
106{
107 using Q = QskGraphicLabel;
108
109 const auto colorFilter = label->graphicFilter();
110 const auto rect = label->subControlRect( Q::Graphic );
111
112 Qt::Orientations mirrored;
113 if ( label->mirror() )
114 mirrored = Qt::Horizontal;
115
116 if ( label->fillMode() == Q::Stretch )
117 {
118 node = QskSkinlet::updateGraphicNode( label, node,
119 label->graphic(), colorFilter, rect, mirrored );
120 }
121 else
122 {
123 node = QskSkinlet::updateGraphicNode( label, node,
124 label->graphic(), colorFilter, rect, Qt::AlignCenter, mirrored );
125 }
126
127 return node;
128}
129
130QSizeF QskGraphicLabelSkinlet::sizeHint( const QskSkinnable* skinnable,
131 Qt::SizeHint which, const QSizeF& constraint ) const
132{
133 using Q = QskGraphicLabel;
134
135 if ( which != Qt::PreferredSize )
136 return QSizeF();
137
138 const bool hasConstraint =
139 ( constraint.width() >= 0.0 ) || ( constraint.height() >= 0.0 );
140
141 const auto label = static_cast< const QskGraphicLabel* >( skinnable );
142 const auto sourceSize = label->effectiveSourceSize();
143
144 auto hint = sourceSize;
145
146 if ( hasConstraint && !sourceSize.isEmpty() )
147 {
148 auto innerConstraint = constraint;
149
150 if ( label->hasPanel() )
151 {
152 constexpr qreal max = std::numeric_limits< int >::max();
153
154 QRectF r( 0.0, 0.0, max, max );
155
156 if ( constraint.width() >= 0.0 )
157 r.setWidth( constraint.width() );
158 else
159 r.setHeight( constraint.height() );
160
161 innerConstraint = label->subControlContentsRect( r, Q::Panel ).size();
162 }
163
164 const qreal aspectRatio = sourceSize.width() / sourceSize.height();
165
166 if ( constraint.width() >= 0.0 )
167 hint.setHeight( innerConstraint.width() / aspectRatio );
168 else
169 hint.setWidth( innerConstraint.height() * aspectRatio );
170 }
171
172 hint = hint.expandedTo( label->strutSizeHint( Q::Graphic ) );
173
174 if ( label->hasPanel() )
175 {
176 hint = label->outerBoxSize( Q::Panel, hint );
177 hint = hint.expandedTo( label->strutSizeHint( Q::Panel ) );
178 }
179
180 if ( hasConstraint )
181 hint = hintWithoutConstraint( hint, constraint );
182
183 return hint;
184}
185
186#include "moc_QskGraphicLabelSkinlet.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
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.