1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQuick module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QQUICKANCHORS_P_P_H
41 #define QQUICKANCHORS_P_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include "qquickanchors_p.h"
55 #include "qquickitemchangelistener_p.h"
56 #include <private/qobject_p.h>
57 
58 QT_BEGIN_NAMESPACE
59 
60 class QQuickAnchorLine
61 {
62 public:
QQuickAnchorLine()63     QQuickAnchorLine() {}
QQuickAnchorLine(QQuickItem * i,QQuickAnchors::Anchor l)64     QQuickAnchorLine(QQuickItem *i, QQuickAnchors::Anchor l) : item(i), anchorLine(l) {}
QQuickAnchorLine(QQuickItem * i,uint l)65     QQuickAnchorLine(QQuickItem *i, uint l)
66         : item(i)
67         , anchorLine(static_cast<QQuickAnchors::Anchor>(l))
68     { Q_ASSERT(l < ((QQuickAnchors::BaselineAnchor << 1) - 1)); }
69 
70     QQuickItem *item = nullptr;
71     QQuickAnchors::Anchor anchorLine = QQuickAnchors::InvalidAnchor;
72 };
73 
74 inline bool operator==(const QQuickAnchorLine& a, const QQuickAnchorLine& b)
75 {
76     return a.item == b.item && a.anchorLine == b.anchorLine;
77 }
78 
79 class QQuickAnchorsPrivate : public QObjectPrivate, public QQuickItemChangeListener
80 {
Q_DECLARE_PUBLIC(QQuickAnchors)81     Q_DECLARE_PUBLIC(QQuickAnchors)
82 public:
83     QQuickAnchorsPrivate(QQuickItem *i)
84         : leftMargin(0)
85         , rightMargin(0)
86         , topMargin(0)
87         , bottomMargin(0)
88         , margins(0)
89         , vCenterOffset(0)
90         , hCenterOffset(0)
91         , baselineOffset(0)
92         , item(i)
93         , fill(nullptr)
94         , centerIn(nullptr)
95         , leftAnchorItem(nullptr)
96         , rightAnchorItem(nullptr)
97         , topAnchorItem(nullptr)
98         , bottomAnchorItem(nullptr)
99         , vCenterAnchorItem(nullptr)
100         , hCenterAnchorItem(nullptr)
101         , baselineAnchorItem(nullptr)
102         , leftAnchorLine(QQuickAnchors::InvalidAnchor)
103         , leftMarginExplicit(false)
104         , rightAnchorLine(QQuickAnchors::InvalidAnchor)
105         , rightMarginExplicit(false)
106         , topAnchorLine(QQuickAnchors::InvalidAnchor)
107         , topMarginExplicit(false)
108         , bottomAnchorLine(QQuickAnchors::InvalidAnchor)
109         , bottomMarginExplicit(false)
110         , vCenterAnchorLine(QQuickAnchors::InvalidAnchor)
111         , updatingMe(false)
112         , hCenterAnchorLine(QQuickAnchors::InvalidAnchor)
113         , inDestructor(false)
114         , baselineAnchorLine(QQuickAnchors::InvalidAnchor)
115         , centerAligned(true)
116         , usedAnchors(QQuickAnchors::InvalidAnchor)
117         , componentComplete(true)
118         , updatingFill(0)
119         , updatingCenterIn(0)
120         , updatingHorizontalAnchor(0)
121         , updatingVerticalAnchor(0)
122     {
123     }
124 
125     void clearItem(QQuickItem *);
126 
127     QQuickGeometryChange calculateDependency(QQuickItem *) const;
128     void addDepend(QQuickItem *);
129     void remDepend(QQuickItem *);
130     bool isItemComplete() const;
131 
132     void setItemHeight(qreal);
133     void setItemWidth(qreal);
134     void setItemX(qreal);
135     void setItemY(qreal);
136     void setItemPos(const QPointF &);
137     void setItemSize(const QSizeF &);
138 
139     void update();
140     void updateOnComplete();
141     void updateMe();
142 
143     // QQuickItemGeometryListener interface
144     void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override;
anchorPrivate()145     QQuickAnchorsPrivate *anchorPrivate() override { return this; }
146 
147     bool checkHValid() const;
148     bool checkVValid() const;
149     bool checkHAnchorValid(QQuickAnchorLine anchor) const;
150     bool checkVAnchorValid(QQuickAnchorLine anchor) const;
151     bool calcStretch(QQuickItem *edge1Item, QQuickAnchors::Anchor edge1Line,
152                      QQuickItem *edge2Item, QQuickAnchors::Anchor edge2Line,
153                      qreal offset1, qreal offset2, QQuickAnchors::Anchor line, qreal &stretch) const;
154 
155     bool isMirrored() const;
156     void updateHorizontalAnchors();
157     void updateVerticalAnchors();
158     void fillChanged();
159     void centerInChanged();
160 
161     qreal leftMargin;
162     qreal rightMargin;
163     qreal topMargin;
164     qreal bottomMargin;
165     qreal margins;
166     qreal vCenterOffset;
167     qreal hCenterOffset;
168     qreal baselineOffset;
169 
170     QQuickItem *item;
171 
172     QQuickItem *fill;
173     QQuickItem *centerIn;
174 
175     QQuickItem *leftAnchorItem;
176     QQuickItem *rightAnchorItem;
177     QQuickItem *topAnchorItem;
178     QQuickItem *bottomAnchorItem;
179     QQuickItem *vCenterAnchorItem;
180     QQuickItem *hCenterAnchorItem;
181     QQuickItem *baselineAnchorItem;
182 
183     // The bit fields below are carefully laid out in chunks of 1 byte, so the compiler doesn't
184     // need to generate 2 loads (and combining shifts/ors) to create a single field.
185 
186     QQuickAnchors::Anchor leftAnchorLine     : 7;
187     uint leftMarginExplicit                  : 1;
188     QQuickAnchors::Anchor rightAnchorLine    : 7;
189     uint rightMarginExplicit                 : 1;
190     QQuickAnchors::Anchor topAnchorLine      : 7;
191     uint topMarginExplicit                   : 1;
192     QQuickAnchors::Anchor bottomAnchorLine   : 7;
193     uint bottomMarginExplicit                : 1;
194 
195     QQuickAnchors::Anchor vCenterAnchorLine  : 7;
196     uint updatingMe                          : 1;
197     QQuickAnchors::Anchor hCenterAnchorLine  : 7;
198     uint inDestructor                        : 1;
199     QQuickAnchors::Anchor baselineAnchorLine : 7;
200     uint centerAligned                       : 1;
201     uint usedAnchors                         : 7; // QQuickAnchors::Anchors
202     uint componentComplete                   : 1;
203 
204     // Instead of using a mostly empty bit field, we can stretch the following fields up to be full
205     // bytes. The advantage is that incrementing/decrementing does not need any combining ands/ors.
206     qint8 updatingFill;
207     qint8 updatingCenterIn;
208     qint8 updatingHorizontalAnchor;
209     qint8 updatingVerticalAnchor;
210 
211 
get(QQuickAnchors * o)212     static inline QQuickAnchorsPrivate *get(QQuickAnchors *o) {
213         return static_cast<QQuickAnchorsPrivate *>(QObjectPrivate::get(o));
214     }
215 };
216 
217 QT_END_NAMESPACE
218 
219 Q_DECLARE_METATYPE(QQuickAnchorLine)
220 
221 #endif
222