1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qquickanchors_p_p.h"
44 #include "qquickitem.h"
45 #include "qquickitem_p.h"
51 //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
52 //TODO: support non-parent, non-sibling (need to find lowest common ancestor)
54 static inline qreal hcenter(QQuickItem *item)
56 qreal width = item->width();
57 if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
58 if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
63 return (width + 1) / 2;
68 static inline qreal vcenter(QQuickItem *item)
70 qreal height = item->height();
71 if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
72 if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
77 return (height + 1) / 2;
84 static qreal position(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine)
88 case QQuickAnchorLine::Left:
91 case QQuickAnchorLine::Right:
92 ret = item->x() + item->width();
94 case QQuickAnchorLine::Top:
97 case QQuickAnchorLine::Bottom:
98 ret = item->y() + item->height();
100 case QQuickAnchorLine::HCenter:
101 ret = item->x() + hcenter(item);
103 case QQuickAnchorLine::VCenter:
104 ret = item->y() + vcenter(item);
106 case QQuickAnchorLine::Baseline:
107 ret = item->y() + item->baselineOffset();
116 //position when origin is 0,0
117 static qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine)
120 switch (anchorLine) {
121 case QQuickAnchorLine::Left:
124 case QQuickAnchorLine::Right:
127 case QQuickAnchorLine::Top:
130 case QQuickAnchorLine::Bottom:
131 ret = item->height();
133 case QQuickAnchorLine::HCenter:
136 case QQuickAnchorLine::VCenter:
139 case QQuickAnchorLine::Baseline:
140 ret = item->baselineOffset();
149 QQuickAnchors::QQuickAnchors(QQuickItem *item, QObject *parent)
150 : QObject(*new QQuickAnchorsPrivate(item), parent)
154 QQuickAnchors::~QQuickAnchors()
157 d->inDestructor = true;
158 d->remDepend(d->fill);
159 d->remDepend(d->centerIn);
160 d->remDepend(d->left.item);
161 d->remDepend(d->right.item);
162 d->remDepend(d->top.item);
163 d->remDepend(d->bottom.item);
164 d->remDepend(d->vCenter.item);
165 d->remDepend(d->hCenter.item);
166 d->remDepend(d->baseline.item);
169 void QQuickAnchorsPrivate::fillChanged()
172 if (!fill || !isItemComplete())
175 if (updatingFill < 2) {
178 qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
180 if (fill == item->parentItem()) { //child-parent
181 setItemPos(QPointF(horizontalMargin, topMargin));
182 } else if (fill->parentItem() == item->parentItem()) { //siblings
183 setItemPos(QPointF(fill->x()+horizontalMargin, fill->y()+topMargin));
185 setItemSize(QSizeF(fill->width()-leftMargin-rightMargin, fill->height()-topMargin-bottomMargin));
189 // ### Make this certain :)
190 qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on fill.");
195 void QQuickAnchorsPrivate::centerInChanged()
198 if (!centerIn || fill || !isItemComplete())
201 if (updatingCenterIn < 2) {
204 qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
205 if (centerIn == item->parentItem()) {
206 QPointF p(hcenter(item->parentItem()) - hcenter(item) + effectiveHCenterOffset,
207 vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
210 } else if (centerIn->parentItem() == item->parentItem()) {
211 QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset,
212 centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
218 // ### Make this certain :)
219 qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on centerIn.");
223 void QQuickAnchorsPrivate::clearItem(QQuickItem *item)
229 if (centerIn == item)
231 if (left.item == item) {
233 usedAnchors &= ~QQuickAnchors::LeftAnchor;
235 if (right.item == item) {
237 usedAnchors &= ~QQuickAnchors::RightAnchor;
239 if (top.item == item) {
241 usedAnchors &= ~QQuickAnchors::TopAnchor;
243 if (bottom.item == item) {
245 usedAnchors &= ~QQuickAnchors::BottomAnchor;
247 if (vCenter.item == item) {
249 usedAnchors &= ~QQuickAnchors::VCenterAnchor;
251 if (hCenter.item == item) {
253 usedAnchors &= ~QQuickAnchors::HCenterAnchor;
255 if (baseline.item == item) {
257 usedAnchors &= ~QQuickAnchors::BaselineAnchor;
261 int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem)
263 QQuickItemPrivate::GeometryChangeTypes dependency = QQuickItemPrivate::NoChange;
265 if (!controlItem || inDestructor)
268 if (fill == controlItem) {
269 if (controlItem == item->parentItem())
270 dependency |= QQuickItemPrivate::SizeChange;
272 dependency |= QQuickItemPrivate::GeometryChange;
273 return dependency; //exit early
276 if (centerIn == controlItem) {
277 if (controlItem == item->parentItem())
278 dependency |= QQuickItemPrivate::SizeChange;
280 dependency |= QQuickItemPrivate::GeometryChange;
281 return dependency; //exit early
284 if ((usedAnchors & QQuickAnchors::LeftAnchor && left.item == controlItem) ||
285 (usedAnchors & QQuickAnchors::RightAnchor && right.item == controlItem) ||
286 (usedAnchors & QQuickAnchors::HCenterAnchor && hCenter.item == controlItem)) {
287 if (controlItem == item->parentItem())
288 dependency |= QQuickItemPrivate::WidthChange;
290 dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::XChange | QQuickItemPrivate::WidthChange);
293 if ((usedAnchors & QQuickAnchors::TopAnchor && top.item == controlItem) ||
294 (usedAnchors & QQuickAnchors::BottomAnchor && bottom.item == controlItem) ||
295 (usedAnchors & QQuickAnchors::VCenterAnchor && vCenter.item == controlItem) ||
296 (usedAnchors & QQuickAnchors::BaselineAnchor && baseline.item == controlItem)) {
297 if (controlItem == item->parentItem())
298 dependency |= QQuickItemPrivate::HeightChange;
300 dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::YChange | QQuickItemPrivate::HeightChange);
306 void QQuickAnchorsPrivate::addDepend(QQuickItem *item)
308 if (!item || !componentComplete)
311 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
312 p->updateOrAddGeometryChangeListener(this, QFlags<QQuickItemPrivate::GeometryChangeType>(calculateDependency(item)));
315 void QQuickAnchorsPrivate::remDepend(QQuickItem *item)
317 if (!item || !componentComplete)
320 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
321 p->updateOrRemoveGeometryChangeListener(this, QFlags<QQuickItemPrivate::GeometryChangeType>(calculateDependency(item)));
324 bool QQuickAnchors::mirrored()
327 return QQuickItemPrivate::get(d->item)->effectiveLayoutMirror;
330 bool QQuickAnchors::alignWhenCentered() const
332 Q_D(const QQuickAnchors);
333 return d->centerAligned;
336 void QQuickAnchors::setAlignWhenCentered(bool aligned)
339 if (aligned == d->centerAligned)
341 d->centerAligned = aligned;
342 emit centerAlignedChanged();
344 d->centerInChanged();
346 if (d->usedAnchors & QQuickAnchors::VCenterAnchor)
347 d->updateVerticalAnchors();
348 else if (d->usedAnchors & QQuickAnchors::HCenterAnchor)
349 d->updateHorizontalAnchors();
353 bool QQuickAnchorsPrivate::isItemComplete() const
355 return componentComplete;
358 void QQuickAnchors::classBegin()
361 d->componentComplete = false;
364 void QQuickAnchors::componentComplete()
367 d->componentComplete = true;
370 void QQuickAnchorsPrivate::setItemHeight(qreal v)
377 void QQuickAnchorsPrivate::setItemWidth(qreal v)
384 void QQuickAnchorsPrivate::setItemX(qreal v)
391 void QQuickAnchorsPrivate::setItemY(qreal v)
398 void QQuickAnchorsPrivate::setItemPos(const QPointF &v)
401 item->setPosition(v);
405 void QQuickAnchorsPrivate::setItemSize(const QSizeF &v)
412 void QQuickAnchorsPrivate::updateMe()
422 void QQuickAnchorsPrivate::updateOnComplete()
424 //optimization to only set initial dependencies once, at completion time
425 QSet<QQuickItem *> dependencies;
426 dependencies << fill << centerIn
427 << left.item << right.item << hCenter.item
428 << top.item << bottom.item << vCenter.item << baseline.item;
430 foreach (QQuickItem *dependency, dependencies)
431 addDepend(dependency);
437 void QQuickAnchorsPrivate::update()
441 if (usedAnchors & QQuickAnchorLine::Horizontal_Mask)
442 updateHorizontalAnchors();
443 if (usedAnchors & QQuickAnchorLine::Vertical_Mask)
444 updateVerticalAnchors();
447 void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newG, const QRectF &oldG)
451 if ((usedAnchors & QQuickAnchorLine::Horizontal_Mask) && (newG.x() != oldG.x() || newG.width() != oldG.width()))
452 updateHorizontalAnchors();
453 if ((usedAnchors & QQuickAnchorLine::Vertical_Mask) && (newG.y() != oldG.y() || newG.height() != oldG.height()))
454 updateVerticalAnchors();
457 QQuickItem *QQuickAnchors::fill() const
459 Q_D(const QQuickAnchors);
463 void QQuickAnchors::setFill(QQuickItem *f)
470 QQuickItem *oldFill = d->fill;
472 d->remDepend(oldFill);
476 if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){
477 qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
480 QQuickItem *oldFill = d->fill;
482 d->remDepend(oldFill);
483 d->addDepend(d->fill);
488 void QQuickAnchors::resetFill()
493 QQuickItem *QQuickAnchors::centerIn() const
495 Q_D(const QQuickAnchors);
499 void QQuickAnchors::setCenterIn(QQuickItem* c)
502 if (d->centerIn == c)
506 QQuickItem *oldCI = d->centerIn;
509 emit centerInChanged();
512 if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){
513 qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
516 QQuickItem *oldCI = d->centerIn;
519 d->addDepend(d->centerIn);
520 emit centerInChanged();
521 d->centerInChanged();
524 void QQuickAnchors::resetCenterIn()
529 bool QQuickAnchorsPrivate::calcStretch(const QQuickAnchorLine &edge1,
530 const QQuickAnchorLine &edge2,
533 QQuickAnchorLine::AnchorLine line,
536 bool edge1IsParent = (edge1.item == item->parentItem());
537 bool edge2IsParent = (edge2.item == item->parentItem());
538 bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
539 bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
541 bool invalid = false;
542 if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
543 stretch = (position(edge2.item, edge2.anchorLine) + offset2)
544 - (position(edge1.item, edge1.anchorLine) + offset1);
545 } else if (edge2IsParent && edge1IsSibling) {
546 stretch = (position(edge2.item, edge2.anchorLine) + offset2)
547 - (position(item->parentItem(), line)
548 + position(edge1.item, edge1.anchorLine) + offset1);
549 } else if (edge2IsSibling && edge1IsParent) {
550 stretch = (position(item->parentItem(), line) + position(edge2.item, edge2.anchorLine) + offset2)
551 - (position(edge1.item, edge1.anchorLine) + offset1);
558 void QQuickAnchorsPrivate::updateVerticalAnchors()
560 if (fill || centerIn || !isItemComplete())
563 if (updatingVerticalAnchor < 2) {
564 ++updatingVerticalAnchor;
565 if (usedAnchors & QQuickAnchors::TopAnchor) {
569 if (usedAnchors & QQuickAnchors::BottomAnchor) {
570 invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QQuickAnchorLine::Top, height);
571 } else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
572 invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QQuickAnchorLine::Top, height);
576 setItemHeight(height);
579 if (top.item == item->parentItem()) {
580 setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
581 } else if (top.item->parentItem() == item->parentItem()) {
582 setItemY(position(top.item, top.anchorLine) + topMargin);
584 } else if (usedAnchors & QQuickAnchors::BottomAnchor) {
585 //Handle stretching (top + bottom case is handled above)
586 if (usedAnchors & QQuickAnchors::VCenterAnchor) {
588 bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
589 QQuickAnchorLine::Top, height);
591 setItemHeight(height*2);
595 if (bottom.item == item->parentItem()) {
596 setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
597 } else if (bottom.item->parentItem() == item->parentItem()) {
598 setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
600 } else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
601 //(stetching handled above)
604 if (vCenter.item == item->parentItem()) {
605 setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
606 - vcenter(item) + vCenterOffset);
607 } else if (vCenter.item->parentItem() == item->parentItem()) {
608 setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset);
610 } else if (usedAnchors & QQuickAnchors::BaselineAnchor) {
612 if (baseline.item == item->parentItem()) {
613 setItemY(adjustedPosition(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset);
614 } else if (baseline.item->parentItem() == item->parentItem()) {
615 setItemY(position(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset);
618 --updatingVerticalAnchor;
620 // ### Make this certain :)
621 qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on vertical anchor.");
625 inline QQuickAnchorLine::AnchorLine reverseAnchorLine(QQuickAnchorLine::AnchorLine anchorLine)
627 if (anchorLine == QQuickAnchorLine::Left) {
628 return QQuickAnchorLine::Right;
629 } else if (anchorLine == QQuickAnchorLine::Right) {
630 return QQuickAnchorLine::Left;
636 void QQuickAnchorsPrivate::updateHorizontalAnchors()
639 if (fill || centerIn || !isItemComplete())
642 if (updatingHorizontalAnchor < 3) {
643 ++updatingHorizontalAnchor;
644 qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
645 QQuickAnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter;
646 QQuickAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
648 effectiveLeftAnchor = QQuickAnchors::RightAnchor;
649 effectiveRightAnchor = QQuickAnchors::LeftAnchor;
650 effectiveLeft.item = right.item;
651 effectiveLeft.anchorLine = reverseAnchorLine(right.anchorLine);
652 effectiveRight.item = left.item;
653 effectiveRight.anchorLine = reverseAnchorLine(left.anchorLine);
654 effectiveHorizontalCenter.item = hCenter.item;
655 effectiveHorizontalCenter.anchorLine = reverseAnchorLine(hCenter.anchorLine);
656 effectiveLeftMargin = rightMargin;
657 effectiveRightMargin = leftMargin;
658 effectiveHorizontalCenterOffset = -hCenterOffset;
660 effectiveLeftAnchor = QQuickAnchors::LeftAnchor;
661 effectiveRightAnchor = QQuickAnchors::RightAnchor;
662 effectiveLeft = left;
663 effectiveRight = right;
664 effectiveHorizontalCenter = hCenter;
665 effectiveLeftMargin = leftMargin;
666 effectiveRightMargin = rightMargin;
667 effectiveHorizontalCenterOffset = hCenterOffset;
670 if (usedAnchors & effectiveLeftAnchor) {
674 if (usedAnchors & effectiveRightAnchor) {
675 invalid = calcStretch(effectiveLeft, effectiveRight, effectiveLeftMargin, -effectiveRightMargin, QQuickAnchorLine::Left, width);
676 } else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
677 invalid = calcStretch(effectiveLeft, effectiveHorizontalCenter, effectiveLeftMargin, effectiveHorizontalCenterOffset, QQuickAnchorLine::Left, width);
684 if (effectiveLeft.item == item->parentItem()) {
685 setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
686 } else if (effectiveLeft.item->parentItem() == item->parentItem()) {
687 setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
689 } else if (usedAnchors & effectiveRightAnchor) {
690 //Handle stretching (left + right case is handled in updateLeftAnchor)
691 if (usedAnchors & QQuickAnchors::HCenterAnchor) {
693 bool invalid = calcStretch(effectiveHorizontalCenter, effectiveRight, effectiveHorizontalCenterOffset, -effectiveRightMargin,
694 QQuickAnchorLine::Left, width);
696 setItemWidth(width*2);
700 if (effectiveRight.item == item->parentItem()) {
701 setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin);
702 } else if (effectiveRight.item->parentItem() == item->parentItem()) {
703 setItemX(position(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin);
705 } else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
707 if (effectiveHorizontalCenter.item == item->parentItem()) {
708 setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
709 } else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) {
710 setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
713 --updatingHorizontalAnchor;
715 // ### Make this certain :)
716 qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on horizontal anchor.");
720 QQuickAnchorLine QQuickAnchors::top() const
722 Q_D(const QQuickAnchors);
726 void QQuickAnchors::setTop(const QQuickAnchorLine &edge)
729 if (!d->checkVAnchorValid(edge) || d->top == edge)
732 d->usedAnchors |= TopAnchor;
734 if (!d->checkVValid()) {
735 d->usedAnchors &= ~TopAnchor;
739 QQuickItem *oldTop = d->top.item;
741 d->remDepend(oldTop);
742 d->addDepend(d->top.item);
744 d->updateVerticalAnchors();
747 void QQuickAnchors::resetTop()
750 d->usedAnchors &= ~TopAnchor;
751 d->remDepend(d->top.item);
752 d->top = QQuickAnchorLine();
754 d->updateVerticalAnchors();
757 QQuickAnchorLine QQuickAnchors::bottom() const
759 Q_D(const QQuickAnchors);
763 void QQuickAnchors::setBottom(const QQuickAnchorLine &edge)
766 if (!d->checkVAnchorValid(edge) || d->bottom == edge)
769 d->usedAnchors |= BottomAnchor;
771 if (!d->checkVValid()) {
772 d->usedAnchors &= ~BottomAnchor;
776 QQuickItem *oldBottom = d->bottom.item;
778 d->remDepend(oldBottom);
779 d->addDepend(d->bottom.item);
780 emit bottomChanged();
781 d->updateVerticalAnchors();
784 void QQuickAnchors::resetBottom()
787 d->usedAnchors &= ~BottomAnchor;
788 d->remDepend(d->bottom.item);
789 d->bottom = QQuickAnchorLine();
790 emit bottomChanged();
791 d->updateVerticalAnchors();
794 QQuickAnchorLine QQuickAnchors::verticalCenter() const
796 Q_D(const QQuickAnchors);
800 void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge)
803 if (!d->checkVAnchorValid(edge) || d->vCenter == edge)
806 d->usedAnchors |= VCenterAnchor;
808 if (!d->checkVValid()) {
809 d->usedAnchors &= ~VCenterAnchor;
813 QQuickItem *oldVCenter = d->vCenter.item;
815 d->remDepend(oldVCenter);
816 d->addDepend(d->vCenter.item);
817 emit verticalCenterChanged();
818 d->updateVerticalAnchors();
821 void QQuickAnchors::resetVerticalCenter()
824 d->usedAnchors &= ~VCenterAnchor;
825 d->remDepend(d->vCenter.item);
826 d->vCenter = QQuickAnchorLine();
827 emit verticalCenterChanged();
828 d->updateVerticalAnchors();
831 QQuickAnchorLine QQuickAnchors::baseline() const
833 Q_D(const QQuickAnchors);
837 void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge)
840 if (!d->checkVAnchorValid(edge) || d->baseline == edge)
843 d->usedAnchors |= BaselineAnchor;
845 if (!d->checkVValid()) {
846 d->usedAnchors &= ~BaselineAnchor;
850 QQuickItem *oldBaseline = d->baseline.item;
852 d->remDepend(oldBaseline);
853 d->addDepend(d->baseline.item);
854 emit baselineChanged();
855 d->updateVerticalAnchors();
858 void QQuickAnchors::resetBaseline()
861 d->usedAnchors &= ~BaselineAnchor;
862 d->remDepend(d->baseline.item);
863 d->baseline = QQuickAnchorLine();
864 emit baselineChanged();
865 d->updateVerticalAnchors();
868 QQuickAnchorLine QQuickAnchors::left() const
870 Q_D(const QQuickAnchors);
874 void QQuickAnchors::setLeft(const QQuickAnchorLine &edge)
877 if (!d->checkHAnchorValid(edge) || d->left == edge)
880 d->usedAnchors |= LeftAnchor;
882 if (!d->checkHValid()) {
883 d->usedAnchors &= ~LeftAnchor;
887 QQuickItem *oldLeft = d->left.item;
889 d->remDepend(oldLeft);
890 d->addDepend(d->left.item);
892 d->updateHorizontalAnchors();
895 void QQuickAnchors::resetLeft()
898 d->usedAnchors &= ~LeftAnchor;
899 d->remDepend(d->left.item);
900 d->left = QQuickAnchorLine();
902 d->updateHorizontalAnchors();
905 QQuickAnchorLine QQuickAnchors::right() const
907 Q_D(const QQuickAnchors);
911 void QQuickAnchors::setRight(const QQuickAnchorLine &edge)
914 if (!d->checkHAnchorValid(edge) || d->right == edge)
917 d->usedAnchors |= RightAnchor;
919 if (!d->checkHValid()) {
920 d->usedAnchors &= ~RightAnchor;
924 QQuickItem *oldRight = d->right.item;
926 d->remDepend(oldRight);
927 d->addDepend(d->right.item);
929 d->updateHorizontalAnchors();
932 void QQuickAnchors::resetRight()
935 d->usedAnchors &= ~RightAnchor;
936 d->remDepend(d->right.item);
937 d->right = QQuickAnchorLine();
939 d->updateHorizontalAnchors();
942 QQuickAnchorLine QQuickAnchors::horizontalCenter() const
944 Q_D(const QQuickAnchors);
948 void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge)
951 if (!d->checkHAnchorValid(edge) || d->hCenter == edge)
954 d->usedAnchors |= HCenterAnchor;
956 if (!d->checkHValid()) {
957 d->usedAnchors &= ~HCenterAnchor;
961 QQuickItem *oldHCenter = d->hCenter.item;
963 d->remDepend(oldHCenter);
964 d->addDepend(d->hCenter.item);
965 emit horizontalCenterChanged();
966 d->updateHorizontalAnchors();
969 void QQuickAnchors::resetHorizontalCenter()
972 d->usedAnchors &= ~HCenterAnchor;
973 d->remDepend(d->hCenter.item);
974 d->hCenter = QQuickAnchorLine();
975 emit horizontalCenterChanged();
976 d->updateHorizontalAnchors();
979 qreal QQuickAnchors::leftMargin() const
981 Q_D(const QQuickAnchors);
982 return d->leftMargin;
985 void QQuickAnchors::setLeftMargin(qreal offset)
988 d->leftMarginExplicit = true;
989 if (d->leftMargin == offset)
991 d->leftMargin = offset;
995 d->updateHorizontalAnchors();
996 emit leftMarginChanged();
999 void QQuickAnchors::resetLeftMargin()
1002 d->leftMarginExplicit = false;
1003 if (d->leftMargin == d->margins)
1005 d->leftMargin = d->margins;
1009 d->updateHorizontalAnchors();
1010 emit leftMarginChanged();
1013 qreal QQuickAnchors::rightMargin() const
1015 Q_D(const QQuickAnchors);
1016 return d->rightMargin;
1019 void QQuickAnchors::setRightMargin(qreal offset)
1022 d->rightMarginExplicit = true;
1023 if (d->rightMargin == offset)
1025 d->rightMargin = offset;
1029 d->updateHorizontalAnchors();
1030 emit rightMarginChanged();
1033 void QQuickAnchors::resetRightMargin()
1036 d->rightMarginExplicit = false;
1037 if (d->rightMargin == d->margins)
1039 d->rightMargin = d->margins;
1043 d->updateHorizontalAnchors();
1044 emit rightMarginChanged();
1047 qreal QQuickAnchors::margins() const
1049 Q_D(const QQuickAnchors);
1053 void QQuickAnchors::setMargins(qreal offset)
1056 if (d->margins == offset)
1058 d->margins = offset;
1060 bool updateHorizontal = false;
1061 bool updateVertical = false;
1063 if (!d->rightMarginExplicit && d->rightMargin != offset) {
1064 d->rightMargin = offset;
1065 updateHorizontal = true;
1066 emit rightMarginChanged();
1068 if (!d->leftMarginExplicit && d->leftMargin != offset) {
1069 d->leftMargin = offset;
1070 updateHorizontal = true;
1071 emit leftMarginChanged();
1073 if (!d->topMarginExplicit && d->topMargin != offset) {
1074 d->topMargin = offset;
1075 updateVertical = true;
1076 emit topMarginChanged();
1078 if (!d->bottomMarginExplicit && d->bottomMargin != offset) {
1079 d->bottomMargin = offset;
1080 updateVertical = true;
1081 emit bottomMarginChanged();
1085 if (updateHorizontal || updateVertical)
1088 if (updateHorizontal)
1089 d->updateHorizontalAnchors();
1091 d->updateVerticalAnchors();
1094 emit marginsChanged();
1097 qreal QQuickAnchors::horizontalCenterOffset() const
1099 Q_D(const QQuickAnchors);
1100 return d->hCenterOffset;
1103 void QQuickAnchors::setHorizontalCenterOffset(qreal offset)
1106 if (d->hCenterOffset == offset)
1108 d->hCenterOffset = offset;
1110 d->centerInChanged();
1112 d->updateHorizontalAnchors();
1113 emit horizontalCenterOffsetChanged();
1116 qreal QQuickAnchors::topMargin() const
1118 Q_D(const QQuickAnchors);
1119 return d->topMargin;
1122 void QQuickAnchors::setTopMargin(qreal offset)
1125 d->topMarginExplicit = true;
1126 if (d->topMargin == offset)
1128 d->topMargin = offset;
1132 d->updateVerticalAnchors();
1133 emit topMarginChanged();
1136 void QQuickAnchors::resetTopMargin()
1139 d->topMarginExplicit = false;
1140 if (d->topMargin == d->margins)
1142 d->topMargin = d->margins;
1146 d->updateVerticalAnchors();
1147 emit topMarginChanged();
1150 qreal QQuickAnchors::bottomMargin() const
1152 Q_D(const QQuickAnchors);
1153 return d->bottomMargin;
1156 void QQuickAnchors::setBottomMargin(qreal offset)
1159 d->bottomMarginExplicit = true;
1160 if (d->bottomMargin == offset)
1162 d->bottomMargin = offset;
1166 d->updateVerticalAnchors();
1167 emit bottomMarginChanged();
1170 void QQuickAnchors::resetBottomMargin()
1173 d->bottomMarginExplicit = false;
1174 if (d->bottomMargin == d->margins)
1176 d->bottomMargin = d->margins;
1180 d->updateVerticalAnchors();
1181 emit bottomMarginChanged();
1184 qreal QQuickAnchors::verticalCenterOffset() const
1186 Q_D(const QQuickAnchors);
1187 return d->vCenterOffset;
1190 void QQuickAnchors::setVerticalCenterOffset(qreal offset)
1193 if (d->vCenterOffset == offset)
1195 d->vCenterOffset = offset;
1197 d->centerInChanged();
1199 d->updateVerticalAnchors();
1200 emit verticalCenterOffsetChanged();
1203 qreal QQuickAnchors::baselineOffset() const
1205 Q_D(const QQuickAnchors);
1206 return d->baselineOffset;
1209 void QQuickAnchors::setBaselineOffset(qreal offset)
1212 if (d->baselineOffset == offset)
1214 d->baselineOffset = offset;
1215 d->updateVerticalAnchors();
1216 emit baselineOffsetChanged();
1219 QQuickAnchors::Anchors QQuickAnchors::usedAnchors() const
1221 Q_D(const QQuickAnchors);
1222 return d->usedAnchors;
1225 bool QQuickAnchorsPrivate::checkHValid() const
1227 if (usedAnchors & QQuickAnchors::LeftAnchor &&
1228 usedAnchors & QQuickAnchors::RightAnchor &&
1229 usedAnchors & QQuickAnchors::HCenterAnchor) {
1230 qmlInfo(item) << QQuickAnchors::tr("Cannot specify left, right, and horizontalCenter anchors at the same time.");
1237 bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const
1240 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
1242 } else if (anchor.anchorLine & QQuickAnchorLine::Vertical_Mask) {
1243 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
1245 } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
1246 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1248 } else if (anchor.item == item) {
1249 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor item to self.");
1256 bool QQuickAnchorsPrivate::checkVValid() const
1258 if (usedAnchors & QQuickAnchors::TopAnchor &&
1259 usedAnchors & QQuickAnchors::BottomAnchor &&
1260 usedAnchors & QQuickAnchors::VCenterAnchor) {
1261 qmlInfo(item) << QQuickAnchors::tr("Cannot specify top, bottom, and verticalCenter anchors at the same time.");
1263 } else if (usedAnchors & QQuickAnchors::BaselineAnchor &&
1264 (usedAnchors & QQuickAnchors::TopAnchor ||
1265 usedAnchors & QQuickAnchors::BottomAnchor ||
1266 usedAnchors & QQuickAnchors::VCenterAnchor)) {
1267 qmlInfo(item) << QQuickAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors.");
1274 bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const
1277 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
1279 } else if (anchor.anchorLine & QQuickAnchorLine::Horizontal_Mask) {
1280 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
1282 } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
1283 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1285 } else if (anchor.item == item){
1286 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor item to self.");
1295 #include <moc_qquickanchors_p.cpp>