1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickanchors_p_p.h"
44 #include "qquickitem.h"
45 #include "qquickitem_p.h"
47 #include <qdeclarativeinfo.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 qreal hcenter(QQuickItem *item)
56 qreal width = item->width();
59 return (width + 1) / 2;
64 static qreal vcenter(QQuickItem *item)
66 qreal height = item->height();
69 return (height + 1) / 2;
76 static qreal position(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine)
80 case QQuickAnchorLine::Left:
83 case QQuickAnchorLine::Right:
84 ret = item->x() + item->width();
86 case QQuickAnchorLine::Top:
89 case QQuickAnchorLine::Bottom:
90 ret = item->y() + item->height();
92 case QQuickAnchorLine::HCenter:
93 ret = item->x() + hcenter(item);
95 case QQuickAnchorLine::VCenter:
96 ret = item->y() + vcenter(item);
98 case QQuickAnchorLine::Baseline:
99 ret = item->y() + item->baselineOffset();
108 //position when origin is 0,0
109 static qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine)
112 switch (anchorLine) {
113 case QQuickAnchorLine::Left:
116 case QQuickAnchorLine::Right:
119 case QQuickAnchorLine::Top:
122 case QQuickAnchorLine::Bottom:
123 ret = item->height();
125 case QQuickAnchorLine::HCenter:
128 case QQuickAnchorLine::VCenter:
131 case QQuickAnchorLine::Baseline:
132 ret = item->baselineOffset();
141 QQuickAnchors::QQuickAnchors(QQuickItem *item, QObject *parent)
142 : QObject(*new QQuickAnchorsPrivate(item), parent)
146 QQuickAnchors::~QQuickAnchors()
149 d->inDestructor = true;
150 d->remDepend(d->fill);
151 d->remDepend(d->centerIn);
152 d->remDepend(d->left.item);
153 d->remDepend(d->right.item);
154 d->remDepend(d->top.item);
155 d->remDepend(d->bottom.item);
156 d->remDepend(d->vCenter.item);
157 d->remDepend(d->hCenter.item);
158 d->remDepend(d->baseline.item);
161 void QQuickAnchorsPrivate::fillChanged()
164 if (!fill || !isItemComplete())
167 if (updatingFill < 2) {
170 qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
172 if (fill == item->parentItem()) { //child-parent
173 setItemPos(QPointF(horizontalMargin, topMargin));
174 } else if (fill->parentItem() == item->parentItem()) { //siblings
175 setItemPos(QPointF(fill->x()+horizontalMargin, fill->y()+topMargin));
177 setItemSize(QSizeF(fill->width()-leftMargin-rightMargin, fill->height()-topMargin-bottomMargin));
181 // ### Make this certain :)
182 qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on fill.");
187 void QQuickAnchorsPrivate::centerInChanged()
190 if (!centerIn || fill || !isItemComplete())
193 if (updatingCenterIn < 2) {
196 qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
197 if (centerIn == item->parentItem()) {
198 QPointF p(hcenter(item->parentItem()) - hcenter(item) + effectiveHCenterOffset,
199 vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
202 } else if (centerIn->parentItem() == item->parentItem()) {
203 QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset,
204 centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
210 // ### Make this certain :)
211 qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on centerIn.");
215 void QQuickAnchorsPrivate::clearItem(QQuickItem *item)
221 if (centerIn == item)
223 if (left.item == item) {
225 usedAnchors &= ~QQuickAnchors::LeftAnchor;
227 if (right.item == item) {
229 usedAnchors &= ~QQuickAnchors::RightAnchor;
231 if (top.item == item) {
233 usedAnchors &= ~QQuickAnchors::TopAnchor;
235 if (bottom.item == item) {
237 usedAnchors &= ~QQuickAnchors::BottomAnchor;
239 if (vCenter.item == item) {
241 usedAnchors &= ~QQuickAnchors::VCenterAnchor;
243 if (hCenter.item == item) {
245 usedAnchors &= ~QQuickAnchors::HCenterAnchor;
247 if (baseline.item == item) {
249 usedAnchors &= ~QQuickAnchors::BaselineAnchor;
253 int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem)
255 QQuickItemPrivate::GeometryChangeTypes dependency = QQuickItemPrivate::NoChange;
257 if (!controlItem || inDestructor)
260 if (fill == controlItem) {
261 if ((controlItem == item->parentItem()))
262 dependency |= QQuickItemPrivate::SizeChange;
264 dependency |= QQuickItemPrivate::GeometryChange;
265 return dependency; //exit early
268 if (centerIn == controlItem) {
269 if ((controlItem == item->parentItem()))
270 dependency |= QQuickItemPrivate::SizeChange;
272 dependency |= QQuickItemPrivate::GeometryChange;
273 return dependency; //exit early
276 if ((usedAnchors & QQuickAnchors::LeftAnchor && left.item == controlItem) ||
277 (usedAnchors & QQuickAnchors::RightAnchor && right.item == controlItem) ||
278 (usedAnchors & QQuickAnchors::HCenterAnchor && hCenter.item == controlItem)) {
279 if ((controlItem == item->parentItem()))
280 dependency |= QQuickItemPrivate::WidthChange;
282 dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::XChange | QQuickItemPrivate::WidthChange);
285 if ((usedAnchors & QQuickAnchors::TopAnchor && top.item == controlItem) ||
286 (usedAnchors & QQuickAnchors::BottomAnchor && bottom.item == controlItem) ||
287 (usedAnchors & QQuickAnchors::VCenterAnchor && vCenter.item == controlItem) ||
288 (usedAnchors & QQuickAnchors::BaselineAnchor && baseline.item == controlItem)) {
289 if ((controlItem == item->parentItem()))
290 dependency |= QQuickItemPrivate::HeightChange;
292 dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::YChange | QQuickItemPrivate::HeightChange);
298 void QQuickAnchorsPrivate::addDepend(QQuickItem *item)
300 if (!item || !componentComplete)
303 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
304 p->updateOrAddGeometryChangeListener(this, QFlags<QQuickItemPrivate::GeometryChangeType>(calculateDependency(item)));
307 void QQuickAnchorsPrivate::remDepend(QQuickItem *item)
309 if (!item || !componentComplete)
312 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
313 p->updateOrRemoveGeometryChangeListener(this, QFlags<QQuickItemPrivate::GeometryChangeType>(calculateDependency(item)));
316 bool QQuickAnchors::mirrored()
319 return QQuickItemPrivate::get(d->item)->effectiveLayoutMirror;
322 bool QQuickAnchorsPrivate::isItemComplete() const
324 return componentComplete;
327 void QQuickAnchors::classBegin()
330 d->componentComplete = false;
333 void QQuickAnchors::componentComplete()
336 d->componentComplete = true;
339 void QQuickAnchorsPrivate::setItemHeight(qreal v)
346 void QQuickAnchorsPrivate::setItemWidth(qreal v)
353 void QQuickAnchorsPrivate::setItemX(qreal v)
360 void QQuickAnchorsPrivate::setItemY(qreal v)
367 void QQuickAnchorsPrivate::setItemPos(const QPointF &v)
374 void QQuickAnchorsPrivate::setItemSize(const QSizeF &v)
381 void QQuickAnchorsPrivate::updateMe()
391 void QQuickAnchorsPrivate::updateOnComplete()
393 //optimization to only set initial dependencies once, at completion time
394 QSet<QQuickItem *> dependencies;
395 dependencies << fill << centerIn
396 << left.item << right.item << hCenter.item
397 << top.item << bottom.item << vCenter.item << baseline.item;
399 foreach (QQuickItem *dependency, dependencies)
400 addDepend(dependency);
406 void QQuickAnchorsPrivate::update()
410 if (usedAnchors & QQuickAnchorLine::Horizontal_Mask)
411 updateHorizontalAnchors();
412 if (usedAnchors & QQuickAnchorLine::Vertical_Mask)
413 updateVerticalAnchors();
416 void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newG, const QRectF &oldG)
420 if ((usedAnchors & QQuickAnchorLine::Horizontal_Mask) && (newG.x() != oldG.x() || newG.width() != oldG.width()))
421 updateHorizontalAnchors();
422 if ((usedAnchors & QQuickAnchorLine::Vertical_Mask) && (newG.y() != oldG.y() || newG.height() != oldG.height()))
423 updateVerticalAnchors();
426 QQuickItem *QQuickAnchors::fill() const
428 Q_D(const QQuickAnchors);
432 void QQuickAnchors::setFill(QQuickItem *f)
439 QQuickItem *oldFill = d->fill;
441 d->remDepend(oldFill);
445 if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){
446 qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
449 QQuickItem *oldFill = d->fill;
451 d->remDepend(oldFill);
452 d->addDepend(d->fill);
457 void QQuickAnchors::resetFill()
462 QQuickItem *QQuickAnchors::centerIn() const
464 Q_D(const QQuickAnchors);
468 void QQuickAnchors::setCenterIn(QQuickItem* c)
471 if (d->centerIn == c)
475 QQuickItem *oldCI = d->centerIn;
478 emit centerInChanged();
481 if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){
482 qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
485 QQuickItem *oldCI = d->centerIn;
488 d->addDepend(d->centerIn);
489 emit centerInChanged();
490 d->centerInChanged();
493 void QQuickAnchors::resetCenterIn()
498 bool QQuickAnchorsPrivate::calcStretch(const QQuickAnchorLine &edge1,
499 const QQuickAnchorLine &edge2,
502 QQuickAnchorLine::AnchorLine line,
505 bool edge1IsParent = (edge1.item == item->parentItem());
506 bool edge2IsParent = (edge2.item == item->parentItem());
507 bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
508 bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
510 bool invalid = false;
511 if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
512 stretch = (position(edge2.item, edge2.anchorLine) + offset2)
513 - (position(edge1.item, edge1.anchorLine) + offset1);
514 } else if (edge2IsParent && edge1IsSibling) {
515 stretch = (position(edge2.item, edge2.anchorLine) + offset2)
516 - (position(item->parentItem(), line)
517 + position(edge1.item, edge1.anchorLine) + offset1);
518 } else if (edge2IsSibling && edge1IsParent) {
519 stretch = (position(item->parentItem(), line) + position(edge2.item, edge2.anchorLine) + offset2)
520 - (position(edge1.item, edge1.anchorLine) + offset1);
527 void QQuickAnchorsPrivate::updateVerticalAnchors()
529 if (fill || centerIn || !isItemComplete())
532 if (updatingVerticalAnchor < 2) {
533 ++updatingVerticalAnchor;
534 if (usedAnchors & QQuickAnchors::TopAnchor) {
538 if (usedAnchors & QQuickAnchors::BottomAnchor) {
539 invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QQuickAnchorLine::Top, height);
540 } else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
541 invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QQuickAnchorLine::Top, height);
545 setItemHeight(height);
548 if (top.item == item->parentItem()) {
549 setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
550 } else if (top.item->parentItem() == item->parentItem()) {
551 setItemY(position(top.item, top.anchorLine) + topMargin);
553 } else if (usedAnchors & QQuickAnchors::BottomAnchor) {
554 //Handle stretching (top + bottom case is handled above)
555 if (usedAnchors & QQuickAnchors::VCenterAnchor) {
557 bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
558 QQuickAnchorLine::Top, height);
560 setItemHeight(height*2);
564 if (bottom.item == item->parentItem()) {
565 setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
566 } else if (bottom.item->parentItem() == item->parentItem()) {
567 setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
569 } else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
570 //(stetching handled above)
573 if (vCenter.item == item->parentItem()) {
574 setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
575 - vcenter(item) + vCenterOffset);
576 } else if (vCenter.item->parentItem() == item->parentItem()) {
577 setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset);
579 } else if (usedAnchors & QQuickAnchors::BaselineAnchor) {
581 if (baseline.item == item->parentItem()) {
582 setItemY(adjustedPosition(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset);
583 } else if (baseline.item->parentItem() == item->parentItem()) {
584 setItemY(position(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset);
587 --updatingVerticalAnchor;
589 // ### Make this certain :)
590 qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on vertical anchor.");
594 inline QQuickAnchorLine::AnchorLine reverseAnchorLine(QQuickAnchorLine::AnchorLine anchorLine)
596 if (anchorLine == QQuickAnchorLine::Left) {
597 return QQuickAnchorLine::Right;
598 } else if (anchorLine == QQuickAnchorLine::Right) {
599 return QQuickAnchorLine::Left;
605 void QQuickAnchorsPrivate::updateHorizontalAnchors()
608 if (fill || centerIn || !isItemComplete())
611 if (updatingHorizontalAnchor < 3) {
612 ++updatingHorizontalAnchor;
613 qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
614 QQuickAnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter;
615 QQuickAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
617 effectiveLeftAnchor = QQuickAnchors::RightAnchor;
618 effectiveRightAnchor = QQuickAnchors::LeftAnchor;
619 effectiveLeft.item = right.item;
620 effectiveLeft.anchorLine = reverseAnchorLine(right.anchorLine);
621 effectiveRight.item = left.item;
622 effectiveRight.anchorLine = reverseAnchorLine(left.anchorLine);
623 effectiveHorizontalCenter.item = hCenter.item;
624 effectiveHorizontalCenter.anchorLine = reverseAnchorLine(hCenter.anchorLine);
625 effectiveLeftMargin = rightMargin;
626 effectiveRightMargin = leftMargin;
627 effectiveHorizontalCenterOffset = -hCenterOffset;
629 effectiveLeftAnchor = QQuickAnchors::LeftAnchor;
630 effectiveRightAnchor = QQuickAnchors::RightAnchor;
631 effectiveLeft = left;
632 effectiveRight = right;
633 effectiveHorizontalCenter = hCenter;
634 effectiveLeftMargin = leftMargin;
635 effectiveRightMargin = rightMargin;
636 effectiveHorizontalCenterOffset = hCenterOffset;
639 if (usedAnchors & effectiveLeftAnchor) {
643 if (usedAnchors & effectiveRightAnchor) {
644 invalid = calcStretch(effectiveLeft, effectiveRight, effectiveLeftMargin, -effectiveRightMargin, QQuickAnchorLine::Left, width);
645 } else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
646 invalid = calcStretch(effectiveLeft, effectiveHorizontalCenter, effectiveLeftMargin, effectiveHorizontalCenterOffset, QQuickAnchorLine::Left, width);
653 if (effectiveLeft.item == item->parentItem()) {
654 setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
655 } else if (effectiveLeft.item->parentItem() == item->parentItem()) {
656 setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
658 } else if (usedAnchors & effectiveRightAnchor) {
659 //Handle stretching (left + right case is handled in updateLeftAnchor)
660 if (usedAnchors & QQuickAnchors::HCenterAnchor) {
662 bool invalid = calcStretch(effectiveHorizontalCenter, effectiveRight, effectiveHorizontalCenterOffset, -effectiveRightMargin,
663 QQuickAnchorLine::Left, width);
665 setItemWidth(width*2);
669 if (effectiveRight.item == item->parentItem()) {
670 setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin);
671 } else if (effectiveRight.item->parentItem() == item->parentItem()) {
672 setItemX(position(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin);
674 } else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
676 if (effectiveHorizontalCenter.item == item->parentItem()) {
677 setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
678 } else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) {
679 setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
682 --updatingHorizontalAnchor;
684 // ### Make this certain :)
685 qmlInfo(item) << QQuickAnchors::tr("Possible anchor loop detected on horizontal anchor.");
689 QQuickAnchorLine QQuickAnchors::top() const
691 Q_D(const QQuickAnchors);
695 void QQuickAnchors::setTop(const QQuickAnchorLine &edge)
698 if (!d->checkVAnchorValid(edge) || d->top == edge)
701 d->usedAnchors |= TopAnchor;
703 if (!d->checkVValid()) {
704 d->usedAnchors &= ~TopAnchor;
708 QQuickItem *oldTop = d->top.item;
710 d->remDepend(oldTop);
711 d->addDepend(d->top.item);
713 d->updateVerticalAnchors();
716 void QQuickAnchors::resetTop()
719 d->usedAnchors &= ~TopAnchor;
720 d->remDepend(d->top.item);
721 d->top = QQuickAnchorLine();
723 d->updateVerticalAnchors();
726 QQuickAnchorLine QQuickAnchors::bottom() const
728 Q_D(const QQuickAnchors);
732 void QQuickAnchors::setBottom(const QQuickAnchorLine &edge)
735 if (!d->checkVAnchorValid(edge) || d->bottom == edge)
738 d->usedAnchors |= BottomAnchor;
740 if (!d->checkVValid()) {
741 d->usedAnchors &= ~BottomAnchor;
745 QQuickItem *oldBottom = d->bottom.item;
747 d->remDepend(oldBottom);
748 d->addDepend(d->bottom.item);
749 emit bottomChanged();
750 d->updateVerticalAnchors();
753 void QQuickAnchors::resetBottom()
756 d->usedAnchors &= ~BottomAnchor;
757 d->remDepend(d->bottom.item);
758 d->bottom = QQuickAnchorLine();
759 emit bottomChanged();
760 d->updateVerticalAnchors();
763 QQuickAnchorLine QQuickAnchors::verticalCenter() const
765 Q_D(const QQuickAnchors);
769 void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge)
772 if (!d->checkVAnchorValid(edge) || d->vCenter == edge)
775 d->usedAnchors |= VCenterAnchor;
777 if (!d->checkVValid()) {
778 d->usedAnchors &= ~VCenterAnchor;
782 QQuickItem *oldVCenter = d->vCenter.item;
784 d->remDepend(oldVCenter);
785 d->addDepend(d->vCenter.item);
786 emit verticalCenterChanged();
787 d->updateVerticalAnchors();
790 void QQuickAnchors::resetVerticalCenter()
793 d->usedAnchors &= ~VCenterAnchor;
794 d->remDepend(d->vCenter.item);
795 d->vCenter = QQuickAnchorLine();
796 emit verticalCenterChanged();
797 d->updateVerticalAnchors();
800 QQuickAnchorLine QQuickAnchors::baseline() const
802 Q_D(const QQuickAnchors);
806 void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge)
809 if (!d->checkVAnchorValid(edge) || d->baseline == edge)
812 d->usedAnchors |= BaselineAnchor;
814 if (!d->checkVValid()) {
815 d->usedAnchors &= ~BaselineAnchor;
819 QQuickItem *oldBaseline = d->baseline.item;
821 d->remDepend(oldBaseline);
822 d->addDepend(d->baseline.item);
823 emit baselineChanged();
824 d->updateVerticalAnchors();
827 void QQuickAnchors::resetBaseline()
830 d->usedAnchors &= ~BaselineAnchor;
831 d->remDepend(d->baseline.item);
832 d->baseline = QQuickAnchorLine();
833 emit baselineChanged();
834 d->updateVerticalAnchors();
837 QQuickAnchorLine QQuickAnchors::left() const
839 Q_D(const QQuickAnchors);
843 void QQuickAnchors::setLeft(const QQuickAnchorLine &edge)
846 if (!d->checkHAnchorValid(edge) || d->left == edge)
849 d->usedAnchors |= LeftAnchor;
851 if (!d->checkHValid()) {
852 d->usedAnchors &= ~LeftAnchor;
856 QQuickItem *oldLeft = d->left.item;
858 d->remDepend(oldLeft);
859 d->addDepend(d->left.item);
861 d->updateHorizontalAnchors();
864 void QQuickAnchors::resetLeft()
867 d->usedAnchors &= ~LeftAnchor;
868 d->remDepend(d->left.item);
869 d->left = QQuickAnchorLine();
871 d->updateHorizontalAnchors();
874 QQuickAnchorLine QQuickAnchors::right() const
876 Q_D(const QQuickAnchors);
880 void QQuickAnchors::setRight(const QQuickAnchorLine &edge)
883 if (!d->checkHAnchorValid(edge) || d->right == edge)
886 d->usedAnchors |= RightAnchor;
888 if (!d->checkHValid()) {
889 d->usedAnchors &= ~RightAnchor;
893 QQuickItem *oldRight = d->right.item;
895 d->remDepend(oldRight);
896 d->addDepend(d->right.item);
898 d->updateHorizontalAnchors();
901 void QQuickAnchors::resetRight()
904 d->usedAnchors &= ~RightAnchor;
905 d->remDepend(d->right.item);
906 d->right = QQuickAnchorLine();
908 d->updateHorizontalAnchors();
911 QQuickAnchorLine QQuickAnchors::horizontalCenter() const
913 Q_D(const QQuickAnchors);
917 void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge)
920 if (!d->checkHAnchorValid(edge) || d->hCenter == edge)
923 d->usedAnchors |= HCenterAnchor;
925 if (!d->checkHValid()) {
926 d->usedAnchors &= ~HCenterAnchor;
930 QQuickItem *oldHCenter = d->hCenter.item;
932 d->remDepend(oldHCenter);
933 d->addDepend(d->hCenter.item);
934 emit horizontalCenterChanged();
935 d->updateHorizontalAnchors();
938 void QQuickAnchors::resetHorizontalCenter()
941 d->usedAnchors &= ~HCenterAnchor;
942 d->remDepend(d->hCenter.item);
943 d->hCenter = QQuickAnchorLine();
944 emit horizontalCenterChanged();
945 d->updateHorizontalAnchors();
948 qreal QQuickAnchors::leftMargin() const
950 Q_D(const QQuickAnchors);
951 return d->leftMargin;
954 void QQuickAnchors::setLeftMargin(qreal offset)
957 if (d->leftMargin == offset)
959 d->leftMargin = offset;
963 d->updateHorizontalAnchors();
964 emit leftMarginChanged();
967 qreal QQuickAnchors::rightMargin() const
969 Q_D(const QQuickAnchors);
970 return d->rightMargin;
973 void QQuickAnchors::setRightMargin(qreal offset)
976 if (d->rightMargin == offset)
978 d->rightMargin = offset;
982 d->updateHorizontalAnchors();
983 emit rightMarginChanged();
986 qreal QQuickAnchors::margins() const
988 Q_D(const QQuickAnchors);
992 void QQuickAnchors::setMargins(qreal offset)
995 if (d->margins == offset)
997 //###Is it significantly faster to set them directly so we can call fillChanged only once?
998 if (!d->rightMargin || d->rightMargin == d->margins)
999 setRightMargin(offset);
1000 if (!d->leftMargin || d->leftMargin == d->margins)
1001 setLeftMargin(offset);
1002 if (!d->topMargin || d->topMargin == d->margins)
1003 setTopMargin(offset);
1004 if (!d->bottomMargin || d->bottomMargin == d->margins)
1005 setBottomMargin(offset);
1006 d->margins = offset;
1007 emit marginsChanged();
1011 qreal QQuickAnchors::horizontalCenterOffset() const
1013 Q_D(const QQuickAnchors);
1014 return d->hCenterOffset;
1017 void QQuickAnchors::setHorizontalCenterOffset(qreal offset)
1020 if (d->hCenterOffset == offset)
1022 d->hCenterOffset = offset;
1024 d->centerInChanged();
1026 d->updateHorizontalAnchors();
1027 emit horizontalCenterOffsetChanged();
1030 qreal QQuickAnchors::topMargin() const
1032 Q_D(const QQuickAnchors);
1033 return d->topMargin;
1036 void QQuickAnchors::setTopMargin(qreal offset)
1039 if (d->topMargin == offset)
1041 d->topMargin = offset;
1045 d->updateVerticalAnchors();
1046 emit topMarginChanged();
1049 qreal QQuickAnchors::bottomMargin() const
1051 Q_D(const QQuickAnchors);
1052 return d->bottomMargin;
1055 void QQuickAnchors::setBottomMargin(qreal offset)
1058 if (d->bottomMargin == offset)
1060 d->bottomMargin = offset;
1064 d->updateVerticalAnchors();
1065 emit bottomMarginChanged();
1068 qreal QQuickAnchors::verticalCenterOffset() const
1070 Q_D(const QQuickAnchors);
1071 return d->vCenterOffset;
1074 void QQuickAnchors::setVerticalCenterOffset(qreal offset)
1077 if (d->vCenterOffset == offset)
1079 d->vCenterOffset = offset;
1081 d->centerInChanged();
1083 d->updateVerticalAnchors();
1084 emit verticalCenterOffsetChanged();
1087 qreal QQuickAnchors::baselineOffset() const
1089 Q_D(const QQuickAnchors);
1090 return d->baselineOffset;
1093 void QQuickAnchors::setBaselineOffset(qreal offset)
1096 if (d->baselineOffset == offset)
1098 d->baselineOffset = offset;
1099 d->updateVerticalAnchors();
1100 emit baselineOffsetChanged();
1103 QQuickAnchors::Anchors QQuickAnchors::usedAnchors() const
1105 Q_D(const QQuickAnchors);
1106 return d->usedAnchors;
1109 bool QQuickAnchorsPrivate::checkHValid() const
1111 if (usedAnchors & QQuickAnchors::LeftAnchor &&
1112 usedAnchors & QQuickAnchors::RightAnchor &&
1113 usedAnchors & QQuickAnchors::HCenterAnchor) {
1114 qmlInfo(item) << QQuickAnchors::tr("Cannot specify left, right, and hcenter anchors.");
1121 bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const
1124 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
1126 } else if (anchor.anchorLine & QQuickAnchorLine::Vertical_Mask) {
1127 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
1129 } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
1130 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1132 } else if (anchor.item == item) {
1133 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor item to self.");
1140 bool QQuickAnchorsPrivate::checkVValid() const
1142 if (usedAnchors & QQuickAnchors::TopAnchor &&
1143 usedAnchors & QQuickAnchors::BottomAnchor &&
1144 usedAnchors & QQuickAnchors::VCenterAnchor) {
1145 qmlInfo(item) << QQuickAnchors::tr("Cannot specify top, bottom, and vcenter anchors.");
1147 } else if (usedAnchors & QQuickAnchors::BaselineAnchor &&
1148 (usedAnchors & QQuickAnchors::TopAnchor ||
1149 usedAnchors & QQuickAnchors::BottomAnchor ||
1150 usedAnchors & QQuickAnchors::VCenterAnchor)) {
1151 qmlInfo(item) << QQuickAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.");
1158 bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const
1161 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
1163 } else if (anchor.anchorLine & QQuickAnchorLine::Horizontal_Mask) {
1164 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
1166 } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
1167 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
1169 } else if (anchor.item == item){
1170 qmlInfo(item) << QQuickAnchors::tr("Cannot anchor item to self.");
1179 #include <moc_qquickanchors_p.cpp>