Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickflexboxlayoutitem.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtCore/qloggingcategory.h>
6#include <QtQuickLayouts/private/qquickflexboxlayoutitem_p.h>
7#include <yoga/YGNode.h>
8
10
11Q_LOGGING_CATEGORY(lcQuickFlexLayoutItem, "qt.quick.flexlayouts.item")
12
13static constexpr YGWrap QtToYGFlexboxWrap(QQuickFlexboxLayout::FlexboxWrap qtWrap) {
14 switch (qtWrap) {
15 case QQuickFlexboxLayout::NoWrap: return YGWrap::YGWrapNoWrap;
16 case QQuickFlexboxLayout::Wrap: return YGWrap::YGWrapWrap;
17 case QQuickFlexboxLayout::WrapReverse: return YGWrap::YGWrapWrapReverse;
18 default: {
19 qWarning("Not a valid wrap");
20 return YGWrap{};
21 }
22 }
23};
24
25static constexpr YGFlexDirection QtToYGFlexboxDirection(QQuickFlexboxLayout::FlexboxDirection qtDirection) {
26 switch (qtDirection) {
27 case QQuickFlexboxLayout::Column: return YGFlexDirection::YGFlexDirectionColumn;
28 case QQuickFlexboxLayout::ColumnReverse: return YGFlexDirection::YGFlexDirectionColumnReverse;
29 case QQuickFlexboxLayout::Row: return YGFlexDirection::YGFlexDirectionRow;
30 case QQuickFlexboxLayout::RowReverse: return YGFlexDirection::YGFlexDirectionRowReverse;
31 default: {
32 qWarning("Not a valid direction");
33 return YGFlexDirection{};
34 }
35 }
36};
37
38static constexpr YGAlign QtToYGFlexboxAlignment(QQuickFlexboxLayout::FlexboxAlignment qtAlignment) {
39 switch (qtAlignment) {
40 case QQuickFlexboxLayout::AlignAuto: return YGAlign::YGAlignAuto;
41 case QQuickFlexboxLayout::AlignStart: return YGAlign::YGAlignFlexStart;
42 case QQuickFlexboxLayout::AlignCenter: return YGAlign::YGAlignCenter;
43 case QQuickFlexboxLayout::AlignEnd: return YGAlign::YGAlignFlexEnd;
44 case QQuickFlexboxLayout::AlignStretch: return YGAlign::YGAlignStretch;
45 case QQuickFlexboxLayout::AlignBaseline: return YGAlign::YGAlignBaseline;
46 case QQuickFlexboxLayout::AlignSpaceBetween: return YGAlign::YGAlignSpaceBetween;
47 case QQuickFlexboxLayout::AlignSpaceAround: return YGAlign::YGAlignSpaceAround;
48 case QQuickFlexboxLayout::AlignSpaceEvenly: {
49 return YGAlign{};
50 }
51 default: {
52 qWarning("Not a valid alignment");
53 return YGAlign{};
54 }
55 }
56};
57
58static constexpr YGJustify QtToYGFlexboxJustify(QQuickFlexboxLayout::FlexboxJustify qtJustify) {
59 switch (qtJustify) {
60 case QQuickFlexboxLayout::JustifyStart: return YGJustify::YGJustifyFlexStart;
61 case QQuickFlexboxLayout::JustifyCenter: return YGJustify::YGJustifyCenter;
62 case QQuickFlexboxLayout::JustifyEnd: return YGJustify::YGJustifyFlexEnd;
63 case QQuickFlexboxLayout::JustifySpaceBetween: return YGJustify::YGJustifySpaceBetween;
64 case QQuickFlexboxLayout::JustifySpaceAround: return YGJustify::YGJustifySpaceAround;
65 case QQuickFlexboxLayout::JustifySpaceEvenly: return YGJustify::YGJustifySpaceEvenly;
66 default: {
67 qWarning("Not a valid justify");
68 return YGJustify{};
69 }
70 }
71};
72
73static constexpr YGEdge QtToYGFlexboxEdge(QQuickFlexboxLayout::FlexboxEdge qtEdge) {
74 switch (qtEdge) {
75 case QQuickFlexboxLayout::EdgeLeft: return YGEdge::YGEdgeLeft;
76 case QQuickFlexboxLayout::EdgeRight: return YGEdge::YGEdgeRight;
77 case QQuickFlexboxLayout::EdgeTop: return YGEdge::YGEdgeTop;
78 case QQuickFlexboxLayout::EdgeBottom: return YGEdge::YGEdgeBottom;
79 case QQuickFlexboxLayout::EdgeAll: return YGEdge::YGEdgeAll;
80 default: {
81 qWarning("Not a valid edge");
82 return YGEdge{};
83 }
84 }
85};
86
87static constexpr YGGutter QtToYGFlexboxGap(QQuickFlexboxLayout::FlexboxGap qtGap) {
88 switch (qtGap) {
89 case QQuickFlexboxLayout::GapRow: return YGGutter::YGGutterRow;
90 case QQuickFlexboxLayout::GapColumn: return YGGutter::YGGutterColumn;
91 case QQuickFlexboxLayout::GapAll: return YGGutter::YGGutterAll;
92 default: {
93 qWarning("Not a valid gap");
94 return YGGutter{};
95 }
96 }
97};
98
99QQuickFlexboxLayoutItem::QQuickFlexboxLayoutItem(QQuickItem *item)
100 : m_item(item)
101{
102 Q_ASSERT(m_item != nullptr);
103 m_yogaNode = YGNodeNew();
104 resetDefault();
105}
106
107QQuickFlexboxLayoutItem::~QQuickFlexboxLayoutItem()
108{
109 YGNodeFree(m_yogaNode);
110}
111
112void QQuickFlexboxLayoutItem::setMinSize(const QSizeF &size)
113{
114 YGNodeStyleSetMinWidth(m_yogaNode, static_cast<float>(size.width()));
115 YGNodeStyleSetMinHeight(m_yogaNode, static_cast<float>(size.height()));
116}
117
118void QQuickFlexboxLayoutItem::setSize(const QSizeF &size)
119{
120 YGNodeStyleSetWidth(m_yogaNode, static_cast<float>(size.width()));
121 YGNodeStyleSetHeight(m_yogaNode, static_cast<float>(size.height()));
122}
123
124void QQuickFlexboxLayoutItem::setWidth(const qreal &width)
125{
126 YGNodeStyleSetWidth(m_yogaNode, static_cast<float>(width));
127}
128
129void QQuickFlexboxLayoutItem::setHeight(const qreal &height)
130{
131 YGNodeStyleSetHeight(m_yogaNode, static_cast<float>(height));
132}
133
134void QQuickFlexboxLayoutItem::setMaxSize(const QSizeF &size)
135{
136 YGNodeStyleSetMaxWidth(m_yogaNode, static_cast<float>(size.width()));
137 YGNodeStyleSetMaxHeight(m_yogaNode, static_cast<float>(size.height()));
138}
139
140void QQuickFlexboxLayoutItem::setFlexBasis(const qreal value, bool reset)
141{
142 YGNodeStyleSetFlexBasis(m_yogaNode, reset ? qQNaN() : value);
143}
144
145bool QQuickFlexboxLayoutItem::isFlexBasisUndefined() const
146{
147 float value = YGNodeStyleGetFlexBasis(m_yogaNode).value;
148 return (value == YGUndefined || qt_is_nan(value));
149}
150
151void QQuickFlexboxLayoutItem::setItemGrowAlongMainAxis(const qreal value)
152{
153 YGNodeStyleSetFlexGrow(m_yogaNode, value);
154}
155
156void QQuickFlexboxLayoutItem::setItemShrinkAlongMainAxis(const qreal value)
157{
158 YGNodeStyleSetFlexShrink(m_yogaNode, value);
159}
160
161void QQuickFlexboxLayoutItem::setItemStretchAlongCrossSection()
162{
163 YGNodeStyleSetAlignSelf(m_yogaNode, YGAlignStretch);
164}
165
166void QQuickFlexboxLayoutItem::setFlexDirection(QQuickFlexboxLayout::FlexboxDirection direction)
167{
168 YGNodeStyleSetFlexDirection(m_yogaNode, QtToYGFlexboxDirection(direction));
169}
170
171void QQuickFlexboxLayoutItem::setFlexWrap(QQuickFlexboxLayout::FlexboxWrap wrap)
172{
173 YGNodeStyleSetFlexWrap(m_yogaNode, QtToYGFlexboxWrap(wrap));
174}
175
176void QQuickFlexboxLayoutItem::setFlexAlignItemsProperty(QQuickFlexboxLayout::FlexboxAlignment align)
177{
178 YGNodeStyleSetAlignItems(m_yogaNode, QtToYGFlexboxAlignment(align));
179}
180
181void QQuickFlexboxLayoutItem::setFlexAlignContentProperty(QQuickFlexboxLayout::FlexboxAlignment align)
182{
183 YGNodeStyleSetAlignContent(m_yogaNode, QtToYGFlexboxAlignment(align));
184}
185
186void QQuickFlexboxLayoutItem::setFlexJustifyContentProperty(QQuickFlexboxLayout::FlexboxJustify justify)
187{
188 YGNodeStyleSetJustifyContent(m_yogaNode, QtToYGFlexboxJustify(justify));
189}
190
191void QQuickFlexboxLayoutItem::setFlexAlignSelfProperty(QQuickFlexboxLayout::FlexboxAlignment align)
192{
193 YGNodeStyleSetAlignSelf(m_yogaNode, QtToYGFlexboxAlignment(align));
194}
195
196void QQuickFlexboxLayoutItem::setFlexMargin(QQuickFlexboxLayout::FlexboxEdge edge, const qreal value)
197{
198 YGNodeStyleSetMargin(m_yogaNode, QtToYGFlexboxEdge(edge), value);
199}
200
201void QQuickFlexboxLayoutItem::setFlexPadding(QQuickFlexboxLayout::FlexboxEdge edge, const qreal value)
202{
203 YGNodeStyleSetPadding(m_yogaNode, QtToYGFlexboxEdge(edge), value);
204}
205
206void QQuickFlexboxLayoutItem::setFlexGap(QQuickFlexboxLayout::FlexboxGap gap, const qreal value)
207{
208 YGNodeStyleSetGap(m_yogaNode, QtToYGFlexboxGap(gap), value);
209}
210
211bool QQuickFlexboxLayoutItem::isItemStreched() const
212{
213 return ((YGNodeStyleGetAlignSelf(m_yogaNode) == YGAlignStretch) ||
214 ((YGNodeStyleGetAlignSelf(m_yogaNode) == YGAlignAuto) &&
215 (YGNodeStyleGetAlignItems(m_yogaNode->getParent()) == YGAlignStretch)));
216}
217
218void QQuickFlexboxLayoutItem::inheritItemStretchAlongCrossSection()
219{
220 YGNodeStyleSetAlignSelf(m_yogaNode, YGAlignAuto);
221}
222
223void QQuickFlexboxLayoutItem::resetMargins()
224{
225 YGNodeStyleSetMargin(m_yogaNode, YGEdgeLeft, 0);
226 YGNodeStyleSetMargin(m_yogaNode, YGEdgeTop, 0);
227 YGNodeStyleSetMargin(m_yogaNode, YGEdgeRight, 0);
228 YGNodeStyleSetMargin(m_yogaNode, YGEdgeBottom, 0);
229}
230
231void QQuickFlexboxLayoutItem::resetPaddings()
232{
233 YGNodeStyleSetPadding(m_yogaNode, YGEdgeAll, 0);
234}
235
236void QQuickFlexboxLayoutItem::resetSize()
237{
238 YGNodeStyleSetWidth(m_yogaNode, YGUndefined);
239 YGNodeStyleSetHeight(m_yogaNode, YGUndefined);
240}
241
242QPoint QQuickFlexboxLayoutItem::position() const
243{
244 return QPoint(YGNodeLayoutGetLeft(m_yogaNode), YGNodeLayoutGetTop(m_yogaNode));
245}
246
247QSizeF QQuickFlexboxLayoutItem::size() const
248{
249 return QSizeF(YGNodeLayoutGetWidth(m_yogaNode), YGNodeLayoutGetHeight(m_yogaNode));
250}
251
252void QQuickFlexboxLayoutItem::insertChild(QQuickFlexboxLayoutItem *child, int index)
253{
254 YGNodeInsertChild(m_yogaNode, child->yogaItem(), index);
255 // TODO: We may need this only for the text node?
256 // YGNodeSetMeasureFunc(m_yogaNode, &QQuickFlexboxLayoutItem::measureFunc);
257}
258
259void QQuickFlexboxLayoutItem::resetDefault()
260{
261 // Context object is required here for callback functionality
262 // For instance, the measurement function would be called to determine the
263 // layout size
264 YGNodeSetContext(m_yogaNode, this);
265 resetMargins();
266 resetPaddings();
267 YGNodeStyleSetFlexBasis(m_yogaNode, YGUndefined);
268}
269
270bool QQuickFlexboxLayoutItem::hasMeasureFunc() const
271{
272 return YGNodeHasMeasureFunc(m_yogaNode);
273}
274
275void QQuickFlexboxLayoutItem::resetMeasureFunc()
276{
277 YGNodeSetMeasureFunc(m_yogaNode, nullptr);
278}
279
280SizeHints &QQuickFlexboxLayoutItem::cachedItemSizeHints() const
281{
282 return m_cachedSizeHint;
283}
284
285void QQuickFlexboxLayoutItem::computeLayout(const QSizeF &size)
286{
287 // Consider either NaN or Inf as YGUndefined
288 const float width = (qt_is_nan(size.width()) || qt_is_inf(size.width()) ||
289 !size.width()) ? YGUndefined : size.width();
290 const float height = (qt_is_nan(size.height()) || qt_is_inf(size.height()) ||
291 !size.height()) ? YGUndefined : size.height();
292 YGNodeCalculateLayout(m_yogaNode, width, height, YGDirectionLTR);
293}
294
295QT_END_NAMESPACE
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
static constexpr YGJustify QtToYGFlexboxJustify(QQuickFlexboxLayout::FlexboxJustify qtJustify)
static constexpr YGGutter QtToYGFlexboxGap(QQuickFlexboxLayout::FlexboxGap qtGap)
static constexpr YGEdge QtToYGFlexboxEdge(QQuickFlexboxLayout::FlexboxEdge qtEdge)
static constexpr YGAlign QtToYGFlexboxAlignment(QQuickFlexboxLayout::FlexboxAlignment qtAlignment)
static QT_BEGIN_NAMESPACE constexpr YGWrap QtToYGFlexboxWrap(QQuickFlexboxLayout::FlexboxWrap qtWrap)
static constexpr YGFlexDirection QtToYGFlexboxDirection(QQuickFlexboxLayout::FlexboxDirection qtDirection)