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 #include "qquickanchors_p_p.h"
41 
42 #include "qquickitem_p.h"
43 
44 #include <qqmlinfo.h>
45 
46 QT_BEGIN_NAMESPACE
47 
readParentItem(const QQuickItem * item)48 static Q_ALWAYS_INLINE QQuickItem *readParentItem(const QQuickItem *item)
49 {
50     return QQuickItemPrivate::get(item)->parentItem;
51 }
52 
readX(const QQuickItem * item)53 static Q_ALWAYS_INLINE qreal readX(const QQuickItem *item)
54 {
55     return QQuickItemPrivate::get(item)->x;
56 }
57 
readY(const QQuickItem * item)58 static Q_ALWAYS_INLINE qreal readY(const QQuickItem *item)
59 {
60     return QQuickItemPrivate::get(item)->y;
61 }
62 
readWidth(const QQuickItem * item)63 static Q_ALWAYS_INLINE qreal readWidth(const QQuickItem *item)
64 {
65     return QQuickItemPrivate::get(item)->width;
66 }
67 
readHeight(const QQuickItem * item)68 static Q_ALWAYS_INLINE qreal readHeight(const QQuickItem *item)
69 {
70     return QQuickItemPrivate::get(item)->height;
71 }
72 
readBaselineOffset(const QQuickItem * item)73 static Q_ALWAYS_INLINE qreal readBaselineOffset(const QQuickItem *item)
74 {
75     return QQuickItemPrivate::get(item)->baselineOffset;
76 }
77 
78 //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
79 //TODO: support non-parent, non-sibling (need to find lowest common ancestor)
80 
hcenter(const QQuickItem * item)81 static inline qreal hcenter(const QQuickItem *item)
82 {
83     qreal width = readWidth(item);
84     if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
85         if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
86             return width / 2;
87     }
88     int iw = width;
89     if (iw % 2)
90         return (width + 1) / 2;
91     else
92         return width / 2;
93 }
94 
vcenter(const QQuickItem * item)95 static inline qreal vcenter(const QQuickItem *item)
96 {
97     qreal height = readHeight(item);
98     if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
99         if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
100             return height / 2;
101     }
102     int ih = height;
103     if (ih % 2)
104         return (height + 1) / 2;
105     else
106         return height / 2;
107 }
108 
109 //local position
position(const QQuickItem * item,QQuickAnchors::Anchor anchorLine)110 static inline qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
111 {
112     qreal ret = 0.0;
113     switch (anchorLine) {
114     case QQuickAnchors::LeftAnchor:
115         ret = readX(item);
116         break;
117     case QQuickAnchors::RightAnchor:
118         ret = readX(item) + readWidth(item);
119         break;
120     case QQuickAnchors::TopAnchor:
121         ret = readY(item);
122         break;
123     case QQuickAnchors::BottomAnchor:
124         ret = readY(item) + readHeight(item);
125         break;
126     case QQuickAnchors::HCenterAnchor:
127         ret = readX(item) + hcenter(item);
128         break;
129     case QQuickAnchors::VCenterAnchor:
130         ret = readY(item) + vcenter(item);
131         break;
132     case QQuickAnchors::BaselineAnchor:
133         ret = readY(item) + readBaselineOffset(item);
134         break;
135     default:
136         break;
137     }
138 
139     return ret;
140 }
141 
142 //position when origin is 0,0
adjustedPosition(QQuickItem * item,QQuickAnchors::Anchor anchorLine)143 static inline qreal adjustedPosition(QQuickItem *item, QQuickAnchors::Anchor anchorLine)
144 {
145     qreal ret = 0.0;
146     switch (anchorLine) {
147     case QQuickAnchors::LeftAnchor:
148         ret = 0.0;
149         break;
150     case QQuickAnchors::RightAnchor:
151         ret = readWidth(item);
152         break;
153     case QQuickAnchors::TopAnchor:
154         ret = 0.0;
155         break;
156     case QQuickAnchors::BottomAnchor:
157         ret = readHeight(item);
158         break;
159     case QQuickAnchors::HCenterAnchor:
160         ret = hcenter(item);
161         break;
162     case QQuickAnchors::VCenterAnchor:
163         ret = vcenter(item);
164         break;
165     case QQuickAnchors::BaselineAnchor:
166         ret = readBaselineOffset(item);
167         break;
168     default:
169         break;
170     }
171 
172     return ret;
173 }
174 
QQuickAnchors(QQuickItem * item,QObject * parent)175 QQuickAnchors::QQuickAnchors(QQuickItem *item, QObject *parent)
176 : QObject(*new QQuickAnchorsPrivate(item), parent)
177 {
178 }
179 
~QQuickAnchors()180 QQuickAnchors::~QQuickAnchors()
181 {
182     Q_D(QQuickAnchors);
183     d->inDestructor = true;
184     d->remDepend(d->fill);
185     d->remDepend(d->centerIn);
186     d->remDepend(d->leftAnchorItem);
187     d->remDepend(d->rightAnchorItem);
188     d->remDepend(d->topAnchorItem);
189     d->remDepend(d->bottomAnchorItem);
190     d->remDepend(d->vCenterAnchorItem);
191     d->remDepend(d->hCenterAnchorItem);
192     d->remDepend(d->baselineAnchorItem);
193 }
194 
fillChanged()195 void QQuickAnchorsPrivate::fillChanged()
196 {
197     Q_Q(QQuickAnchors);
198     if (!fill || !isItemComplete())
199         return;
200 
201     if (updatingFill < 2) {
202         ++updatingFill;
203 
204         qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
205 
206         if (fill == readParentItem(item)) {                         //child-parent
207             setItemPos(QPointF(horizontalMargin, topMargin));
208         } else if (readParentItem(fill) == readParentItem(item)) {   //siblings
209             setItemPos(QPointF(readX(fill)+horizontalMargin, readY(fill) + topMargin));
210         }
211         setItemSize(QSizeF(readWidth(fill) - leftMargin - rightMargin,
212                            readHeight(fill) - topMargin - bottomMargin));
213 
214         --updatingFill;
215     } else {
216         // ### Make this certain :)
217         qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on fill.");
218     }
219 
220 }
221 
centerInChanged()222 void QQuickAnchorsPrivate::centerInChanged()
223 {
224     Q_Q(QQuickAnchors);
225     if (!centerIn || fill || !isItemComplete())
226         return;
227 
228     if (updatingCenterIn < 2) {
229         ++updatingCenterIn;
230 
231         qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
232         if (centerIn == readParentItem(item)) {
233             QPointF p(hcenter(readParentItem(item)) - hcenter(item) + effectiveHCenterOffset,
234                       vcenter(readParentItem(item)) - vcenter(item) + vCenterOffset);
235             setItemPos(p);
236 
237         } else if (readParentItem(centerIn) == readParentItem(item)) {
238             QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset,
239                       centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
240             setItemPos(p);
241         }
242 
243         --updatingCenterIn;
244     } else {
245         // ### Make this certain :)
246         qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on centerIn.");
247     }
248 }
249 
clearItem(QQuickItem * item)250 void QQuickAnchorsPrivate::clearItem(QQuickItem *item)
251 {
252     if (!item)
253         return;
254     if (fill == item)
255         fill = nullptr;
256     if (centerIn == item)
257         centerIn = nullptr;
258     if (leftAnchorItem == item) {
259         leftAnchorItem = nullptr;
260         usedAnchors &= ~QQuickAnchors::LeftAnchor;
261     }
262     if (rightAnchorItem == item) {
263         rightAnchorItem = nullptr;
264         usedAnchors &= ~QQuickAnchors::RightAnchor;
265     }
266     if (topAnchorItem == item) {
267         topAnchorItem = nullptr;
268         usedAnchors &= ~QQuickAnchors::TopAnchor;
269     }
270     if (bottomAnchorItem == item) {
271         bottomAnchorItem = nullptr;
272         usedAnchors &= ~QQuickAnchors::BottomAnchor;
273     }
274     if (vCenterAnchorItem == item) {
275         vCenterAnchorItem = nullptr;
276         usedAnchors &= ~QQuickAnchors::VCenterAnchor;
277     }
278     if (hCenterAnchorItem == item) {
279         hCenterAnchorItem = nullptr;
280         usedAnchors &= ~QQuickAnchors::HCenterAnchor;
281     }
282     if (baselineAnchorItem == item) {
283         baselineAnchorItem = nullptr;
284         usedAnchors &= ~QQuickAnchors::BaselineAnchor;
285     }
286 }
287 
calculateDependency(QQuickItem * controlItem) const288 QQuickGeometryChange QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem) const
289 {
290     QQuickGeometryChange dependency;
291 
292     if (!controlItem || inDestructor)
293         return dependency;
294 
295     if (fill == controlItem) {
296         if (controlItem == readParentItem(item))
297             dependency.setSizeChange(true);
298         else    //sibling
299             dependency.setAllChanged(true);
300         return dependency;  //exit early
301     }
302 
303     if (centerIn == controlItem) {
304         if (controlItem == readParentItem(item))
305             dependency.setSizeChange(true);
306         else    //sibling
307             dependency.setAllChanged(true);
308         return dependency;  //exit early
309     }
310 
311     if ((usedAnchors & QQuickAnchors::LeftAnchor && leftAnchorItem == controlItem) ||
312         (usedAnchors & QQuickAnchors::RightAnchor && rightAnchorItem == controlItem) ||
313         (usedAnchors & QQuickAnchors::HCenterAnchor && hCenterAnchorItem == controlItem)) {
314         if (controlItem == readParentItem(item))
315             dependency.setWidthChange(true);
316         else    //sibling
317             dependency.setHorizontalChange(true);
318     }
319 
320     if ((usedAnchors & QQuickAnchors::TopAnchor && topAnchorItem == controlItem) ||
321         (usedAnchors & QQuickAnchors::BottomAnchor && bottomAnchorItem == controlItem) ||
322         (usedAnchors & QQuickAnchors::VCenterAnchor && vCenterAnchorItem == controlItem) ||
323         (usedAnchors & QQuickAnchors::BaselineAnchor && baselineAnchorItem == controlItem)) {
324         if (controlItem == readParentItem(item))
325             dependency.setHeightChange(true);
326         else    //sibling
327             dependency.setVerticalChange(true);
328     }
329 
330     return dependency;
331 }
332 
addDepend(QQuickItem * item)333 void QQuickAnchorsPrivate::addDepend(QQuickItem *item)
334 {
335     if (!item || !componentComplete)
336         return;
337 
338     QQuickItemPrivate *p = QQuickItemPrivate::get(item);
339     p->updateOrAddGeometryChangeListener(this, calculateDependency(item));
340 }
341 
remDepend(QQuickItem * item)342 void QQuickAnchorsPrivate::remDepend(QQuickItem *item)
343 {
344     if (!item || !componentComplete)
345         return;
346 
347     QQuickItemPrivate *p = QQuickItemPrivate::get(item);
348     p->updateOrRemoveGeometryChangeListener(this, calculateDependency(item));
349 }
350 
mirrored()351 bool QQuickAnchors::mirrored()
352 {
353     Q_D(QQuickAnchors);
354     return QQuickItemPrivate::get(d->item)->effectiveLayoutMirror;
355 }
356 
alignWhenCentered() const357 bool QQuickAnchors::alignWhenCentered() const
358 {
359     Q_D(const QQuickAnchors);
360     return d->centerAligned;
361 }
362 
setAlignWhenCentered(bool aligned)363 void QQuickAnchors::setAlignWhenCentered(bool aligned)
364 {
365     Q_D(QQuickAnchors);
366     if (aligned == d->centerAligned)
367         return;
368     d->centerAligned = aligned;
369     emit centerAlignedChanged();
370     if (d->centerIn) {
371         d->centerInChanged();
372     } else {
373         if (d->usedAnchors & QQuickAnchors::VCenterAnchor)
374             d->updateVerticalAnchors();
375         else if (d->usedAnchors & QQuickAnchors::HCenterAnchor)
376             d->updateHorizontalAnchors();
377     }
378 }
379 
isItemComplete() const380 bool QQuickAnchorsPrivate::isItemComplete() const
381 {
382     return componentComplete;
383 }
384 
classBegin()385 void QQuickAnchors::classBegin()
386 {
387     Q_D(QQuickAnchors);
388     d->componentComplete = false;
389 }
390 
componentComplete()391 void QQuickAnchors::componentComplete()
392 {
393     Q_D(QQuickAnchors);
394     d->componentComplete = true;
395 }
396 
setItemHeight(qreal v)397 void QQuickAnchorsPrivate::setItemHeight(qreal v)
398 {
399     updatingMe = true;
400     item->setHeight(v);
401     updatingMe = false;
402 }
403 
setItemWidth(qreal v)404 void QQuickAnchorsPrivate::setItemWidth(qreal v)
405 {
406     updatingMe = true;
407     item->setWidth(v);
408     updatingMe = false;
409 }
410 
setItemX(qreal v)411 void QQuickAnchorsPrivate::setItemX(qreal v)
412 {
413     updatingMe = true;
414     item->setX(v);
415     updatingMe = false;
416 }
417 
setItemY(qreal v)418 void QQuickAnchorsPrivate::setItemY(qreal v)
419 {
420     updatingMe = true;
421     item->setY(v);
422     updatingMe = false;
423 }
424 
setItemPos(const QPointF & v)425 void QQuickAnchorsPrivate::setItemPos(const QPointF &v)
426 {
427     updatingMe = true;
428     item->setPosition(v);
429     updatingMe = false;
430 }
431 
setItemSize(const QSizeF & v)432 void QQuickAnchorsPrivate::setItemSize(const QSizeF &v)
433 {
434     updatingMe = true;
435     item->setSize(v);
436     updatingMe = false;
437 }
438 
updateMe()439 void QQuickAnchorsPrivate::updateMe()
440 {
441     if (updatingMe) {
442         updatingMe = false;
443         return;
444     }
445 
446     update();
447 }
448 
updateOnComplete()449 void QQuickAnchorsPrivate::updateOnComplete()
450 {
451     //optimization to only set initial dependencies once, at completion time
452     QQuickItem *dependencies[9];
453     dependencies[0] = fill;
454     dependencies[1] = centerIn;
455     dependencies[2] = leftAnchorItem;
456     dependencies[3] = rightAnchorItem;
457     dependencies[4] = hCenterAnchorItem;
458     dependencies[5] = topAnchorItem;
459     dependencies[6] = bottomAnchorItem;
460     dependencies[7] = vCenterAnchorItem;
461     dependencies[8] = baselineAnchorItem;
462 
463     std::sort(dependencies, dependencies + 9);
464 
465     QQuickItem *lastDependency = nullptr;
466     for (int i = 0; i < 9; ++i) {
467         QQuickItem *dependency = dependencies[i];
468         if (lastDependency != dependency) {
469             addDepend(dependency);
470             lastDependency = dependency;
471         }
472     }
473 
474     update();
475 }
476 
477 
update()478 void QQuickAnchorsPrivate::update()
479 {
480     if (!isItemComplete())
481         return;
482 
483     if (fill) {
484         fillChanged();
485     } else if (centerIn) {
486         centerInChanged();
487     } else {
488         if (usedAnchors & QQuickAnchors::Horizontal_Mask)
489             updateHorizontalAnchors();
490         if (usedAnchors & QQuickAnchors::Vertical_Mask)
491             updateVerticalAnchors();
492     }
493 }
494 
itemGeometryChanged(QQuickItem *,QQuickGeometryChange change,const QRectF &)495 void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange change, const QRectF &)
496 {
497     if (!isItemComplete())
498         return;
499 
500     if (fill) {
501         fillChanged();
502     } else if (centerIn) {
503         centerInChanged();
504     } else {
505         if ((usedAnchors & QQuickAnchors::Horizontal_Mask) && change.horizontalChange())
506             updateHorizontalAnchors();
507         if ((usedAnchors & QQuickAnchors::Vertical_Mask) && change.verticalChange())
508             updateVerticalAnchors();
509     }
510 }
511 
fill() const512 QQuickItem *QQuickAnchors::fill() const
513 {
514     Q_D(const QQuickAnchors);
515     return d->fill;
516 }
517 
setFill(QQuickItem * f)518 void QQuickAnchors::setFill(QQuickItem *f)
519 {
520     Q_D(QQuickAnchors);
521     if (d->fill == f)
522         return;
523 
524     if (!f) {
525         QQuickItem *oldFill = d->fill;
526         d->fill = f;
527         d->remDepend(oldFill);
528         emit fillChanged();
529         return;
530     }
531     if (f != readParentItem(d->item) && readParentItem(f) != readParentItem(d->item)){
532         qmlWarning(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
533         return;
534     }
535     QQuickItem *oldFill = d->fill;
536     d->fill = f;
537     d->remDepend(oldFill);
538     d->addDepend(d->fill);
539     emit fillChanged();
540     d->fillChanged();
541 }
542 
resetFill()543 void QQuickAnchors::resetFill()
544 {
545     setFill(nullptr);
546 }
547 
centerIn() const548 QQuickItem *QQuickAnchors::centerIn() const
549 {
550     Q_D(const QQuickAnchors);
551     return d->centerIn;
552 }
553 
setCenterIn(QQuickItem * c)554 void QQuickAnchors::setCenterIn(QQuickItem* c)
555 {
556     Q_D(QQuickAnchors);
557     if (d->centerIn == c)
558         return;
559 
560     if (!c) {
561         QQuickItem *oldCI = d->centerIn;
562         d->centerIn = c;
563         d->remDepend(oldCI);
564         emit centerInChanged();
565         return;
566     }
567     if (c != readParentItem(d->item) && readParentItem(c) != readParentItem(d->item)){
568         qmlWarning(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
569         return;
570     }
571     QQuickItem *oldCI = d->centerIn;
572     d->centerIn = c;
573     d->remDepend(oldCI);
574     d->addDepend(d->centerIn);
575     emit centerInChanged();
576     d->centerInChanged();
577 }
578 
resetCenterIn()579 void QQuickAnchors::resetCenterIn()
580 {
581     setCenterIn(nullptr);
582 }
583 
calcStretch(QQuickItem * edge1Item,QQuickAnchors::Anchor edge1Line,QQuickItem * edge2Item,QQuickAnchors::Anchor edge2Line,qreal offset1,qreal offset2,QQuickAnchors::Anchor line,qreal & stretch) const584 bool QQuickAnchorsPrivate::calcStretch(QQuickItem *edge1Item,
585                                        QQuickAnchors::Anchor edge1Line,
586                                        QQuickItem *edge2Item,
587                                        QQuickAnchors::Anchor edge2Line,
588                                        qreal offset1,
589                                        qreal offset2,
590                                        QQuickAnchors::Anchor line,
591                                        qreal &stretch) const
592 {
593     bool edge1IsParent = (edge1Item == readParentItem(item));
594     bool edge2IsParent = (edge2Item == readParentItem(item));
595     bool edge1IsSibling = (readParentItem(edge1Item) == readParentItem(item));
596     bool edge2IsSibling = (readParentItem(edge2Item) == readParentItem(item));
597 
598     bool invalid = false;
599     if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
600         stretch = (position(edge2Item, edge2Line) + offset2)
601                     - (position(edge1Item, edge1Line) + offset1);
602     } else if (edge2IsParent && edge1IsSibling) {
603         stretch = (position(edge2Item, edge2Line) + offset2)
604                     - (position(readParentItem(item), line)
605                     + position(edge1Item, edge1Line) + offset1);
606     } else if (edge2IsSibling && edge1IsParent) {
607         stretch = (position(readParentItem(item), line) + position(edge2Item, edge2Line) + offset2)
608                     - (position(edge1Item, edge1Line) + offset1);
609     } else
610         invalid = true;
611 
612     return invalid;
613 }
614 
updateVerticalAnchors()615 void QQuickAnchorsPrivate::updateVerticalAnchors()
616 {
617     if (fill || centerIn || !isItemComplete())
618         return;
619 
620     if (Q_UNLIKELY(updatingVerticalAnchor > 1)) {
621         // ### Make this certain :)
622         qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on vertical anchor.");
623         return;
624     }
625 
626     ++updatingVerticalAnchor;
627     if (usedAnchors & QQuickAnchors::TopAnchor) {
628         //Handle stretching
629         bool invalid = true;
630         qreal height = 0.0;
631         if (usedAnchors & QQuickAnchors::BottomAnchor) {
632             invalid = calcStretch(topAnchorItem, topAnchorLine,
633                                   bottomAnchorItem, bottomAnchorLine,
634                                   topMargin, -bottomMargin, QQuickAnchors::TopAnchor, height);
635         } else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
636             invalid = calcStretch(topAnchorItem, topAnchorLine,
637                                   vCenterAnchorItem, vCenterAnchorLine,
638                                   topMargin, vCenterOffset, QQuickAnchors::TopAnchor, height);
639             height *= 2;
640         }
641         if (!invalid)
642             setItemHeight(height);
643 
644         //Handle top
645         if (topAnchorItem == readParentItem(item)) {
646             setItemY(adjustedPosition(topAnchorItem, topAnchorLine) + topMargin);
647         } else if (readParentItem(topAnchorItem) == readParentItem(item)) {
648             setItemY(position(topAnchorItem, topAnchorLine) + topMargin);
649         }
650     } else if (usedAnchors & QQuickAnchors::BottomAnchor) {
651         //Handle stretching (top + bottom case is handled above)
652         if (usedAnchors & QQuickAnchors::VCenterAnchor) {
653             qreal height = 0.0;
654             bool invalid = calcStretch(vCenterAnchorItem, vCenterAnchorLine,
655                                        bottomAnchorItem, bottomAnchorLine,
656                                        vCenterOffset, -bottomMargin, QQuickAnchors::TopAnchor,
657                                        height);
658             if (!invalid)
659                 setItemHeight(height*2);
660         }
661 
662         //Handle bottom
663         if (bottomAnchorItem == readParentItem(item)) {
664             setItemY(adjustedPosition(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin);
665         } else if (readParentItem(bottomAnchorItem) == readParentItem(item)) {
666             setItemY(position(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin);
667         }
668     } else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
669         //(stetching handled above)
670 
671         //Handle vCenter
672         if (vCenterAnchorItem == readParentItem(item)) {
673             setItemY(adjustedPosition(vCenterAnchorItem, vCenterAnchorLine)
674                      - vcenter(item) + vCenterOffset);
675         } else if (readParentItem(vCenterAnchorItem) == readParentItem(item)) {
676             setItemY(position(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset);
677         }
678     } else if (usedAnchors & QQuickAnchors::BaselineAnchor) {
679         //Handle baseline
680         if (baselineAnchorItem == readParentItem(item)) {
681             setItemY(adjustedPosition(baselineAnchorItem, baselineAnchorLine)
682                      - readBaselineOffset(item) + baselineOffset);
683         } else if (readParentItem(baselineAnchorItem) == readParentItem(item)) {
684             setItemY(position(baselineAnchorItem, baselineAnchorLine)
685                      - readBaselineOffset(item) + baselineOffset);
686         }
687     }
688     --updatingVerticalAnchor;
689 }
690 
reverseAnchorLine(QQuickAnchors::Anchor anchorLine)691 static inline QQuickAnchors::Anchor reverseAnchorLine(QQuickAnchors::Anchor anchorLine)
692 {
693     if (anchorLine == QQuickAnchors::LeftAnchor) {
694         return QQuickAnchors::RightAnchor;
695     } else if (anchorLine == QQuickAnchors::RightAnchor) {
696         return QQuickAnchors::LeftAnchor;
697     } else {
698         return anchorLine;
699     }
700 }
701 
updateHorizontalAnchors()702 void QQuickAnchorsPrivate::updateHorizontalAnchors()
703 {
704     Q_Q(QQuickAnchors);
705     if (fill || centerIn || !isItemComplete())
706         return;
707 
708     if (updatingHorizontalAnchor < 3) {
709         ++updatingHorizontalAnchor;
710         qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
711         QQuickItem *effectiveLeftItem, *effectiveRightItem, *effectiveHorizontalCenterItem;
712         QQuickAnchors::Anchor effectiveLeftLine, effectiveRightLine, effectiveHorizontalCenterLine;
713         QQuickAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
714         if (q->mirrored()) {
715             effectiveLeftAnchor = QQuickAnchors::RightAnchor;
716             effectiveRightAnchor = QQuickAnchors::LeftAnchor;
717             effectiveLeftItem = rightAnchorItem;
718             effectiveLeftLine = reverseAnchorLine(rightAnchorLine);
719             effectiveRightItem = leftAnchorItem;
720             effectiveRightLine = reverseAnchorLine(leftAnchorLine);
721             effectiveHorizontalCenterItem = hCenterAnchorItem;
722             effectiveHorizontalCenterLine = reverseAnchorLine(hCenterAnchorLine);
723             effectiveLeftMargin = rightMargin;
724             effectiveRightMargin = leftMargin;
725             effectiveHorizontalCenterOffset = -hCenterOffset;
726         } else {
727             effectiveLeftAnchor = QQuickAnchors::LeftAnchor;
728             effectiveRightAnchor = QQuickAnchors::RightAnchor;
729             effectiveLeftItem = leftAnchorItem;
730             effectiveLeftLine = leftAnchorLine;
731             effectiveRightItem = rightAnchorItem;
732             effectiveRightLine = rightAnchorLine;
733             effectiveHorizontalCenterItem = hCenterAnchorItem;
734             effectiveHorizontalCenterLine = hCenterAnchorLine;
735             effectiveLeftMargin = leftMargin;
736             effectiveRightMargin = rightMargin;
737             effectiveHorizontalCenterOffset = hCenterOffset;
738         }
739 
740         if (usedAnchors & effectiveLeftAnchor) {
741             //Handle stretching
742             bool invalid = true;
743             qreal width = 0.0;
744             if (usedAnchors & effectiveRightAnchor) {
745                 invalid = calcStretch(effectiveLeftItem, effectiveLeftLine,
746                                       effectiveRightItem, effectiveRightLine,
747                                       effectiveLeftMargin, -effectiveRightMargin,
748                                       QQuickAnchors::LeftAnchor, width);
749             } else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
750                 invalid = calcStretch(effectiveLeftItem, effectiveLeftLine,
751                                       effectiveHorizontalCenterItem, effectiveHorizontalCenterLine,
752                                       effectiveLeftMargin, effectiveHorizontalCenterOffset,
753                                       QQuickAnchors::LeftAnchor, width);
754                 width *= 2;
755             }
756             if (!invalid)
757                 setItemWidth(width);
758 
759             //Handle left
760             if (effectiveLeftItem == readParentItem(item)) {
761                 setItemX(adjustedPosition(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin);
762             } else if (readParentItem(effectiveLeftItem) == readParentItem(item)) {
763                 setItemX(position(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin);
764             }
765         } else if (usedAnchors & effectiveRightAnchor) {
766             //Handle stretching (left + right case is handled in updateLeftAnchor)
767             if (usedAnchors & QQuickAnchors::HCenterAnchor) {
768                 qreal width = 0.0;
769                 bool invalid = calcStretch(effectiveHorizontalCenterItem,
770                                            effectiveHorizontalCenterLine,
771                                            effectiveRightItem,  effectiveRightLine,
772                                            effectiveHorizontalCenterOffset, -effectiveRightMargin,
773                                            QQuickAnchors::LeftAnchor, width);
774                 if (!invalid)
775                     setItemWidth(width*2);
776             }
777 
778             //Handle right
779             if (effectiveRightItem == readParentItem(item)) {
780                 setItemX(adjustedPosition(effectiveRightItem, effectiveRightLine)
781                          - readWidth(item) - effectiveRightMargin);
782             } else if (readParentItem(effectiveRightItem) == readParentItem(item)) {
783                 setItemX(position(effectiveRightItem, effectiveRightLine)
784                          - readWidth(item) - effectiveRightMargin);
785             }
786         } else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
787             //Handle hCenter
788             if (effectiveHorizontalCenterItem == readParentItem(item)) {
789                 setItemX(adjustedPosition(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset);
790             } else if (readParentItem(effectiveHorizontalCenterItem) == readParentItem(item)) {
791                 setItemX(position(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset);
792             }
793         }
794         --updatingHorizontalAnchor;
795     } else {
796         // ### Make this certain :)
797         qmlWarning(item) << QQuickAnchors::tr("Possible anchor loop detected on horizontal anchor.");
798     }
799 }
800 
top() const801 QQuickAnchorLine QQuickAnchors::top() const
802 {
803     Q_D(const QQuickAnchors);
804     return QQuickAnchorLine(d->topAnchorItem, d->topAnchorLine);
805 }
806 
setTop(const QQuickAnchorLine & edge)807 void QQuickAnchors::setTop(const QQuickAnchorLine &edge)
808 {
809     Q_D(QQuickAnchors);
810     if (!d->checkVAnchorValid(edge) ||
811             (d->topAnchorItem == edge.item && d->topAnchorLine == edge.anchorLine))
812         return;
813 
814     d->usedAnchors |= TopAnchor;
815 
816     if (!d->checkVValid()) {
817         d->usedAnchors &= ~TopAnchor;
818         return;
819     }
820 
821     QQuickItem *oldTop = d->topAnchorItem;
822     d->topAnchorItem = edge.item;
823     d->topAnchorLine = edge.anchorLine;
824     d->remDepend(oldTop);
825     d->addDepend(d->topAnchorItem);
826     emit topChanged();
827     d->updateVerticalAnchors();
828 }
829 
resetTop()830 void QQuickAnchors::resetTop()
831 {
832     Q_D(QQuickAnchors);
833     d->usedAnchors &= ~TopAnchor;
834     d->remDepend(d->topAnchorItem);
835     d->topAnchorItem = nullptr;
836     d->topAnchorLine = QQuickAnchors::InvalidAnchor;
837     emit topChanged();
838     d->updateVerticalAnchors();
839 }
840 
bottom() const841 QQuickAnchorLine QQuickAnchors::bottom() const
842 {
843     Q_D(const QQuickAnchors);
844     return QQuickAnchorLine(d->bottomAnchorItem, d->bottomAnchorLine);
845 }
846 
setBottom(const QQuickAnchorLine & edge)847 void QQuickAnchors::setBottom(const QQuickAnchorLine &edge)
848 {
849     Q_D(QQuickAnchors);
850     if (!d->checkVAnchorValid(edge) ||
851             (d->bottomAnchorItem == edge.item && d->bottomAnchorLine == edge.anchorLine))
852         return;
853 
854     d->usedAnchors |= BottomAnchor;
855 
856     if (!d->checkVValid()) {
857         d->usedAnchors &= ~BottomAnchor;
858         return;
859     }
860 
861     QQuickItem *oldBottom = d->bottomAnchorItem;
862     d->bottomAnchorItem = edge.item;
863     d->bottomAnchorLine = edge.anchorLine;
864     d->remDepend(oldBottom);
865     d->addDepend(d->bottomAnchorItem);
866     emit bottomChanged();
867     d->updateVerticalAnchors();
868 }
869 
resetBottom()870 void QQuickAnchors::resetBottom()
871 {
872     Q_D(QQuickAnchors);
873     d->usedAnchors &= ~BottomAnchor;
874     d->remDepend(d->bottomAnchorItem);
875     d->bottomAnchorItem = nullptr;
876     d->bottomAnchorLine = QQuickAnchors::InvalidAnchor;
877     emit bottomChanged();
878     d->updateVerticalAnchors();
879 }
880 
verticalCenter() const881 QQuickAnchorLine QQuickAnchors::verticalCenter() const
882 {
883     Q_D(const QQuickAnchors);
884     return QQuickAnchorLine(d->vCenterAnchorItem, d->vCenterAnchorLine);
885 }
886 
setVerticalCenter(const QQuickAnchorLine & edge)887 void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge)
888 {
889     Q_D(QQuickAnchors);
890     if (!d->checkVAnchorValid(edge) ||
891             (d->vCenterAnchorItem == edge.item && d->vCenterAnchorLine == edge.anchorLine))
892         return;
893 
894     d->usedAnchors |= VCenterAnchor;
895 
896     if (!d->checkVValid()) {
897         d->usedAnchors &= ~VCenterAnchor;
898         return;
899     }
900 
901     QQuickItem *oldVCenter = d->vCenterAnchorItem;
902     d->vCenterAnchorItem = edge.item;
903     d->vCenterAnchorLine = edge.anchorLine;
904     d->remDepend(oldVCenter);
905     d->addDepend(d->vCenterAnchorItem);
906     emit verticalCenterChanged();
907     d->updateVerticalAnchors();
908 }
909 
resetVerticalCenter()910 void QQuickAnchors::resetVerticalCenter()
911 {
912     Q_D(QQuickAnchors);
913     d->usedAnchors &= ~VCenterAnchor;
914     d->remDepend(d->vCenterAnchorItem);
915     d->vCenterAnchorItem = nullptr;
916     d->vCenterAnchorLine = QQuickAnchors::InvalidAnchor;
917     emit verticalCenterChanged();
918     d->updateVerticalAnchors();
919 }
920 
baseline() const921 QQuickAnchorLine QQuickAnchors::baseline() const
922 {
923     Q_D(const QQuickAnchors);
924     return QQuickAnchorLine(d->baselineAnchorItem, d->baselineAnchorLine);
925 }
926 
setBaseline(const QQuickAnchorLine & edge)927 void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge)
928 {
929     Q_D(QQuickAnchors);
930     if (!d->checkVAnchorValid(edge) ||
931             (d->baselineAnchorItem == edge.item && d->baselineAnchorLine == edge.anchorLine))
932         return;
933 
934     d->usedAnchors |= BaselineAnchor;
935 
936     if (!d->checkVValid()) {
937         d->usedAnchors &= ~BaselineAnchor;
938         return;
939     }
940 
941     QQuickItem *oldBaseline = d->baselineAnchorItem;
942     d->baselineAnchorItem = edge.item;
943     d->baselineAnchorLine = edge.anchorLine;
944     d->remDepend(oldBaseline);
945     d->addDepend(d->baselineAnchorItem);
946     emit baselineChanged();
947     d->updateVerticalAnchors();
948 }
949 
resetBaseline()950 void QQuickAnchors::resetBaseline()
951 {
952     Q_D(QQuickAnchors);
953     d->usedAnchors &= ~BaselineAnchor;
954     d->remDepend(d->baselineAnchorItem);
955     d->baselineAnchorItem = nullptr;
956     d->baselineAnchorLine = QQuickAnchors::InvalidAnchor;
957     emit baselineChanged();
958     d->updateVerticalAnchors();
959 }
960 
left() const961 QQuickAnchorLine QQuickAnchors::left() const
962 {
963     Q_D(const QQuickAnchors);
964     return QQuickAnchorLine(d->leftAnchorItem, d->leftAnchorLine);
965 }
966 
setLeft(const QQuickAnchorLine & edge)967 void QQuickAnchors::setLeft(const QQuickAnchorLine &edge)
968 {
969     Q_D(QQuickAnchors);
970     if (!d->checkHAnchorValid(edge) ||
971             (d->leftAnchorItem == edge.item && d->leftAnchorLine == edge.anchorLine))
972         return;
973 
974     d->usedAnchors |= LeftAnchor;
975 
976     if (!d->checkHValid()) {
977         d->usedAnchors &= ~LeftAnchor;
978         return;
979     }
980 
981     QQuickItem *oldLeft = d->leftAnchorItem;
982     d->leftAnchorItem = edge.item;
983     d->leftAnchorLine = edge.anchorLine;
984     d->remDepend(oldLeft);
985     d->addDepend(d->leftAnchorItem);
986     emit leftChanged();
987     d->updateHorizontalAnchors();
988 }
989 
resetLeft()990 void QQuickAnchors::resetLeft()
991 {
992     Q_D(QQuickAnchors);
993     d->usedAnchors &= ~LeftAnchor;
994     d->remDepend(d->leftAnchorItem);
995     d->leftAnchorItem = nullptr;
996     d->leftAnchorLine = QQuickAnchors::InvalidAnchor;
997     emit leftChanged();
998     d->updateHorizontalAnchors();
999 }
1000 
right() const1001 QQuickAnchorLine QQuickAnchors::right() const
1002 {
1003     Q_D(const QQuickAnchors);
1004     return QQuickAnchorLine(d->rightAnchorItem, d->rightAnchorLine);
1005 }
1006 
setRight(const QQuickAnchorLine & edge)1007 void QQuickAnchors::setRight(const QQuickAnchorLine &edge)
1008 {
1009     Q_D(QQuickAnchors);
1010     if (!d->checkHAnchorValid(edge) ||
1011             (d->rightAnchorItem == edge.item && d->rightAnchorLine == edge.anchorLine))
1012         return;
1013 
1014     d->usedAnchors |= RightAnchor;
1015 
1016     if (!d->checkHValid()) {
1017         d->usedAnchors &= ~RightAnchor;
1018         return;
1019     }
1020 
1021     QQuickItem *oldRight = d->rightAnchorItem;
1022     d->rightAnchorItem = edge.item;
1023     d->rightAnchorLine = edge.anchorLine;
1024     d->remDepend(oldRight);
1025     d->addDepend(d->rightAnchorItem);
1026     emit rightChanged();
1027     d->updateHorizontalAnchors();
1028 }
1029 
resetRight()1030 void QQuickAnchors::resetRight()
1031 {
1032     Q_D(QQuickAnchors);
1033     d->usedAnchors &= ~RightAnchor;
1034     d->remDepend(d->rightAnchorItem);
1035     d->rightAnchorItem = nullptr;
1036     d->rightAnchorLine = QQuickAnchors::InvalidAnchor;
1037     emit rightChanged();
1038     d->updateHorizontalAnchors();
1039 }
1040 
horizontalCenter() const1041 QQuickAnchorLine QQuickAnchors::horizontalCenter() const
1042 {
1043     Q_D(const QQuickAnchors);
1044     return QQuickAnchorLine(d->hCenterAnchorItem, d->hCenterAnchorLine);
1045 }
1046 
setHorizontalCenter(const QQuickAnchorLine & edge)1047 void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge)
1048 {
1049     Q_D(QQuickAnchors);
1050     if (!d->checkHAnchorValid(edge) ||
1051             (d->hCenterAnchorItem == edge.item && d->hCenterAnchorLine == edge.anchorLine))
1052         return;
1053 
1054     d->usedAnchors |= HCenterAnchor;
1055 
1056     if (!d->checkHValid()) {
1057         d->usedAnchors &= ~HCenterAnchor;
1058         return;
1059     }
1060 
1061     QQuickItem *oldHCenter = d->hCenterAnchorItem;
1062     d->hCenterAnchorItem = edge.item;
1063     d->hCenterAnchorLine = edge.anchorLine;
1064     d->remDepend(oldHCenter);
1065     d->addDepend(d->hCenterAnchorItem);
1066     emit horizontalCenterChanged();
1067     d->updateHorizontalAnchors();
1068 }
1069 
resetHorizontalCenter()1070 void QQuickAnchors::resetHorizontalCenter()
1071 {
1072     Q_D(QQuickAnchors);
1073     d->usedAnchors &= ~HCenterAnchor;
1074     d->remDepend(d->hCenterAnchorItem);
1075     d->hCenterAnchorItem = nullptr;
1076     d->hCenterAnchorLine = QQuickAnchors::InvalidAnchor;
1077     emit horizontalCenterChanged();
1078     d->updateHorizontalAnchors();
1079 }
1080 
leftMargin() const1081 qreal QQuickAnchors::leftMargin() const
1082 {
1083     Q_D(const QQuickAnchors);
1084     return d->leftMargin;
1085 }
1086 
setLeftMargin(qreal offset)1087 void QQuickAnchors::setLeftMargin(qreal offset)
1088 {
1089     Q_D(QQuickAnchors);
1090     d->leftMarginExplicit = true;
1091     if (d->leftMargin == offset)
1092         return;
1093     d->leftMargin = offset;
1094     if (d->fill)
1095         d->fillChanged();
1096     else
1097         d->updateHorizontalAnchors();
1098     emit leftMarginChanged();
1099 }
1100 
resetLeftMargin()1101 void QQuickAnchors::resetLeftMargin()
1102 {
1103     Q_D(QQuickAnchors);
1104     d->leftMarginExplicit = false;
1105     if (d->leftMargin == d->margins)
1106         return;
1107     d->leftMargin = d->margins;
1108     if (d->fill)
1109         d->fillChanged();
1110     else
1111         d->updateHorizontalAnchors();
1112     emit leftMarginChanged();
1113 }
1114 
rightMargin() const1115 qreal QQuickAnchors::rightMargin() const
1116 {
1117     Q_D(const QQuickAnchors);
1118     return d->rightMargin;
1119 }
1120 
setRightMargin(qreal offset)1121 void QQuickAnchors::setRightMargin(qreal offset)
1122 {
1123     Q_D(QQuickAnchors);
1124     d->rightMarginExplicit = true;
1125     if (d->rightMargin == offset)
1126         return;
1127     d->rightMargin = offset;
1128     if (d->fill)
1129         d->fillChanged();
1130     else
1131         d->updateHorizontalAnchors();
1132     emit rightMarginChanged();
1133 }
1134 
resetRightMargin()1135 void QQuickAnchors::resetRightMargin()
1136 {
1137     Q_D(QQuickAnchors);
1138     d->rightMarginExplicit = false;
1139     if (d->rightMargin == d->margins)
1140         return;
1141     d->rightMargin = d->margins;
1142     if (d->fill)
1143         d->fillChanged();
1144     else
1145         d->updateHorizontalAnchors();
1146     emit rightMarginChanged();
1147 }
1148 
margins() const1149 qreal QQuickAnchors::margins() const
1150 {
1151     Q_D(const QQuickAnchors);
1152     return d->margins;
1153 }
1154 
setMargins(qreal offset)1155 void QQuickAnchors::setMargins(qreal offset)
1156 {
1157     Q_D(QQuickAnchors);
1158     if (d->margins == offset)
1159         return;
1160     d->margins = offset;
1161 
1162     bool updateHorizontal = false;
1163     bool updateVertical = false;
1164 
1165     if (!d->rightMarginExplicit && d->rightMargin != offset) {
1166         d->rightMargin = offset;
1167         updateHorizontal = true;
1168         emit rightMarginChanged();
1169     }
1170     if (!d->leftMarginExplicit && d->leftMargin != offset) {
1171         d->leftMargin = offset;
1172         updateHorizontal = true;
1173         emit leftMarginChanged();
1174     }
1175     if (!d->topMarginExplicit && d->topMargin != offset) {
1176         d->topMargin = offset;
1177         updateVertical = true;
1178         emit topMarginChanged();
1179     }
1180     if (!d->bottomMarginExplicit && d->bottomMargin != offset) {
1181         d->bottomMargin = offset;
1182         updateVertical = true;
1183         emit bottomMarginChanged();
1184     }
1185 
1186     if (d->fill) {
1187         if (updateHorizontal || updateVertical)
1188             d->fillChanged();
1189     } else {
1190         if (updateHorizontal)
1191             d->updateHorizontalAnchors();
1192         if (updateVertical)
1193             d->updateVerticalAnchors();
1194     }
1195 
1196     emit marginsChanged();
1197 }
1198 
horizontalCenterOffset() const1199 qreal QQuickAnchors::horizontalCenterOffset() const
1200 {
1201     Q_D(const QQuickAnchors);
1202     return d->hCenterOffset;
1203 }
1204 
setHorizontalCenterOffset(qreal offset)1205 void QQuickAnchors::setHorizontalCenterOffset(qreal offset)
1206 {
1207     Q_D(QQuickAnchors);
1208     if (d->hCenterOffset == offset)
1209         return;
1210     d->hCenterOffset = offset;
1211     if (d->centerIn)
1212         d->centerInChanged();
1213     else
1214         d->updateHorizontalAnchors();
1215     emit horizontalCenterOffsetChanged();
1216 }
1217 
topMargin() const1218 qreal QQuickAnchors::topMargin() const
1219 {
1220     Q_D(const QQuickAnchors);
1221     return d->topMargin;
1222 }
1223 
setTopMargin(qreal offset)1224 void QQuickAnchors::setTopMargin(qreal offset)
1225 {
1226     Q_D(QQuickAnchors);
1227     d->topMarginExplicit = true;
1228     if (d->topMargin == offset)
1229         return;
1230     d->topMargin = offset;
1231     if (d->fill)
1232         d->fillChanged();
1233     else
1234         d->updateVerticalAnchors();
1235     emit topMarginChanged();
1236 }
1237 
resetTopMargin()1238 void QQuickAnchors::resetTopMargin()
1239 {
1240     Q_D(QQuickAnchors);
1241     d->topMarginExplicit = false;
1242     if (d->topMargin == d->margins)
1243         return;
1244     d->topMargin = d->margins;
1245     if (d->fill)
1246         d->fillChanged();
1247     else
1248         d->updateVerticalAnchors();
1249     emit topMarginChanged();
1250 }
1251 
bottomMargin() const1252 qreal QQuickAnchors::bottomMargin() const
1253 {
1254     Q_D(const QQuickAnchors);
1255     return d->bottomMargin;
1256 }
1257 
setBottomMargin(qreal offset)1258 void QQuickAnchors::setBottomMargin(qreal offset)
1259 {
1260     Q_D(QQuickAnchors);
1261     d->bottomMarginExplicit = true;
1262     if (d->bottomMargin == offset)
1263         return;
1264     d->bottomMargin = offset;
1265     if (d->fill)
1266         d->fillChanged();
1267     else
1268         d->updateVerticalAnchors();
1269     emit bottomMarginChanged();
1270 }
1271 
resetBottomMargin()1272 void QQuickAnchors::resetBottomMargin()
1273 {
1274     Q_D(QQuickAnchors);
1275     d->bottomMarginExplicit = false;
1276     if (d->bottomMargin == d->margins)
1277         return;
1278     d->bottomMargin = d->margins;
1279     if (d->fill)
1280         d->fillChanged();
1281     else
1282         d->updateVerticalAnchors();
1283     emit bottomMarginChanged();
1284 }
1285 
verticalCenterOffset() const1286 qreal QQuickAnchors::verticalCenterOffset() const
1287 {
1288     Q_D(const QQuickAnchors);
1289     return d->vCenterOffset;
1290 }
1291 
setVerticalCenterOffset(qreal offset)1292 void QQuickAnchors::setVerticalCenterOffset(qreal offset)
1293 {
1294     Q_D(QQuickAnchors);
1295     if (d->vCenterOffset == offset)
1296         return;
1297     d->vCenterOffset = offset;
1298     if (d->centerIn)
1299         d->centerInChanged();
1300     else
1301         d->updateVerticalAnchors();
1302     emit verticalCenterOffsetChanged();
1303 }
1304 
baselineOffset() const1305 qreal QQuickAnchors::baselineOffset() const
1306 {
1307     Q_D(const QQuickAnchors);
1308     return d->baselineOffset;
1309 }
1310 
setBaselineOffset(qreal offset)1311 void QQuickAnchors::setBaselineOffset(qreal offset)
1312 {
1313     Q_D(QQuickAnchors);
1314     if (d->baselineOffset == offset)
1315         return;
1316     d->baselineOffset = offset;
1317     d->updateVerticalAnchors();
1318     emit baselineOffsetChanged();
1319 }
1320 
usedAnchors() const1321 QQuickAnchors::Anchors QQuickAnchors::usedAnchors() const
1322 {
1323     Q_D(const QQuickAnchors);
1324     return static_cast<QQuickAnchors::Anchors>(d->usedAnchors);
1325 }
1326 
activeDirections() const1327 Qt::Orientations QQuickAnchors::activeDirections() const
1328 {
1329     Q_D(const QQuickAnchors);
1330     if (d->fill || d->centerIn)
1331         return Qt::Horizontal | Qt::Vertical;
1332     Qt::Orientations o;
1333     if (d->usedAnchors & QQuickAnchors::Horizontal_Mask)
1334         o |= Qt::Horizontal;
1335     if (d->usedAnchors & QQuickAnchors::Vertical_Mask)
1336         o |= Qt::Vertical;
1337     return o;
1338 }
1339 
checkHValid() const1340 bool QQuickAnchorsPrivate::checkHValid() const
1341 {
1342     if (usedAnchors & QQuickAnchors::LeftAnchor &&
1343         usedAnchors & QQuickAnchors::RightAnchor &&
1344         usedAnchors & QQuickAnchors::HCenterAnchor) {
1345         qmlWarning(item) << QQuickAnchors::tr("Cannot specify left, right, and horizontalCenter anchors at the same time.");
1346         return false;
1347     }
1348 
1349     return true;
1350 }
1351 
checkHAnchorValid(QQuickAnchorLine anchor) const1352 bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const
1353 {
1354     if (!anchor.item) {
1355         qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
1356         return false;
1357     } else if (anchor.anchorLine & QQuickAnchors::Vertical_Mask) {
1358         qmlWarning(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
1359         return false;
1360     } else if (anchor.item != readParentItem(item)
1361                && readParentItem(anchor.item) != readParentItem(item)) {
1362         qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1363         return false;
1364     } else if (anchor.item == item) {
1365         qmlWarning(item) << QQuickAnchors::tr("Cannot anchor item to self.");
1366         return false;
1367     }
1368 
1369     return true;
1370 }
1371 
checkVValid() const1372 bool QQuickAnchorsPrivate::checkVValid() const
1373 {
1374     if (usedAnchors & QQuickAnchors::TopAnchor &&
1375         usedAnchors & QQuickAnchors::BottomAnchor &&
1376         usedAnchors & QQuickAnchors::VCenterAnchor) {
1377         qmlWarning(item) << QQuickAnchors::tr("Cannot specify top, bottom, and verticalCenter anchors at the same time.");
1378         return false;
1379     } else if (usedAnchors & QQuickAnchors::BaselineAnchor &&
1380                (usedAnchors & QQuickAnchors::TopAnchor ||
1381                 usedAnchors & QQuickAnchors::BottomAnchor ||
1382                 usedAnchors & QQuickAnchors::VCenterAnchor)) {
1383         qmlWarning(item) << QQuickAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors.");
1384         return false;
1385     }
1386 
1387     return true;
1388 }
1389 
checkVAnchorValid(QQuickAnchorLine anchor) const1390 bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const
1391 {
1392     if (!anchor.item) {
1393         qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
1394         return false;
1395     } else if (anchor.anchorLine & QQuickAnchors::Horizontal_Mask) {
1396         qmlWarning(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
1397         return false;
1398     } else if (anchor.item != readParentItem(item)
1399                && readParentItem(anchor.item) != readParentItem(item)) {
1400         qmlWarning(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1401         return false;
1402     } else if (anchor.item == item){
1403         qmlWarning(item) << QQuickAnchors::tr("Cannot anchor item to self.");
1404         return false;
1405     }
1406 
1407     return true;
1408 }
1409 
1410 QT_END_NAMESPACE
1411 
1412 #include <moc_qquickanchors_p.cpp>
1413 
1414