QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskLayoutElement.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskLayoutElement.h"
7#include "QskLayoutMetrics.h"
8#include "QskSizePolicy.h"
9
10static inline bool qskCanGrow(
11 const QskLayoutElement* element, Qt::Orientation orientation )
12{
13 const quint32 growFlags = QskSizePolicy::GrowFlag | QskSizePolicy::ExpandFlag;
14 return element->sizePolicy().policy( orientation ) & growFlags;
15}
16
17QskLayoutElement::QskLayoutElement()
18{
19}
20
21QskLayoutElement::~QskLayoutElement()
22{
23}
24
25QSizeF QskLayoutElement::sizeConstraint(
26 Qt::SizeHint which, const QSizeF& constraint ) const
27{
28 if ( constraint.isValid() )
29 return constraint;
30
31 auto policy = sizePolicy();
32
33 bool ignoreWidth = false;
34 bool ignoreHeight = false;
35
36 if ( which == Qt::PreferredSize )
37 {
38 /*
39 First we are checking the IgnoreFlag, to avoid doing
40 pointless calculations.
41 */
42 ignoreWidth = policy.policy( Qt::Horizontal ) & QskSizePolicy::IgnoreFlag;
43 ignoreHeight = policy.policy( Qt::Vertical ) & QskSizePolicy::IgnoreFlag;
44
45 if ( ( ignoreWidth && ignoreHeight )
46 || ( ignoreWidth && constraint.height() >= 0.0 )
47 || ( ignoreHeight && constraint.width() >= 0.0 ) )
48 {
49 return QSizeF();
50 }
51 }
52
53 const auto whichH = policy.effectiveSizeHintType( which, Qt::Horizontal );
54 const auto whichV = policy.effectiveSizeHintType( which, Qt::Vertical );
55
56 QSizeF size;
57
58 int constraintType = QskSizePolicy::Unconstrained;
59
60 /*
61 We apply a constraint - even, when the policy is unconstrained.
62 Do we really want to do this ???
63 */
64 if ( constraint.height() >= 0.0 )
65 {
66 const auto h = boundedSize( Qt::Vertical, constraint.height() );
67 size = sizeHint( whichV, QSizeF( -1.0, h ) );
68
69 if ( ( whichH != whichV ) || ( size.height() != h ) )
70 constraintType = QskSizePolicy::WidthForHeight;
71 }
72 else if ( constraint.width() >= 0.0 )
73 {
74 const auto w = boundedSize( Qt::Horizontal, constraint.width() );
75 size = sizeHint( whichH, QSizeF( w, -1.0 ) );
76
77 if ( ( whichV != whichH ) || ( size.width() != w ) )
78 constraintType = QskSizePolicy::HeightForWidth;
79 }
80 else
81 {
82 constraintType = policy.constraintType();
83
84 switch( constraintType )
85 {
86 case QskSizePolicy::WidthForHeight:
87 {
88 size = sizeHint( whichV );
89 break;
90 }
91 case QskSizePolicy::HeightForWidth:
92 {
93 size = sizeHint( whichH );
94 break;
95 }
96 default:
97 {
98 if ( whichV != whichH )
99 {
100 if ( !ignoreWidth )
101 size.rwidth() = sizeHint( whichH ).width();
102
103 if ( !ignoreHeight )
104 size.rheight() = sizeHint( whichV ).height();
105 }
106 else
107 {
108 size = sizeHint( whichH );
109 }
110 }
111 }
112 }
113
114 switch( constraintType )
115 {
116 case QskSizePolicy::HeightForWidth:
117 {
118 const QSizeF c( size.width(), -1.0 );
119 size.rheight() = sizeHint( whichV, c ).height();
120 break;
121 }
122 case QskSizePolicy::WidthForHeight:
123 {
124 const QSizeF c( -1.0, size.height() );
125 size.rwidth() = sizeHint( whichH, c ).width();
126 break;
127 }
128 }
129
130 if ( ignoreWidth || constraint.width() >= 0.0 )
131 size.rwidth() = -1.0;
132
133 if ( ignoreHeight || constraint.height() >= 0.0 )
134 size.rheight() = -1.0;
135
136 return size;
137}
138
139QSizeF QskLayoutElement::constrainedSize( const QSizeF& size ) const
140{
141 if ( size.width() <= 0.0 && size.height() <= 0.0 )
142 return QSizeF( 0.0, 0.0 );
143
144 QSizeF min, max;
145
146 const auto policy = sizePolicy();
147
148 switch( policy.constraintType() )
149 {
150 case QskSizePolicy::WidthForHeight:
151 {
152 const qreal h = boundedSize( Qt::Vertical, size.height() );
153
154 min = sizeConstraint( Qt::MinimumSize, QSizeF( -1.0, h ) );
155 max = sizeConstraint( Qt::MaximumSize, QSizeF( -1.0, h ) );
156
157 min.rheight() = max.rheight() = h;
158 break;
159 }
160 case QskSizePolicy::HeightForWidth:
161 {
162 const qreal w = boundedSize( Qt::Horizontal, size.width() );
163
164 min = sizeConstraint( Qt::MinimumSize, QSizeF( w, -1.0 ) );
165 max = sizeConstraint( Qt::MaximumSize, QSizeF( w, -1.0 ) );
166
167 min.rwidth() = max.rwidth() = w;
168 break;
169 }
170 default:
171 {
172 min = sizeConstraint( Qt::MinimumSize, QSizeF() );
173 max = sizeConstraint( Qt::MaximumSize, QSizeF() );
174 }
175 }
176
177 qreal width = size.width();
178 qreal height = size.height();
179
180 if ( max.width() >= 0.0 )
181 width = qMin( width, max.width() );
182
183 if ( max.height() >= 0.0 )
184 height = qMin( height, max.height() );
185
186 width = qMax( width, min.width() );
187 height = qMax( height, min.height() );
188
189 return QSizeF( width, height );
190}
191
192QskLayoutMetrics QskLayoutElement::metrics(
193 Qt::Orientation orientation, qreal constraint ) const
194{
195 const auto policy = sizePolicy().policy( orientation );
196
197 qreal minimum, preferred, maximum;
198
199 const auto expandFlags = QskSizePolicy::GrowFlag | QskSizePolicy::ExpandFlag;
200
201 if ( ( policy & QskSizePolicy::ShrinkFlag ) &&
202 ( policy & expandFlags ) && ( policy & QskSizePolicy::IgnoreFlag ) )
203 {
204 // we don't need to calculate the preferred size
205
206 minimum = metric( orientation, Qt::MinimumSize, -1.0 );
207 maximum = metric( orientation, Qt::MaximumSize, -1.0 );
208 preferred = minimum;
209 }
210 else
211 {
212 if ( constraint >= 0.0 )
213 {
214 if ( !( policy & QskSizePolicy::ConstrainedFlag ) )
215 constraint = -1.0;
216 }
217
218 preferred = metric( orientation, Qt::PreferredSize, constraint );
219
220 if ( policy & QskSizePolicy::ShrinkFlag )
221 minimum = metric( orientation, Qt::MinimumSize, -1.0 );
222 else
223 minimum = preferred;
224
225 if ( policy & expandFlags )
226 maximum = metric( orientation, Qt::MaximumSize, -1.0 );
227 else
228 maximum = preferred;
229
230 if ( policy & QskSizePolicy::IgnoreFlag )
231 preferred = minimum;
232 }
233
234 return QskLayoutMetrics( minimum, preferred, maximum );
235}
236
237qreal QskLayoutElement::metric( Qt::Orientation orientation,
238 Qt::SizeHint which, qreal constraint ) const
239{
240 qreal metric = 0.0;
241
242 if ( which == Qt::MinimumSize )
243 {
244 const auto hint = sizeHint( Qt::MinimumSize );
245
246 if ( orientation == Qt::Horizontal )
247 metric = hint.width();
248 else
249 metric = hint.height();
250
251 if ( metric < 0.0 )
252 metric = 0.0;
253 }
254 else if ( which == Qt::MaximumSize )
255 {
256 const auto hint = sizeHint( Qt::MaximumSize );
257
258 if ( orientation == Qt::Horizontal )
259 metric = hint.width();
260 else
261 metric = hint.height();
262
263 if ( metric < 0.0 )
264 metric = QskLayoutMetrics::unlimited;
265 }
266 else if ( which == Qt::PreferredSize )
267 {
268 const auto constraintType = sizePolicy().constraintType();
269
270 if ( constraintType == QskSizePolicy::Unconstrained )
271 {
272 const auto hint = sizeHint( Qt::PreferredSize );
273
274 if ( orientation == Qt::Horizontal )
275 metric = hint.width();
276 else
277 metric = hint.height();
278 }
279 else
280 {
281 if ( constraint < 0.0 )
282 {
283 auto hint = sizeHint( Qt::PreferredSize );
284
285 if ( orientation == Qt::Horizontal )
286 {
287 if ( constraintType == QskSizePolicy::WidthForHeight )
288 hint.setWidth( widthForHeight( hint.height() ) );
289
290 metric = hint.width();
291 }
292 else
293 {
294 if ( constraintType == QskSizePolicy::HeightForWidth )
295 hint.setHeight( heightForWidth( hint.width() ) );
296
297 metric = hint.height();
298 }
299 }
300 else
301 {
302 if ( orientation == Qt::Horizontal )
303 {
304 if ( !qskCanGrow( this, Qt::Vertical ) )
305 {
306 const auto maxH = sizeHint( Qt::PreferredSize ).height();
307
308 if ( maxH >= 0.0 )
309 constraint = qMin( constraint, maxH );
310 }
311
312 metric = widthForHeight( constraint );
313 }
314 else
315 {
316 if ( !qskCanGrow( this, Qt::Horizontal ) )
317 {
318 const auto maxW = sizeHint( Qt::PreferredSize ).width();
319
320 if ( maxW >= 0.0 )
321 constraint = qMin( constraint, maxW );
322 }
323
324 metric = heightForWidth( constraint );
325 }
326 }
327 }
328
329 if ( metric < 0.0 )
330 metric = 0.0;
331 }
332
333 return metric;
334}
335
336qreal QskLayoutElement::boundedSize( Qt::Orientation orientation, qreal size ) const
337{
338 const auto policy = sizePolicy();
339
340 const auto whichMin = policy.effectiveSizeHintType( Qt::MinimumSize, orientation );
341 const auto whichMax = policy.effectiveSizeHintType( Qt::MaximumSize, orientation );
342
343 const auto hintMin = sizeHint( whichMin );
344 const auto hintMax = ( whichMax == whichMin ) ? hintMin : sizeHint( whichMax );
345
346 if ( orientation == Qt::Horizontal )
347 {
348 if ( hintMax.width() >= 0.0 )
349 size = qMin( size, hintMax.width() );
350
351 size = qMax( size, hintMin.width() );
352 }
353 else
354 {
355 if ( hintMax.height() >= 0.0 )
356 size = qMin( size, hintMax.height() );
357
358 size = qMax( size, hintMin.height() );
359 }
360
361 return size;
362}
363
364#include "QskQuick.h"
365
366QskItemLayoutElement::QskItemLayoutElement( const QQuickItem* item )
367 : m_item( item )
368{
369}
370
371QskSizePolicy QskItemLayoutElement::sizePolicy() const
372{
373 return qskSizePolicy( m_item );
374}
375
376QSizeF QskItemLayoutElement::sizeHint( Qt::SizeHint which,
377 const QSizeF& constraint ) const
378{
379 return qskEffectiveSizeHint( m_item, which, constraint );
380}
381
382Qt::Alignment QskItemLayoutElement::alignment() const
383{
384 return qskLayoutAlignmentHint( m_item );
385}