1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickstateoperations_p.h"
43 #include "qquickitem_p.h"
45 #include <private/qquickstate_p_p.h>
47 #include <QtQml/qqmlinfo.h>
48 #include <QtCore/qmath.h>
52 class QQuickParentChangePrivate : public QQuickStateOperationPrivate
54 Q_DECLARE_PUBLIC(QQuickParentChange)
56 QQuickParentChangePrivate() : target(0), parent(0), origParent(0), origStackBefore(0),
57 rewindParent(0), rewindStackBefore(0) {}
60 QQmlGuard<QQuickItem> parent;
61 QQmlGuard<QQuickItem> origParent;
62 QQmlGuard<QQuickItem> origStackBefore;
63 QQuickItem *rewindParent;
64 QQuickItem *rewindStackBefore;
66 QQmlNullableValue<QQmlScriptString> xString;
67 QQmlNullableValue<QQmlScriptString> yString;
68 QQmlNullableValue<QQmlScriptString> widthString;
69 QQmlNullableValue<QQmlScriptString> heightString;
70 QQmlNullableValue<QQmlScriptString> scaleString;
71 QQmlNullableValue<QQmlScriptString> rotationString;
73 void doChange(QQuickItem *targetParent, QQuickItem *stackBefore = 0);
76 void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *stackBefore)
78 if (targetParent && target && target->parentItem()) {
79 Q_Q(QQuickParentChange);
81 const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok);
82 if (transform.type() >= QTransform::TxShear || !ok) {
83 qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under complex transform");
89 bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
90 if (ok && !isRotate) {
91 if (transform.m11() == transform.m22())
92 scale = transform.m11();
94 qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
97 } else if (ok && isRotate) {
98 if (transform.m11() == transform.m22())
99 scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
101 qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
106 rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
108 qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0");
113 const QPointF &point = transform.map(QPointF(target->x(),target->y()));
117 // setParentItem will update the transformOriginPoint if needed
118 target->setParentItem(targetParent);
120 if (ok && target->transformOrigin() != QQuickItem::TopLeft) {
121 qreal tempxt = target->transformOriginPoint().x();
122 qreal tempyt = target->transformOriginPoint().y();
124 t.translate(-tempxt, -tempyt);
126 t.scale(scale, scale);
127 t.translate(tempxt, tempyt);
128 const QPointF &offset = t.map(QPointF(0,0));
134 //qDebug() << x << y << rotation << scale;
135 target->setPos(QPointF(x, y));
136 target->setRotation(target->rotation() + rotation);
137 target->setScale(target->scale() * scale);
140 target->setParentItem(targetParent);
143 //restore the original stack position.
144 //### if stackBefore has also been reparented this won't work
146 target->stackBefore(stackBefore);
150 \qmlclass ParentChange QQuickParentChange
151 \inqmlmodule QtQuick 2
152 \ingroup qml-state-elements
153 \brief The ParentChange element allows you to reparent an Item in a state change.
155 ParentChange reparents an item while preserving its visual appearance (position, size,
156 rotation, and scale) on screen. You can then specify a transition to move/resize/rotate/scale
157 the item to its final intended appearance.
159 ParentChange can only preserve visual appearance if no complex transforms are involved.
160 More specifically, it will not work if the transform property has been set for any
161 items involved in the reparenting (i.e. items in the common ancestor tree
162 for the original and new parent).
164 The example below displays a large red rectangle and a small blue rectangle, side by side.
165 When the \c blueRect is clicked, it changes to the "reparented" state: its parent is changed to \c redRect and it is
166 positioned at (10, 10) within the red rectangle, as specified in the ParentChange.
168 \snippet doc/snippets/qml/parentchange.qml 0
170 \image parentchange.png
172 You can specify at which point in a transition you want a ParentChange to occur by
173 using a ParentAnimation.
175 Note that unlike PropertyChanges, ParentChange expects an Item-based target; it will not work with
176 arbitrary objects (for example, you couldn't use it to reparent a Timer).
179 QQuickParentChange::QQuickParentChange(QObject *parent)
180 : QQuickStateOperation(*(new QQuickParentChangePrivate), parent)
184 QQuickParentChange::~QQuickParentChange()
189 \qmlproperty real ParentChange::x
190 \qmlproperty real ParentChange::y
191 \qmlproperty real ParentChange::width
192 \qmlproperty real ParentChange::height
193 \qmlproperty real ParentChange::scale
194 \qmlproperty real ParentChange::rotation
195 These properties hold the new position, size, scale, and rotation
196 for the item in this state.
198 QQmlScriptString QQuickParentChange::x() const
200 Q_D(const QQuickParentChange);
201 return d->xString.value;
204 void QQuickParentChange::setX(QQmlScriptString x)
206 Q_D(QQuickParentChange);
210 bool QQuickParentChange::xIsSet() const
212 Q_D(const QQuickParentChange);
213 return d->xString.isValid();
216 QQmlScriptString QQuickParentChange::y() const
218 Q_D(const QQuickParentChange);
219 return d->yString.value;
222 void QQuickParentChange::setY(QQmlScriptString y)
224 Q_D(QQuickParentChange);
228 bool QQuickParentChange::yIsSet() const
230 Q_D(const QQuickParentChange);
231 return d->yString.isValid();
234 QQmlScriptString QQuickParentChange::width() const
236 Q_D(const QQuickParentChange);
237 return d->widthString.value;
240 void QQuickParentChange::setWidth(QQmlScriptString width)
242 Q_D(QQuickParentChange);
243 d->widthString = width;
246 bool QQuickParentChange::widthIsSet() const
248 Q_D(const QQuickParentChange);
249 return d->widthString.isValid();
252 QQmlScriptString QQuickParentChange::height() const
254 Q_D(const QQuickParentChange);
255 return d->heightString.value;
258 void QQuickParentChange::setHeight(QQmlScriptString height)
260 Q_D(QQuickParentChange);
261 d->heightString = height;
264 bool QQuickParentChange::heightIsSet() const
266 Q_D(const QQuickParentChange);
267 return d->heightString.isValid();
270 QQmlScriptString QQuickParentChange::scale() const
272 Q_D(const QQuickParentChange);
273 return d->scaleString.value;
276 void QQuickParentChange::setScale(QQmlScriptString scale)
278 Q_D(QQuickParentChange);
279 d->scaleString = scale;
282 bool QQuickParentChange::scaleIsSet() const
284 Q_D(const QQuickParentChange);
285 return d->scaleString.isValid();
288 QQmlScriptString QQuickParentChange::rotation() const
290 Q_D(const QQuickParentChange);
291 return d->rotationString.value;
294 void QQuickParentChange::setRotation(QQmlScriptString rotation)
296 Q_D(QQuickParentChange);
297 d->rotationString = rotation;
300 bool QQuickParentChange::rotationIsSet() const
302 Q_D(const QQuickParentChange);
303 return d->rotationString.isValid();
306 QQuickItem *QQuickParentChange::originalParent() const
308 Q_D(const QQuickParentChange);
309 return d->origParent;
313 \qmlproperty Item ParentChange::target
314 This property holds the item to be reparented
316 QQuickItem *QQuickParentChange::object() const
318 Q_D(const QQuickParentChange);
322 void QQuickParentChange::setObject(QQuickItem *target)
324 Q_D(QQuickParentChange);
329 \qmlproperty Item ParentChange::parent
330 This property holds the new parent for the item in this state.
332 QQuickItem *QQuickParentChange::parent() const
334 Q_D(const QQuickParentChange);
338 void QQuickParentChange::setParent(QQuickItem *parent)
340 Q_D(QQuickParentChange);
344 QQuickStateOperation::ActionList QQuickParentChange::actions()
346 Q_D(QQuickParentChange);
347 if (!d->target || !d->parent)
356 if (d->xString.isValid()) {
358 QString script = d->xString.value.script();
359 qreal x = script.toFloat(&ok);
361 QQuickAction xa(d->target, QLatin1String("x"), x);
364 QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
365 QQmlProperty property(d->target, QLatin1String("x"));
366 newBinding->setTarget(property);
368 xa.property = property;
369 xa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
370 xa.fromValue = xa.property.read();
371 xa.deletableToBinding = true;
376 if (d->yString.isValid()) {
378 QString script = d->yString.value.script();
379 qreal y = script.toFloat(&ok);
381 QQuickAction ya(d->target, QLatin1String("y"), y);
384 QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
385 QQmlProperty property(d->target, QLatin1String("y"));
386 newBinding->setTarget(property);
388 ya.property = property;
389 ya.toBinding = QQmlAbstractBinding::getPointer(newBinding);
390 ya.fromValue = ya.property.read();
391 ya.deletableToBinding = true;
396 if (d->scaleString.isValid()) {
398 QString script = d->scaleString.value.script();
399 qreal scale = script.toFloat(&ok);
401 QQuickAction sa(d->target, QLatin1String("scale"), scale);
404 QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
405 QQmlProperty property(d->target, QLatin1String("scale"));
406 newBinding->setTarget(property);
408 sa.property = property;
409 sa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
410 sa.fromValue = sa.property.read();
411 sa.deletableToBinding = true;
416 if (d->rotationString.isValid()) {
418 QString script = d->rotationString.value.script();
419 qreal rotation = script.toFloat(&ok);
421 QQuickAction ra(d->target, QLatin1String("rotation"), rotation);
424 QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
425 QQmlProperty property(d->target, QLatin1String("rotation"));
426 newBinding->setTarget(property);
428 ra.property = property;
429 ra.toBinding = QQmlAbstractBinding::getPointer(newBinding);
430 ra.fromValue = ra.property.read();
431 ra.deletableToBinding = true;
436 if (d->widthString.isValid()) {
438 QString script = d->widthString.value.script();
439 qreal width = script.toFloat(&ok);
441 QQuickAction wa(d->target, QLatin1String("width"), width);
444 QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
445 QQmlProperty property(d->target, QLatin1String("width"));
446 newBinding->setTarget(property);
448 wa.property = property;
449 wa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
450 wa.fromValue = wa.property.read();
451 wa.deletableToBinding = true;
456 if (d->heightString.isValid()) {
458 QString script = d->heightString.value.script();
459 qreal height = script.toFloat(&ok);
461 QQuickAction ha(d->target, QLatin1String("height"), height);
464 QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
465 QQmlProperty property(d->target, QLatin1String("height"));
466 newBinding->setTarget(property);
468 ha.property = property;
469 ha.toBinding = QQmlAbstractBinding::getPointer(newBinding);
470 ha.fromValue = ha.property.read();
471 ha.deletableToBinding = true;
479 void QQuickParentChange::saveOriginals()
481 Q_D(QQuickParentChange);
483 d->origParent = d->rewindParent;
484 d->origStackBefore = d->rewindStackBefore;
487 /*void QQuickParentChange::copyOriginals(QQuickActionEvent *other)
489 Q_D(QQuickParentChange);
490 QQuickParentChange *pc = static_cast<QQuickParentChange*>(other);
492 d->origParent = pc->d_func()->rewindParent;
493 d->origStackBefore = pc->d_func()->rewindStackBefore;
498 void QQuickParentChange::execute(Reason)
500 Q_D(QQuickParentChange);
501 d->doChange(d->parent);
504 bool QQuickParentChange::isReversable()
509 void QQuickParentChange::reverse(Reason)
511 Q_D(QQuickParentChange);
512 d->doChange(d->origParent, d->origStackBefore);
515 QQuickActionEvent::EventType QQuickParentChange::type() const
520 bool QQuickParentChange::override(QQuickActionEvent*other)
522 Q_D(QQuickParentChange);
523 if (other->type() != ParentChange)
525 if (QQuickParentChange *otherPC = static_cast<QQuickParentChange*>(other))
526 return (d->target == otherPC->object());
530 void QQuickParentChange::saveCurrentValues()
532 Q_D(QQuickParentChange);
535 d->rewindStackBefore = 0;
539 d->rewindParent = d->target->parentItem();
540 d->rewindStackBefore = 0;
542 if (!d->rewindParent)
545 QList<QQuickItem *> children = d->rewindParent->childItems();
546 for (int ii = 0; ii < children.count() - 1; ++ii) {
547 if (children.at(ii) == d->target) {
548 d->rewindStackBefore = children.at(ii + 1);
554 void QQuickParentChange::rewind()
556 Q_D(QQuickParentChange);
557 d->doChange(d->rewindParent, d->rewindStackBefore);
561 \qmlclass AnchorChanges QQuickAnchorChanges
562 \inqmlmodule QtQuick 2
563 \ingroup qml-state-elements
564 \brief The AnchorChanges element allows you to change the anchors of an item in a state.
566 The AnchorChanges element is used to modify the anchors of an item in a \l State.
568 AnchorChanges cannot be used to modify the margins on an item. For this, use
569 PropertyChanges intead.
571 In the following example we change the top and bottom anchors of an item
572 using AnchorChanges, and the top and bottom anchor margins using
575 \snippet doc/snippets/qml/anchorchanges.qml 0
577 \image anchorchanges.png
579 AnchorChanges can be animated using AnchorAnimation.
581 //animate our anchor changes
587 Changes to anchor margins can be animated using NumberAnimation.
589 For more information on anchors see \l {anchor-layout}{Anchor Layouts}.
592 class QQuickAnchorSetPrivate : public QObjectPrivate
594 Q_DECLARE_PUBLIC(QQuickAnchorSet)
596 QQuickAnchorSetPrivate()
597 : usedAnchors(0), resetAnchors(0), fill(0),
598 centerIn(0)/*, leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
599 margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)*/
603 QQuickAnchors::Anchors usedAnchors;
604 QQuickAnchors::Anchors resetAnchors;
607 QQuickItem *centerIn;
609 QQmlScriptString leftScript;
610 QQmlScriptString rightScript;
611 QQmlScriptString topScript;
612 QQmlScriptString bottomScript;
613 QQmlScriptString hCenterScript;
614 QQmlScriptString vCenterScript;
615 QQmlScriptString baselineScript;
624 qreal baselineOffset;*/
627 QQuickAnchorSet::QQuickAnchorSet(QObject *parent)
628 : QObject(*new QQuickAnchorSetPrivate, parent)
632 QQuickAnchorSet::~QQuickAnchorSet()
636 QQmlScriptString QQuickAnchorSet::top() const
638 Q_D(const QQuickAnchorSet);
642 void QQuickAnchorSet::setTop(const QQmlScriptString &edge)
644 Q_D(QQuickAnchorSet);
645 d->usedAnchors |= QQuickAnchors::TopAnchor;
647 if (edge.script() == QLatin1String("undefined"))
651 void QQuickAnchorSet::resetTop()
653 Q_D(QQuickAnchorSet);
654 d->usedAnchors &= ~QQuickAnchors::TopAnchor;
655 d->resetAnchors |= QQuickAnchors::TopAnchor;
658 QQmlScriptString QQuickAnchorSet::bottom() const
660 Q_D(const QQuickAnchorSet);
661 return d->bottomScript;
664 void QQuickAnchorSet::setBottom(const QQmlScriptString &edge)
666 Q_D(QQuickAnchorSet);
667 d->usedAnchors |= QQuickAnchors::BottomAnchor;
668 d->bottomScript = edge;
669 if (edge.script() == QLatin1String("undefined"))
673 void QQuickAnchorSet::resetBottom()
675 Q_D(QQuickAnchorSet);
676 d->usedAnchors &= ~QQuickAnchors::BottomAnchor;
677 d->resetAnchors |= QQuickAnchors::BottomAnchor;
680 QQmlScriptString QQuickAnchorSet::verticalCenter() const
682 Q_D(const QQuickAnchorSet);
683 return d->vCenterScript;
686 void QQuickAnchorSet::setVerticalCenter(const QQmlScriptString &edge)
688 Q_D(QQuickAnchorSet);
689 d->usedAnchors |= QQuickAnchors::VCenterAnchor;
690 d->vCenterScript = edge;
691 if (edge.script() == QLatin1String("undefined"))
692 resetVerticalCenter();
695 void QQuickAnchorSet::resetVerticalCenter()
697 Q_D(QQuickAnchorSet);
698 d->usedAnchors &= ~QQuickAnchors::VCenterAnchor;
699 d->resetAnchors |= QQuickAnchors::VCenterAnchor;
702 QQmlScriptString QQuickAnchorSet::baseline() const
704 Q_D(const QQuickAnchorSet);
705 return d->baselineScript;
708 void QQuickAnchorSet::setBaseline(const QQmlScriptString &edge)
710 Q_D(QQuickAnchorSet);
711 d->usedAnchors |= QQuickAnchors::BaselineAnchor;
712 d->baselineScript = edge;
713 if (edge.script() == QLatin1String("undefined"))
717 void QQuickAnchorSet::resetBaseline()
719 Q_D(QQuickAnchorSet);
720 d->usedAnchors &= ~QQuickAnchors::BaselineAnchor;
721 d->resetAnchors |= QQuickAnchors::BaselineAnchor;
724 QQmlScriptString QQuickAnchorSet::left() const
726 Q_D(const QQuickAnchorSet);
727 return d->leftScript;
730 void QQuickAnchorSet::setLeft(const QQmlScriptString &edge)
732 Q_D(QQuickAnchorSet);
733 d->usedAnchors |= QQuickAnchors::LeftAnchor;
734 d->leftScript = edge;
735 if (edge.script() == QLatin1String("undefined"))
739 void QQuickAnchorSet::resetLeft()
741 Q_D(QQuickAnchorSet);
742 d->usedAnchors &= ~QQuickAnchors::LeftAnchor;
743 d->resetAnchors |= QQuickAnchors::LeftAnchor;
746 QQmlScriptString QQuickAnchorSet::right() const
748 Q_D(const QQuickAnchorSet);
749 return d->rightScript;
752 void QQuickAnchorSet::setRight(const QQmlScriptString &edge)
754 Q_D(QQuickAnchorSet);
755 d->usedAnchors |= QQuickAnchors::RightAnchor;
756 d->rightScript = edge;
757 if (edge.script() == QLatin1String("undefined"))
761 void QQuickAnchorSet::resetRight()
763 Q_D(QQuickAnchorSet);
764 d->usedAnchors &= ~QQuickAnchors::RightAnchor;
765 d->resetAnchors |= QQuickAnchors::RightAnchor;
768 QQmlScriptString QQuickAnchorSet::horizontalCenter() const
770 Q_D(const QQuickAnchorSet);
771 return d->hCenterScript;
774 void QQuickAnchorSet::setHorizontalCenter(const QQmlScriptString &edge)
776 Q_D(QQuickAnchorSet);
777 d->usedAnchors |= QQuickAnchors::HCenterAnchor;
778 d->hCenterScript = edge;
779 if (edge.script() == QLatin1String("undefined"))
780 resetHorizontalCenter();
783 void QQuickAnchorSet::resetHorizontalCenter()
785 Q_D(QQuickAnchorSet);
786 d->usedAnchors &= ~QQuickAnchors::HCenterAnchor;
787 d->resetAnchors |= QQuickAnchors::HCenterAnchor;
790 QQuickItem *QQuickAnchorSet::fill() const
792 Q_D(const QQuickAnchorSet);
796 void QQuickAnchorSet::setFill(QQuickItem *f)
798 Q_D(QQuickAnchorSet);
802 void QQuickAnchorSet::resetFill()
807 QQuickItem *QQuickAnchorSet::centerIn() const
809 Q_D(const QQuickAnchorSet);
813 void QQuickAnchorSet::setCenterIn(QQuickItem* c)
815 Q_D(QQuickAnchorSet);
819 void QQuickAnchorSet::resetCenterIn()
825 class QQuickAnchorChangesPrivate : public QQuickStateOperationPrivate
828 QQuickAnchorChangesPrivate()
829 : target(0), anchorSet(new QQuickAnchorSet),
830 leftBinding(0), rightBinding(0), hCenterBinding(0),
831 topBinding(0), bottomBinding(0), vCenterBinding(0), baselineBinding(0),
832 origLeftBinding(0), origRightBinding(0), origHCenterBinding(0),
833 origTopBinding(0), origBottomBinding(0), origVCenterBinding(0),
834 origBaselineBinding(0)
838 ~QQuickAnchorChangesPrivate() { delete anchorSet; }
841 QQuickAnchorSet *anchorSet;
843 QQmlBinding *leftBinding;
844 QQmlBinding *rightBinding;
845 QQmlBinding *hCenterBinding;
846 QQmlBinding *topBinding;
847 QQmlBinding *bottomBinding;
848 QQmlBinding *vCenterBinding;
849 QQmlBinding *baselineBinding;
851 QQmlAbstractBinding *origLeftBinding;
852 QQmlAbstractBinding *origRightBinding;
853 QQmlAbstractBinding *origHCenterBinding;
854 QQmlAbstractBinding *origTopBinding;
855 QQmlAbstractBinding *origBottomBinding;
856 QQmlAbstractBinding *origVCenterBinding;
857 QQmlAbstractBinding *origBaselineBinding;
859 QQuickAnchorLine rewindLeft;
860 QQuickAnchorLine rewindRight;
861 QQuickAnchorLine rewindHCenter;
862 QQuickAnchorLine rewindTop;
863 QQuickAnchorLine rewindBottom;
864 QQuickAnchorLine rewindVCenter;
865 QQuickAnchorLine rewindBaseline;
884 bool applyOrigHCenter;
886 bool applyOrigBottom;
887 bool applyOrigVCenter;
888 bool applyOrigBaseline;
890 QQmlNullableValue<qreal> origWidth;
891 QQmlNullableValue<qreal> origHeight;
895 QList<QQmlAbstractBinding*> oldBindings;
897 QQmlProperty leftProp;
898 QQmlProperty rightProp;
899 QQmlProperty hCenterProp;
900 QQmlProperty topProp;
901 QQmlProperty bottomProp;
902 QQmlProperty vCenterProp;
903 QQmlProperty baselineProp;
906 QQuickAnchorChanges::QQuickAnchorChanges(QObject *parent)
907 : QQuickStateOperation(*(new QQuickAnchorChangesPrivate), parent)
911 QQuickAnchorChanges::~QQuickAnchorChanges()
915 QQuickAnchorChanges::ActionList QQuickAnchorChanges::actions()
917 Q_D(QQuickAnchorChanges);
918 d->leftBinding = d->rightBinding = d->hCenterBinding = d->topBinding
919 = d->bottomBinding = d->vCenterBinding = d->baselineBinding = 0;
921 d->leftProp = QQmlProperty(d->target, QLatin1String("anchors.left"));
922 d->rightProp = QQmlProperty(d->target, QLatin1String("anchors.right"));
923 d->hCenterProp = QQmlProperty(d->target, QLatin1String("anchors.horizontalCenter"));
924 d->topProp = QQmlProperty(d->target, QLatin1String("anchors.top"));
925 d->bottomProp = QQmlProperty(d->target, QLatin1String("anchors.bottom"));
926 d->vCenterProp = QQmlProperty(d->target, QLatin1String("anchors.verticalCenter"));
927 d->baselineProp = QQmlProperty(d->target, QLatin1String("anchors.baseline"));
929 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::LeftAnchor) {
930 d->leftBinding = new QQmlBinding(d->anchorSet->d_func()->leftScript.script(), d->target, qmlContext(this));
931 d->leftBinding->setTarget(d->leftProp);
933 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::RightAnchor) {
934 d->rightBinding = new QQmlBinding(d->anchorSet->d_func()->rightScript.script(), d->target, qmlContext(this));
935 d->rightBinding->setTarget(d->rightProp);
937 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::HCenterAnchor) {
938 d->hCenterBinding = new QQmlBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, qmlContext(this));
939 d->hCenterBinding->setTarget(d->hCenterProp);
941 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::TopAnchor) {
942 d->topBinding = new QQmlBinding(d->anchorSet->d_func()->topScript.script(), d->target, qmlContext(this));
943 d->topBinding->setTarget(d->topProp);
945 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::BottomAnchor) {
946 d->bottomBinding = new QQmlBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, qmlContext(this));
947 d->bottomBinding->setTarget(d->bottomProp);
949 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::VCenterAnchor) {
950 d->vCenterBinding = new QQmlBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, qmlContext(this));
951 d->vCenterBinding->setTarget(d->vCenterProp);
953 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::BaselineAnchor) {
954 d->baselineBinding = new QQmlBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, qmlContext(this));
955 d->baselineBinding->setTarget(d->baselineProp);
960 return ActionList() << a;
963 QQuickAnchorSet *QQuickAnchorChanges::anchors()
965 Q_D(QQuickAnchorChanges);
970 \qmlproperty Item AnchorChanges::target
971 This property holds the \l Item for which the anchor changes will be applied.
973 QQuickItem *QQuickAnchorChanges::object() const
975 Q_D(const QQuickAnchorChanges);
979 void QQuickAnchorChanges::setObject(QQuickItem *target)
981 Q_D(QQuickAnchorChanges);
986 \qmlproperty AnchorLine AnchorChanges::anchors.left
987 \qmlproperty AnchorLine AnchorChanges::anchors.right
988 \qmlproperty AnchorLine AnchorChanges::anchors.horizontalCenter
989 \qmlproperty AnchorLine AnchorChanges::anchors.top
990 \qmlproperty AnchorLine AnchorChanges::anchors.bottom
991 \qmlproperty AnchorLine AnchorChanges::anchors.verticalCenter
992 \qmlproperty AnchorLine AnchorChanges::anchors.baseline
994 These properties change the respective anchors of the item.
996 To reset an anchor you can assign \c undefined:
1000 anchors.left: undefined //remove myItem's left anchor
1001 anchors.right: otherItem.right
1006 void QQuickAnchorChanges::execute(Reason reason)
1008 Q_D(QQuickAnchorChanges);
1012 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1013 //incorporate any needed "reverts"
1014 if (d->applyOrigLeft) {
1015 if (!d->origLeftBinding)
1016 targetPrivate->anchors()->resetLeft();
1017 QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
1019 if (d->applyOrigRight) {
1020 if (!d->origRightBinding)
1021 targetPrivate->anchors()->resetRight();
1022 QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
1024 if (d->applyOrigHCenter) {
1025 if (!d->origHCenterBinding)
1026 targetPrivate->anchors()->resetHorizontalCenter();
1027 QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
1029 if (d->applyOrigTop) {
1030 if (!d->origTopBinding)
1031 targetPrivate->anchors()->resetTop();
1032 QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding);
1034 if (d->applyOrigBottom) {
1035 if (!d->origBottomBinding)
1036 targetPrivate->anchors()->resetBottom();
1037 QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
1039 if (d->applyOrigVCenter) {
1040 if (!d->origVCenterBinding)
1041 targetPrivate->anchors()->resetVerticalCenter();
1042 QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
1044 if (d->applyOrigBaseline) {
1045 if (!d->origBaselineBinding)
1046 targetPrivate->anchors()->resetBaseline();
1047 QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
1050 //destroy old bindings
1051 if (reason == ActualChange) {
1052 for (int i = 0; i < d->oldBindings.size(); ++i) {
1053 QQmlAbstractBinding *binding = d->oldBindings.at(i);
1057 d->oldBindings.clear();
1060 //reset any anchors that have been specified as "undefined"
1061 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::LeftAnchor) {
1062 targetPrivate->anchors()->resetLeft();
1063 QQmlPropertyPrivate::setBinding(d->leftProp, 0);
1065 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::RightAnchor) {
1066 targetPrivate->anchors()->resetRight();
1067 QQmlPropertyPrivate::setBinding(d->rightProp, 0);
1069 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::HCenterAnchor) {
1070 targetPrivate->anchors()->resetHorizontalCenter();
1071 QQmlPropertyPrivate::setBinding(d->hCenterProp, 0);
1073 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::TopAnchor) {
1074 targetPrivate->anchors()->resetTop();
1075 QQmlPropertyPrivate::setBinding(d->topProp, 0);
1077 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BottomAnchor) {
1078 targetPrivate->anchors()->resetBottom();
1079 QQmlPropertyPrivate::setBinding(d->bottomProp, 0);
1081 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::VCenterAnchor) {
1082 targetPrivate->anchors()->resetVerticalCenter();
1083 QQmlPropertyPrivate::setBinding(d->vCenterProp, 0);
1085 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BaselineAnchor) {
1086 targetPrivate->anchors()->resetBaseline();
1087 QQmlPropertyPrivate::setBinding(d->baselineProp, 0);
1090 //set any anchors that have been specified
1092 QQmlPropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding);
1093 if (d->rightBinding)
1094 QQmlPropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding);
1095 if (d->hCenterBinding)
1096 QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding);
1098 QQmlPropertyPrivate::setBinding(d->topBinding->property(), d->topBinding);
1099 if (d->bottomBinding)
1100 QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding);
1101 if (d->vCenterBinding)
1102 QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding);
1103 if (d->baselineBinding)
1104 QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding);
1107 bool QQuickAnchorChanges::isReversable()
1112 void QQuickAnchorChanges::reverse(Reason reason)
1114 Q_D(QQuickAnchorChanges);
1118 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1119 //reset any anchors set by the state
1120 if (d->leftBinding) {
1121 targetPrivate->anchors()->resetLeft();
1122 QQmlPropertyPrivate::setBinding(d->leftBinding->property(), 0);
1123 if (reason == ActualChange) {
1124 d->leftBinding->destroy(); d->leftBinding = 0;
1127 if (d->rightBinding) {
1128 targetPrivate->anchors()->resetRight();
1129 QQmlPropertyPrivate::setBinding(d->rightBinding->property(), 0);
1130 if (reason == ActualChange) {
1131 d->rightBinding->destroy(); d->rightBinding = 0;
1134 if (d->hCenterBinding) {
1135 targetPrivate->anchors()->resetHorizontalCenter();
1136 QQmlPropertyPrivate::setBinding(d->hCenterBinding->property(), 0);
1137 if (reason == ActualChange) {
1138 d->hCenterBinding->destroy(); d->hCenterBinding = 0;
1141 if (d->topBinding) {
1142 targetPrivate->anchors()->resetTop();
1143 QQmlPropertyPrivate::setBinding(d->topBinding->property(), 0);
1144 if (reason == ActualChange) {
1145 d->topBinding->destroy(); d->topBinding = 0;
1148 if (d->bottomBinding) {
1149 targetPrivate->anchors()->resetBottom();
1150 QQmlPropertyPrivate::setBinding(d->bottomBinding->property(), 0);
1151 if (reason == ActualChange) {
1152 d->bottomBinding->destroy(); d->bottomBinding = 0;
1155 if (d->vCenterBinding) {
1156 targetPrivate->anchors()->resetVerticalCenter();
1157 QQmlPropertyPrivate::setBinding(d->vCenterBinding->property(), 0);
1158 if (reason == ActualChange) {
1159 d->vCenterBinding->destroy(); d->vCenterBinding = 0;
1162 if (d->baselineBinding) {
1163 targetPrivate->anchors()->resetBaseline();
1164 QQmlPropertyPrivate::setBinding(d->baselineBinding->property(), 0);
1165 if (reason == ActualChange) {
1166 d->baselineBinding->destroy(); d->baselineBinding = 0;
1170 //restore previous anchors
1171 if (d->origLeftBinding)
1172 QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
1173 if (d->origRightBinding)
1174 QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
1175 if (d->origHCenterBinding)
1176 QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
1177 if (d->origTopBinding)
1178 QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding);
1179 if (d->origBottomBinding)
1180 QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
1181 if (d->origVCenterBinding)
1182 QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
1183 if (d->origBaselineBinding)
1184 QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
1186 //restore any absolute geometry changed by the state's anchors
1187 QQuickAnchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Vertical_Mask;
1188 QQuickAnchors::Anchors origVAnchors = targetPrivate->anchors()->usedAnchors() & QQuickAnchors::Vertical_Mask;
1189 QQuickAnchors::Anchors stateHAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Horizontal_Mask;
1190 QQuickAnchors::Anchors origHAnchors = targetPrivate->anchors()->usedAnchors() & QQuickAnchors::Horizontal_Mask;
1192 bool stateSetWidth = (stateHAnchors &&
1193 stateHAnchors != QQuickAnchors::LeftAnchor &&
1194 stateHAnchors != QQuickAnchors::RightAnchor &&
1195 stateHAnchors != QQuickAnchors::HCenterAnchor);
1196 bool origSetWidth = (origHAnchors &&
1197 origHAnchors != QQuickAnchors::LeftAnchor &&
1198 origHAnchors != QQuickAnchors::RightAnchor &&
1199 origHAnchors != QQuickAnchors::HCenterAnchor);
1200 if (d->origWidth.isValid() && stateSetWidth && !origSetWidth)
1201 d->target->setWidth(d->origWidth.value);
1203 bool stateSetHeight = (stateVAnchors &&
1204 stateVAnchors != QQuickAnchors::TopAnchor &&
1205 stateVAnchors != QQuickAnchors::BottomAnchor &&
1206 stateVAnchors != QQuickAnchors::VCenterAnchor &&
1207 stateVAnchors != QQuickAnchors::BaselineAnchor);
1208 bool origSetHeight = (origVAnchors &&
1209 origVAnchors != QQuickAnchors::TopAnchor &&
1210 origVAnchors != QQuickAnchors::BottomAnchor &&
1211 origVAnchors != QQuickAnchors::VCenterAnchor &&
1212 origVAnchors != QQuickAnchors::BaselineAnchor);
1213 if (d->origHeight.isValid() && stateSetHeight && !origSetHeight)
1214 d->target->setHeight(d->origHeight.value);
1216 if (stateHAnchors && !origHAnchors)
1217 d->target->setX(d->origX);
1219 if (stateVAnchors && !origVAnchors)
1220 d->target->setY(d->origY);
1223 QQuickActionEvent::EventType QQuickAnchorChanges::type() const
1225 return AnchorChanges;
1228 QList<QQuickAction> QQuickAnchorChanges::additionalActions()
1230 Q_D(QQuickAnchorChanges);
1231 QList<QQuickAction> extra;
1233 QQuickAnchors::Anchors combined = d->anchorSet->d_func()->usedAnchors | d->anchorSet->d_func()->resetAnchors;
1234 bool hChange = combined & QQuickAnchors::Horizontal_Mask;
1235 bool vChange = combined & QQuickAnchors::Vertical_Mask;
1239 if (hChange && d->fromX != d->toX) {
1240 a.property = QQmlProperty(d->target, QLatin1String("x"));
1244 if (vChange && d->fromY != d->toY) {
1245 a.property = QQmlProperty(d->target, QLatin1String("y"));
1249 if (hChange && d->fromWidth != d->toWidth) {
1250 a.property = QQmlProperty(d->target, QLatin1String("width"));
1251 a.toValue = d->toWidth;
1254 if (vChange && d->fromHeight != d->toHeight) {
1255 a.property = QQmlProperty(d->target, QLatin1String("height"));
1256 a.toValue = d->toHeight;
1264 bool QQuickAnchorChanges::changesBindings()
1269 void QQuickAnchorChanges::saveOriginals()
1271 Q_D(QQuickAnchorChanges);
1275 d->origLeftBinding = QQmlPropertyPrivate::binding(d->leftProp);
1276 d->origRightBinding = QQmlPropertyPrivate::binding(d->rightProp);
1277 d->origHCenterBinding = QQmlPropertyPrivate::binding(d->hCenterProp);
1278 d->origTopBinding = QQmlPropertyPrivate::binding(d->topProp);
1279 d->origBottomBinding = QQmlPropertyPrivate::binding(d->bottomProp);
1280 d->origVCenterBinding = QQmlPropertyPrivate::binding(d->vCenterProp);
1281 d->origBaselineBinding = QQmlPropertyPrivate::binding(d->baselineProp);
1283 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1284 if (targetPrivate->widthValid)
1285 d->origWidth = d->target->width();
1286 if (targetPrivate->heightValid)
1287 d->origHeight = d->target->height();
1288 d->origX = d->target->x();
1289 d->origY = d->target->y();
1291 d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop
1292 = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false;
1294 saveCurrentValues();
1297 void QQuickAnchorChanges::copyOriginals(QQuickActionEvent *other)
1299 Q_D(QQuickAnchorChanges);
1300 QQuickAnchorChanges *ac = static_cast<QQuickAnchorChanges*>(other);
1301 QQuickAnchorChangesPrivate *acp = ac->d_func();
1303 QQuickAnchors::Anchors combined = acp->anchorSet->d_func()->usedAnchors |
1304 acp->anchorSet->d_func()->resetAnchors;
1306 //probably also need to revert some things
1307 d->applyOrigLeft = (combined & QQuickAnchors::LeftAnchor);
1308 d->applyOrigRight = (combined & QQuickAnchors::RightAnchor);
1309 d->applyOrigHCenter = (combined & QQuickAnchors::HCenterAnchor);
1310 d->applyOrigTop = (combined & QQuickAnchors::TopAnchor);
1311 d->applyOrigBottom = (combined & QQuickAnchors::BottomAnchor);
1312 d->applyOrigVCenter = (combined & QQuickAnchors::VCenterAnchor);
1313 d->applyOrigBaseline = (combined & QQuickAnchors::BaselineAnchor);
1315 d->origLeftBinding = acp->origLeftBinding;
1316 d->origRightBinding = acp->origRightBinding;
1317 d->origHCenterBinding = acp->origHCenterBinding;
1318 d->origTopBinding = acp->origTopBinding;
1319 d->origBottomBinding = acp->origBottomBinding;
1320 d->origVCenterBinding = acp->origVCenterBinding;
1321 d->origBaselineBinding = acp->origBaselineBinding;
1323 d->origWidth = acp->origWidth;
1324 d->origHeight = acp->origHeight;
1325 d->origX = acp->origX;
1326 d->origY = acp->origY;
1328 d->oldBindings.clear();
1329 d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding
1330 << acp->topBinding << acp->bottomBinding << acp->baselineBinding;
1332 saveCurrentValues();
1335 void QQuickAnchorChanges::clearBindings()
1337 Q_D(QQuickAnchorChanges);
1341 //### should this (saving "from" values) be moved to saveCurrentValues()?
1342 d->fromX = d->target->x();
1343 d->fromY = d->target->y();
1344 d->fromWidth = d->target->width();
1345 d->fromHeight = d->target->height();
1347 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1348 //reset any anchors with corresponding reverts
1349 //reset any anchors that have been specified as "undefined"
1350 //reset any anchors that we'll be setting in the state
1351 QQuickAnchors::Anchors combined = d->anchorSet->d_func()->resetAnchors |
1352 d->anchorSet->d_func()->usedAnchors;
1353 if (d->applyOrigLeft || (combined & QQuickAnchors::LeftAnchor)) {
1354 targetPrivate->anchors()->resetLeft();
1355 QQmlPropertyPrivate::setBinding(d->leftProp, 0);
1357 if (d->applyOrigRight || (combined & QQuickAnchors::RightAnchor)) {
1358 targetPrivate->anchors()->resetRight();
1359 QQmlPropertyPrivate::setBinding(d->rightProp, 0);
1361 if (d->applyOrigHCenter || (combined & QQuickAnchors::HCenterAnchor)) {
1362 targetPrivate->anchors()->resetHorizontalCenter();
1363 QQmlPropertyPrivate::setBinding(d->hCenterProp, 0);
1365 if (d->applyOrigTop || (combined & QQuickAnchors::TopAnchor)) {
1366 targetPrivate->anchors()->resetTop();
1367 QQmlPropertyPrivate::setBinding(d->topProp, 0);
1369 if (d->applyOrigBottom || (combined & QQuickAnchors::BottomAnchor)) {
1370 targetPrivate->anchors()->resetBottom();
1371 QQmlPropertyPrivate::setBinding(d->bottomProp, 0);
1373 if (d->applyOrigVCenter || (combined & QQuickAnchors::VCenterAnchor)) {
1374 targetPrivate->anchors()->resetVerticalCenter();
1375 QQmlPropertyPrivate::setBinding(d->vCenterProp, 0);
1377 if (d->applyOrigBaseline || (combined & QQuickAnchors::BaselineAnchor)) {
1378 targetPrivate->anchors()->resetBaseline();
1379 QQmlPropertyPrivate::setBinding(d->baselineProp, 0);
1383 bool QQuickAnchorChanges::override(QQuickActionEvent*other)
1385 if (other->type() != AnchorChanges)
1387 if (static_cast<QQuickActionEvent*>(this) == other)
1389 if (static_cast<QQuickAnchorChanges*>(other)->object() == object())
1394 void QQuickAnchorChanges::rewind()
1396 Q_D(QQuickAnchorChanges);
1400 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1402 //restore previous values (but not previous bindings, i.e. anchors)
1403 d->target->setX(d->rewindX);
1404 d->target->setY(d->rewindY);
1405 if (targetPrivate->widthValid) {
1406 d->target->setWidth(d->rewindWidth);
1408 if (targetPrivate->heightValid) {
1409 d->target->setHeight(d->rewindHeight);
1413 void QQuickAnchorChanges::saveCurrentValues()
1415 Q_D(QQuickAnchorChanges);
1419 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1420 d->rewindLeft = targetPrivate->anchors()->left();
1421 d->rewindRight = targetPrivate->anchors()->right();
1422 d->rewindHCenter = targetPrivate->anchors()->horizontalCenter();
1423 d->rewindTop = targetPrivate->anchors()->top();
1424 d->rewindBottom = targetPrivate->anchors()->bottom();
1425 d->rewindVCenter = targetPrivate->anchors()->verticalCenter();
1426 d->rewindBaseline = targetPrivate->anchors()->baseline();
1428 d->rewindX = d->target->x();
1429 d->rewindY = d->target->y();
1430 d->rewindWidth = d->target->width();
1431 d->rewindHeight = d->target->height();
1434 void QQuickAnchorChanges::saveTargetValues()
1436 Q_D(QQuickAnchorChanges);
1440 d->toX = d->target->x();
1441 d->toY = d->target->y();
1442 d->toWidth = d->target->width();
1443 d->toHeight = d->target->height();
1446 #include <moc_qquickstateoperations_p.cpp>