Doc: Moving Qt Quick docs for new doc structure
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickstateoperations.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickstateoperations_p.h"
43 #include "qquickitem_p.h"
44
45 #include <private/qquickstate_p_p.h>
46
47 #include <QtQml/qqmlinfo.h>
48 #include <QtCore/qmath.h>
49
50 QT_BEGIN_NAMESPACE
51
52 class QQuickParentChangePrivate : public QQuickStateOperationPrivate
53 {
54     Q_DECLARE_PUBLIC(QQuickParentChange)
55 public:
56     QQuickParentChangePrivate() : target(0), parent(0), origParent(0), origStackBefore(0),
57         rewindParent(0), rewindStackBefore(0) {}
58
59     QQuickItem *target;
60     QQmlGuard<QQuickItem> parent;
61     QQmlGuard<QQuickItem> origParent;
62     QQmlGuard<QQuickItem> origStackBefore;
63     QQuickItem *rewindParent;
64     QQuickItem *rewindStackBefore;
65
66     QQmlNullableValue<QQmlScriptString> xString;
67     QQmlNullableValue<QQmlScriptString> yString;
68     QQmlNullableValue<QQmlScriptString> widthString;
69     QQmlNullableValue<QQmlScriptString> heightString;
70     QQmlNullableValue<QQmlScriptString> scaleString;
71     QQmlNullableValue<QQmlScriptString> rotationString;
72
73     void doChange(QQuickItem *targetParent, QQuickItem *stackBefore = 0);
74 };
75
76 void QQuickParentChangePrivate::doChange(QQuickItem *targetParent, QQuickItem *stackBefore)
77 {
78     if (targetParent && target && target->parentItem()) {
79         Q_Q(QQuickParentChange);
80         bool ok;
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");
84             ok = false;
85         }
86
87         qreal scale = 1;
88         qreal rotation = 0;
89         bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
90         if (ok && !isRotate) {
91             if (transform.m11() == transform.m22())
92                 scale = transform.m11();
93             else {
94                 qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
95                 ok = false;
96             }
97         } else if (ok && isRotate) {
98             if (transform.m11() == transform.m22())
99                 scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
100             else {
101                 qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
102                 ok = false;
103             }
104
105             if (scale != 0)
106                 rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
107             else {
108                 qmlInfo(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0");
109                 ok = false;
110             }
111         }
112
113         const QPointF &point = transform.map(QPointF(target->x(),target->y()));
114         qreal x = point.x();
115         qreal y = point.y();
116
117         // setParentItem will update the transformOriginPoint if needed
118         target->setParentItem(targetParent);
119
120         if (ok && target->transformOrigin() != QQuickItem::TopLeft) {
121             qreal tempxt = target->transformOriginPoint().x();
122             qreal tempyt = target->transformOriginPoint().y();
123             QTransform t;
124             t.translate(-tempxt, -tempyt);
125             t.rotate(rotation);
126             t.scale(scale, scale);
127             t.translate(tempxt, tempyt);
128             const QPointF &offset = t.map(QPointF(0,0));
129             x += offset.x();
130             y += offset.y();
131         }
132
133         if (ok) {
134             //qDebug() << x << y << rotation << scale;
135             target->setPos(QPointF(x, y));
136             target->setRotation(target->rotation() + rotation);
137             target->setScale(target->scale() * scale);
138         }
139     } else if (target) {
140         target->setParentItem(targetParent);
141     }
142
143     //restore the original stack position.
144     //### if stackBefore has also been reparented this won't work
145     if (stackBefore)
146         target->stackBefore(stackBefore);
147 }
148
149 /*!
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.
154
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.
158
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).
163
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.
167
168     \snippet doc/snippets/qml/parentchange.qml 0
169
170     \image parentchange.png
171
172     You can specify at which point in a transition you want a ParentChange to occur by
173     using a ParentAnimation.
174
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).
177 */
178
179 QQuickParentChange::QQuickParentChange(QObject *parent)
180     : QQuickStateOperation(*(new QQuickParentChangePrivate), parent)
181 {
182 }
183
184 QQuickParentChange::~QQuickParentChange()
185 {
186 }
187
188 /*!
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.
197 */
198 QQmlScriptString QQuickParentChange::x() const
199 {
200     Q_D(const QQuickParentChange);
201     return d->xString.value;
202 }
203
204 void QQuickParentChange::setX(QQmlScriptString x)
205 {
206     Q_D(QQuickParentChange);
207     d->xString = x;
208 }
209
210 bool QQuickParentChange::xIsSet() const
211 {
212     Q_D(const QQuickParentChange);
213     return d->xString.isValid();
214 }
215
216 QQmlScriptString QQuickParentChange::y() const
217 {
218     Q_D(const QQuickParentChange);
219     return d->yString.value;
220 }
221
222 void QQuickParentChange::setY(QQmlScriptString y)
223 {
224     Q_D(QQuickParentChange);
225     d->yString = y;
226 }
227
228 bool QQuickParentChange::yIsSet() const
229 {
230     Q_D(const QQuickParentChange);
231     return d->yString.isValid();
232 }
233
234 QQmlScriptString QQuickParentChange::width() const
235 {
236     Q_D(const QQuickParentChange);
237     return d->widthString.value;
238 }
239
240 void QQuickParentChange::setWidth(QQmlScriptString width)
241 {
242     Q_D(QQuickParentChange);
243     d->widthString = width;
244 }
245
246 bool QQuickParentChange::widthIsSet() const
247 {
248     Q_D(const QQuickParentChange);
249     return d->widthString.isValid();
250 }
251
252 QQmlScriptString QQuickParentChange::height() const
253 {
254     Q_D(const QQuickParentChange);
255     return d->heightString.value;
256 }
257
258 void QQuickParentChange::setHeight(QQmlScriptString height)
259 {
260     Q_D(QQuickParentChange);
261     d->heightString = height;
262 }
263
264 bool QQuickParentChange::heightIsSet() const
265 {
266     Q_D(const QQuickParentChange);
267     return d->heightString.isValid();
268 }
269
270 QQmlScriptString QQuickParentChange::scale() const
271 {
272     Q_D(const QQuickParentChange);
273     return d->scaleString.value;
274 }
275
276 void QQuickParentChange::setScale(QQmlScriptString scale)
277 {
278     Q_D(QQuickParentChange);
279     d->scaleString = scale;
280 }
281
282 bool QQuickParentChange::scaleIsSet() const
283 {
284     Q_D(const QQuickParentChange);
285     return d->scaleString.isValid();
286 }
287
288 QQmlScriptString QQuickParentChange::rotation() const
289 {
290     Q_D(const QQuickParentChange);
291     return d->rotationString.value;
292 }
293
294 void QQuickParentChange::setRotation(QQmlScriptString rotation)
295 {
296     Q_D(QQuickParentChange);
297     d->rotationString = rotation;
298 }
299
300 bool QQuickParentChange::rotationIsSet() const
301 {
302     Q_D(const QQuickParentChange);
303     return d->rotationString.isValid();
304 }
305
306 QQuickItem *QQuickParentChange::originalParent() const
307 {
308     Q_D(const QQuickParentChange);
309     return d->origParent;
310 }
311
312 /*!
313     \qmlproperty Item ParentChange::target
314     This property holds the item to be reparented
315 */
316 QQuickItem *QQuickParentChange::object() const
317 {
318     Q_D(const QQuickParentChange);
319     return d->target;
320 }
321
322 void QQuickParentChange::setObject(QQuickItem *target)
323 {
324     Q_D(QQuickParentChange);
325     d->target = target;
326 }
327
328 /*!
329     \qmlproperty Item ParentChange::parent
330     This property holds the new parent for the item in this state.
331 */
332 QQuickItem *QQuickParentChange::parent() const
333 {
334     Q_D(const QQuickParentChange);
335     return d->parent;
336 }
337
338 void QQuickParentChange::setParent(QQuickItem *parent)
339 {
340     Q_D(QQuickParentChange);
341     d->parent = parent;
342 }
343
344 QQuickStateOperation::ActionList QQuickParentChange::actions()
345 {
346     Q_D(QQuickParentChange);
347     if (!d->target || !d->parent)
348         return ActionList();
349
350     ActionList actions;
351
352     QQuickAction a;
353     a.event = this;
354     actions << a;
355
356     if (d->xString.isValid()) {
357         bool ok = false;
358         QString script = d->xString.value.script();
359         qreal x = script.toFloat(&ok);
360         if (ok) {
361             QQuickAction xa(d->target, QLatin1String("x"), x);
362             actions << xa;
363         } else {
364             QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
365             QQmlProperty property(d->target, QLatin1String("x"));
366             newBinding->setTarget(property);
367             QQuickAction xa;
368             xa.property = property;
369             xa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
370             xa.fromValue = xa.property.read();
371             xa.deletableToBinding = true;
372             actions << xa;
373         }
374     }
375
376     if (d->yString.isValid()) {
377         bool ok = false;
378         QString script = d->yString.value.script();
379         qreal y = script.toFloat(&ok);
380         if (ok) {
381             QQuickAction ya(d->target, QLatin1String("y"), y);
382             actions << ya;
383         } else {
384             QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
385             QQmlProperty property(d->target, QLatin1String("y"));
386             newBinding->setTarget(property);
387             QQuickAction ya;
388             ya.property = property;
389             ya.toBinding = QQmlAbstractBinding::getPointer(newBinding);
390             ya.fromValue = ya.property.read();
391             ya.deletableToBinding = true;
392             actions << ya;
393         }
394     }
395
396     if (d->scaleString.isValid()) {
397         bool ok = false;
398         QString script = d->scaleString.value.script();
399         qreal scale = script.toFloat(&ok);
400         if (ok) {
401             QQuickAction sa(d->target, QLatin1String("scale"), scale);
402             actions << sa;
403         } else {
404             QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
405             QQmlProperty property(d->target, QLatin1String("scale"));
406             newBinding->setTarget(property);
407             QQuickAction sa;
408             sa.property = property;
409             sa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
410             sa.fromValue = sa.property.read();
411             sa.deletableToBinding = true;
412             actions << sa;
413         }
414     }
415
416     if (d->rotationString.isValid()) {
417         bool ok = false;
418         QString script = d->rotationString.value.script();
419         qreal rotation = script.toFloat(&ok);
420         if (ok) {
421             QQuickAction ra(d->target, QLatin1String("rotation"), rotation);
422             actions << ra;
423         } else {
424             QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
425             QQmlProperty property(d->target, QLatin1String("rotation"));
426             newBinding->setTarget(property);
427             QQuickAction ra;
428             ra.property = property;
429             ra.toBinding = QQmlAbstractBinding::getPointer(newBinding);
430             ra.fromValue = ra.property.read();
431             ra.deletableToBinding = true;
432             actions << ra;
433         }
434     }
435
436     if (d->widthString.isValid()) {
437         bool ok = false;
438         QString script = d->widthString.value.script();
439         qreal width = script.toFloat(&ok);
440         if (ok) {
441             QQuickAction wa(d->target, QLatin1String("width"), width);
442             actions << wa;
443         } else {
444             QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
445             QQmlProperty property(d->target, QLatin1String("width"));
446             newBinding->setTarget(property);
447             QQuickAction wa;
448             wa.property = property;
449             wa.toBinding = QQmlAbstractBinding::getPointer(newBinding);
450             wa.fromValue = wa.property.read();
451             wa.deletableToBinding = true;
452             actions << wa;
453         }
454     }
455
456     if (d->heightString.isValid()) {
457         bool ok = false;
458         QString script = d->heightString.value.script();
459         qreal height = script.toFloat(&ok);
460         if (ok) {
461             QQuickAction ha(d->target, QLatin1String("height"), height);
462             actions << ha;
463         } else {
464             QQmlBinding *newBinding = new QQmlBinding(script, d->target, qmlContext(this));
465             QQmlProperty property(d->target, QLatin1String("height"));
466             newBinding->setTarget(property);
467             QQuickAction ha;
468             ha.property = property;
469             ha.toBinding = QQmlAbstractBinding::getPointer(newBinding);
470             ha.fromValue = ha.property.read();
471             ha.deletableToBinding = true;
472             actions << ha;
473         }
474     }
475
476     return actions;
477 }
478
479 void QQuickParentChange::saveOriginals()
480 {
481     Q_D(QQuickParentChange);
482     saveCurrentValues();
483     d->origParent = d->rewindParent;
484     d->origStackBefore = d->rewindStackBefore;
485 }
486
487 /*void QQuickParentChange::copyOriginals(QQuickActionEvent *other)
488 {
489     Q_D(QQuickParentChange);
490     QQuickParentChange *pc = static_cast<QQuickParentChange*>(other);
491
492     d->origParent = pc->d_func()->rewindParent;
493     d->origStackBefore = pc->d_func()->rewindStackBefore;
494
495     saveCurrentValues();
496 }*/
497
498 void QQuickParentChange::execute(Reason)
499 {
500     Q_D(QQuickParentChange);
501     d->doChange(d->parent);
502 }
503
504 bool QQuickParentChange::isReversable()
505 {
506     return true;
507 }
508
509 void QQuickParentChange::reverse(Reason)
510 {
511     Q_D(QQuickParentChange);
512     d->doChange(d->origParent, d->origStackBefore);
513 }
514
515 QQuickActionEvent::EventType QQuickParentChange::type() const
516 {
517     return ParentChange;
518 }
519
520 bool QQuickParentChange::override(QQuickActionEvent*other)
521 {
522     Q_D(QQuickParentChange);
523     if (other->type() != ParentChange)
524         return false;
525     if (QQuickParentChange *otherPC = static_cast<QQuickParentChange*>(other))
526         return (d->target == otherPC->object());
527     return false;
528 }
529
530 void QQuickParentChange::saveCurrentValues()
531 {
532     Q_D(QQuickParentChange);
533     if (!d->target) {
534         d->rewindParent = 0;
535         d->rewindStackBefore = 0;
536         return;
537     }
538
539     d->rewindParent = d->target->parentItem();
540     d->rewindStackBefore = 0;
541
542     if (!d->rewindParent)
543         return;
544
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);
549             break;
550         }
551     }
552 }
553
554 void QQuickParentChange::rewind()
555 {
556     Q_D(QQuickParentChange);
557     d->doChange(d->rewindParent, d->rewindStackBefore);
558 }
559
560 /*!
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.
565
566     The AnchorChanges element is used to modify the anchors of an item in a \l State.
567
568     AnchorChanges cannot be used to modify the margins on an item. For this, use
569     PropertyChanges intead.
570
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
573     PropertyChanges:
574
575     \snippet doc/snippets/qml/anchorchanges.qml 0
576
577     \image anchorchanges.png
578
579     AnchorChanges can be animated using AnchorAnimation.
580     \qml
581     //animate our anchor changes
582     Transition {
583         AnchorAnimation {}
584     }
585     \endqml
586
587     Changes to anchor margins can be animated using NumberAnimation.
588
589     For more information on anchors see \l {anchor-layout}{Anchor Layouts}.
590 */
591
592 class QQuickAnchorSetPrivate : public QObjectPrivate
593 {
594     Q_DECLARE_PUBLIC(QQuickAnchorSet)
595 public:
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)*/
600     {
601     }
602
603     QQuickAnchors::Anchors usedAnchors;
604     QQuickAnchors::Anchors resetAnchors;
605
606     QQuickItem *fill;
607     QQuickItem *centerIn;
608
609     QQmlScriptString leftScript;
610     QQmlScriptString rightScript;
611     QQmlScriptString topScript;
612     QQmlScriptString bottomScript;
613     QQmlScriptString hCenterScript;
614     QQmlScriptString vCenterScript;
615     QQmlScriptString baselineScript;
616
617     /*qreal leftMargin;
618     qreal rightMargin;
619     qreal topMargin;
620     qreal bottomMargin;
621     qreal margins;
622     qreal vCenterOffset;
623     qreal hCenterOffset;
624     qreal baselineOffset;*/
625 };
626
627 QQuickAnchorSet::QQuickAnchorSet(QObject *parent)
628   : QObject(*new QQuickAnchorSetPrivate, parent)
629 {
630 }
631
632 QQuickAnchorSet::~QQuickAnchorSet()
633 {
634 }
635
636 QQmlScriptString QQuickAnchorSet::top() const
637 {
638     Q_D(const QQuickAnchorSet);
639     return d->topScript;
640 }
641
642 void QQuickAnchorSet::setTop(const QQmlScriptString &edge)
643 {
644     Q_D(QQuickAnchorSet);
645     d->usedAnchors |= QQuickAnchors::TopAnchor;
646     d->topScript = edge;
647     if (edge.script() == QLatin1String("undefined"))
648         resetTop();
649 }
650
651 void QQuickAnchorSet::resetTop()
652 {
653     Q_D(QQuickAnchorSet);
654     d->usedAnchors &= ~QQuickAnchors::TopAnchor;
655     d->resetAnchors |= QQuickAnchors::TopAnchor;
656 }
657
658 QQmlScriptString QQuickAnchorSet::bottom() const
659 {
660     Q_D(const QQuickAnchorSet);
661     return d->bottomScript;
662 }
663
664 void QQuickAnchorSet::setBottom(const QQmlScriptString &edge)
665 {
666     Q_D(QQuickAnchorSet);
667     d->usedAnchors |= QQuickAnchors::BottomAnchor;
668     d->bottomScript = edge;
669     if (edge.script() == QLatin1String("undefined"))
670         resetBottom();
671 }
672
673 void QQuickAnchorSet::resetBottom()
674 {
675     Q_D(QQuickAnchorSet);
676     d->usedAnchors &= ~QQuickAnchors::BottomAnchor;
677     d->resetAnchors |= QQuickAnchors::BottomAnchor;
678 }
679
680 QQmlScriptString QQuickAnchorSet::verticalCenter() const
681 {
682     Q_D(const QQuickAnchorSet);
683     return d->vCenterScript;
684 }
685
686 void QQuickAnchorSet::setVerticalCenter(const QQmlScriptString &edge)
687 {
688     Q_D(QQuickAnchorSet);
689     d->usedAnchors |= QQuickAnchors::VCenterAnchor;
690     d->vCenterScript = edge;
691     if (edge.script() == QLatin1String("undefined"))
692         resetVerticalCenter();
693 }
694
695 void QQuickAnchorSet::resetVerticalCenter()
696 {
697     Q_D(QQuickAnchorSet);
698     d->usedAnchors &= ~QQuickAnchors::VCenterAnchor;
699     d->resetAnchors |= QQuickAnchors::VCenterAnchor;
700 }
701
702 QQmlScriptString QQuickAnchorSet::baseline() const
703 {
704     Q_D(const QQuickAnchorSet);
705     return d->baselineScript;
706 }
707
708 void QQuickAnchorSet::setBaseline(const QQmlScriptString &edge)
709 {
710     Q_D(QQuickAnchorSet);
711     d->usedAnchors |= QQuickAnchors::BaselineAnchor;
712     d->baselineScript = edge;
713     if (edge.script() == QLatin1String("undefined"))
714         resetBaseline();
715 }
716
717 void QQuickAnchorSet::resetBaseline()
718 {
719     Q_D(QQuickAnchorSet);
720     d->usedAnchors &= ~QQuickAnchors::BaselineAnchor;
721     d->resetAnchors |= QQuickAnchors::BaselineAnchor;
722 }
723
724 QQmlScriptString QQuickAnchorSet::left() const
725 {
726     Q_D(const QQuickAnchorSet);
727     return d->leftScript;
728 }
729
730 void QQuickAnchorSet::setLeft(const QQmlScriptString &edge)
731 {
732     Q_D(QQuickAnchorSet);
733     d->usedAnchors |= QQuickAnchors::LeftAnchor;
734     d->leftScript = edge;
735     if (edge.script() == QLatin1String("undefined"))
736         resetLeft();
737 }
738
739 void QQuickAnchorSet::resetLeft()
740 {
741     Q_D(QQuickAnchorSet);
742     d->usedAnchors &= ~QQuickAnchors::LeftAnchor;
743     d->resetAnchors |= QQuickAnchors::LeftAnchor;
744 }
745
746 QQmlScriptString QQuickAnchorSet::right() const
747 {
748     Q_D(const QQuickAnchorSet);
749     return d->rightScript;
750 }
751
752 void QQuickAnchorSet::setRight(const QQmlScriptString &edge)
753 {
754     Q_D(QQuickAnchorSet);
755     d->usedAnchors |= QQuickAnchors::RightAnchor;
756     d->rightScript = edge;
757     if (edge.script() == QLatin1String("undefined"))
758         resetRight();
759 }
760
761 void QQuickAnchorSet::resetRight()
762 {
763     Q_D(QQuickAnchorSet);
764     d->usedAnchors &= ~QQuickAnchors::RightAnchor;
765     d->resetAnchors |= QQuickAnchors::RightAnchor;
766 }
767
768 QQmlScriptString QQuickAnchorSet::horizontalCenter() const
769 {
770     Q_D(const QQuickAnchorSet);
771     return d->hCenterScript;
772 }
773
774 void QQuickAnchorSet::setHorizontalCenter(const QQmlScriptString &edge)
775 {
776     Q_D(QQuickAnchorSet);
777     d->usedAnchors |= QQuickAnchors::HCenterAnchor;
778     d->hCenterScript = edge;
779     if (edge.script() == QLatin1String("undefined"))
780         resetHorizontalCenter();
781 }
782
783 void QQuickAnchorSet::resetHorizontalCenter()
784 {
785     Q_D(QQuickAnchorSet);
786     d->usedAnchors &= ~QQuickAnchors::HCenterAnchor;
787     d->resetAnchors |= QQuickAnchors::HCenterAnchor;
788 }
789
790 QQuickItem *QQuickAnchorSet::fill() const
791 {
792     Q_D(const QQuickAnchorSet);
793     return d->fill;
794 }
795
796 void QQuickAnchorSet::setFill(QQuickItem *f)
797 {
798     Q_D(QQuickAnchorSet);
799     d->fill = f;
800 }
801
802 void QQuickAnchorSet::resetFill()
803 {
804     setFill(0);
805 }
806
807 QQuickItem *QQuickAnchorSet::centerIn() const
808 {
809     Q_D(const QQuickAnchorSet);
810     return d->centerIn;
811 }
812
813 void QQuickAnchorSet::setCenterIn(QQuickItem* c)
814 {
815     Q_D(QQuickAnchorSet);
816     d->centerIn = c;
817 }
818
819 void QQuickAnchorSet::resetCenterIn()
820 {
821     setCenterIn(0);
822 }
823
824
825 class QQuickAnchorChangesPrivate : public QQuickStateOperationPrivate
826 {
827 public:
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)
835     {
836
837     }
838     ~QQuickAnchorChangesPrivate() { delete anchorSet; }
839
840     QQuickItem *target;
841     QQuickAnchorSet *anchorSet;
842
843     QQmlBinding *leftBinding;
844     QQmlBinding *rightBinding;
845     QQmlBinding *hCenterBinding;
846     QQmlBinding *topBinding;
847     QQmlBinding *bottomBinding;
848     QQmlBinding *vCenterBinding;
849     QQmlBinding *baselineBinding;
850
851     QQmlAbstractBinding *origLeftBinding;
852     QQmlAbstractBinding *origRightBinding;
853     QQmlAbstractBinding *origHCenterBinding;
854     QQmlAbstractBinding *origTopBinding;
855     QQmlAbstractBinding *origBottomBinding;
856     QQmlAbstractBinding *origVCenterBinding;
857     QQmlAbstractBinding *origBaselineBinding;
858
859     QQuickAnchorLine rewindLeft;
860     QQuickAnchorLine rewindRight;
861     QQuickAnchorLine rewindHCenter;
862     QQuickAnchorLine rewindTop;
863     QQuickAnchorLine rewindBottom;
864     QQuickAnchorLine rewindVCenter;
865     QQuickAnchorLine rewindBaseline;
866
867     qreal fromX;
868     qreal fromY;
869     qreal fromWidth;
870     qreal fromHeight;
871
872     qreal toX;
873     qreal toY;
874     qreal toWidth;
875     qreal toHeight;
876
877     qreal rewindX;
878     qreal rewindY;
879     qreal rewindWidth;
880     qreal rewindHeight;
881
882     bool applyOrigLeft;
883     bool applyOrigRight;
884     bool applyOrigHCenter;
885     bool applyOrigTop;
886     bool applyOrigBottom;
887     bool applyOrigVCenter;
888     bool applyOrigBaseline;
889
890     QQmlNullableValue<qreal> origWidth;
891     QQmlNullableValue<qreal> origHeight;
892     qreal origX;
893     qreal origY;
894
895     QList<QQmlAbstractBinding*> oldBindings;
896
897     QQmlProperty leftProp;
898     QQmlProperty rightProp;
899     QQmlProperty hCenterProp;
900     QQmlProperty topProp;
901     QQmlProperty bottomProp;
902     QQmlProperty vCenterProp;
903     QQmlProperty baselineProp;
904 };
905
906 QQuickAnchorChanges::QQuickAnchorChanges(QObject *parent)
907  : QQuickStateOperation(*(new QQuickAnchorChangesPrivate), parent)
908 {
909 }
910
911 QQuickAnchorChanges::~QQuickAnchorChanges()
912 {
913 }
914
915 QQuickAnchorChanges::ActionList QQuickAnchorChanges::actions()
916 {
917     Q_D(QQuickAnchorChanges);
918     d->leftBinding = d->rightBinding = d->hCenterBinding = d->topBinding
919                    = d->bottomBinding = d->vCenterBinding = d->baselineBinding = 0;
920
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"));
928
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);
932     }
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);
936     }
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);
940     }
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);
944     }
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);
948     }
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);
952     }
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);
956     }
957
958     QQuickAction a;
959     a.event = this;
960     return ActionList() << a;
961 }
962
963 QQuickAnchorSet *QQuickAnchorChanges::anchors()
964 {
965     Q_D(QQuickAnchorChanges);
966     return d->anchorSet;
967 }
968
969 /*!
970     \qmlproperty Item AnchorChanges::target
971     This property holds the \l Item for which the anchor changes will be applied.
972 */
973 QQuickItem *QQuickAnchorChanges::object() const
974 {
975     Q_D(const QQuickAnchorChanges);
976     return d->target;
977 }
978
979 void QQuickAnchorChanges::setObject(QQuickItem *target)
980 {
981     Q_D(QQuickAnchorChanges);
982     d->target = target;
983 }
984
985 /*!
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
993
994     These properties change the respective anchors of the item.
995
996     To reset an anchor you can assign \c undefined:
997     \qml
998     AnchorChanges {
999         target: myItem
1000         anchors.left: undefined          //remove myItem's left anchor
1001         anchors.right: otherItem.right
1002     }
1003     \endqml
1004 */
1005
1006 void QQuickAnchorChanges::execute(Reason reason)
1007 {
1008     Q_D(QQuickAnchorChanges);
1009     if (!d->target)
1010         return;
1011
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);
1018     }
1019     if (d->applyOrigRight) {
1020         if (!d->origRightBinding)
1021             targetPrivate->anchors()->resetRight();
1022         QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
1023     }
1024     if (d->applyOrigHCenter) {
1025         if (!d->origHCenterBinding)
1026             targetPrivate->anchors()->resetHorizontalCenter();
1027         QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
1028     }
1029     if (d->applyOrigTop) {
1030         if (!d->origTopBinding)
1031             targetPrivate->anchors()->resetTop();
1032         QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding);
1033     }
1034     if (d->applyOrigBottom) {
1035         if (!d->origBottomBinding)
1036             targetPrivate->anchors()->resetBottom();
1037         QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
1038     }
1039     if (d->applyOrigVCenter) {
1040         if (!d->origVCenterBinding)
1041             targetPrivate->anchors()->resetVerticalCenter();
1042         QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
1043     }
1044     if (d->applyOrigBaseline) {
1045         if (!d->origBaselineBinding)
1046             targetPrivate->anchors()->resetBaseline();
1047         QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
1048     }
1049
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);
1054             if (binding)
1055                 binding->destroy();
1056         }
1057         d->oldBindings.clear();
1058     }
1059
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);
1064     }
1065     if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::RightAnchor) {
1066         targetPrivate->anchors()->resetRight();
1067         QQmlPropertyPrivate::setBinding(d->rightProp, 0);
1068     }
1069     if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::HCenterAnchor) {
1070         targetPrivate->anchors()->resetHorizontalCenter();
1071         QQmlPropertyPrivate::setBinding(d->hCenterProp, 0);
1072     }
1073     if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::TopAnchor) {
1074         targetPrivate->anchors()->resetTop();
1075         QQmlPropertyPrivate::setBinding(d->topProp, 0);
1076     }
1077     if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BottomAnchor) {
1078         targetPrivate->anchors()->resetBottom();
1079         QQmlPropertyPrivate::setBinding(d->bottomProp, 0);
1080     }
1081     if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::VCenterAnchor) {
1082         targetPrivate->anchors()->resetVerticalCenter();
1083         QQmlPropertyPrivate::setBinding(d->vCenterProp, 0);
1084     }
1085     if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BaselineAnchor) {
1086         targetPrivate->anchors()->resetBaseline();
1087         QQmlPropertyPrivate::setBinding(d->baselineProp, 0);
1088     }
1089
1090     //set any anchors that have been specified
1091     if (d->leftBinding)
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);
1097     if (d->topBinding)
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);
1105 }
1106
1107 bool QQuickAnchorChanges::isReversable()
1108 {
1109     return true;
1110 }
1111
1112 void QQuickAnchorChanges::reverse(Reason reason)
1113 {
1114     Q_D(QQuickAnchorChanges);
1115     if (!d->target)
1116         return;
1117
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;
1125         }
1126     }
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;
1132         }
1133     }
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;
1139         }
1140     }
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;
1146         }
1147     }
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;
1153         }
1154     }
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;
1160         }
1161     }
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;
1167         }
1168     }
1169
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);
1185
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;
1191
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);
1202
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);
1215
1216     if (stateHAnchors && !origHAnchors)
1217         d->target->setX(d->origX);
1218
1219     if (stateVAnchors && !origVAnchors)
1220         d->target->setY(d->origY);
1221 }
1222
1223 QQuickActionEvent::EventType QQuickAnchorChanges::type() const
1224 {
1225     return AnchorChanges;
1226 }
1227
1228 QList<QQuickAction> QQuickAnchorChanges::additionalActions()
1229 {
1230     Q_D(QQuickAnchorChanges);
1231     QList<QQuickAction> extra;
1232
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;
1236
1237     if (d->target) {
1238         QQuickAction a;
1239         if (hChange && d->fromX != d->toX) {
1240             a.property = QQmlProperty(d->target, QLatin1String("x"));
1241             a.toValue = d->toX;
1242             extra << a;
1243         }
1244         if (vChange && d->fromY != d->toY) {
1245             a.property = QQmlProperty(d->target, QLatin1String("y"));
1246             a.toValue = d->toY;
1247             extra << a;
1248         }
1249         if (hChange && d->fromWidth != d->toWidth) {
1250             a.property = QQmlProperty(d->target, QLatin1String("width"));
1251             a.toValue = d->toWidth;
1252             extra << a;
1253         }
1254         if (vChange && d->fromHeight != d->toHeight) {
1255             a.property = QQmlProperty(d->target, QLatin1String("height"));
1256             a.toValue = d->toHeight;
1257             extra << a;
1258         }
1259     }
1260
1261     return extra;
1262 }
1263
1264 bool QQuickAnchorChanges::changesBindings()
1265 {
1266     return true;
1267 }
1268
1269 void QQuickAnchorChanges::saveOriginals()
1270 {
1271     Q_D(QQuickAnchorChanges);
1272     if (!d->target)
1273         return;
1274
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);
1282
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();
1290
1291     d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop
1292       = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false;
1293
1294     saveCurrentValues();
1295 }
1296
1297 void QQuickAnchorChanges::copyOriginals(QQuickActionEvent *other)
1298 {
1299     Q_D(QQuickAnchorChanges);
1300     QQuickAnchorChanges *ac = static_cast<QQuickAnchorChanges*>(other);
1301     QQuickAnchorChangesPrivate *acp = ac->d_func();
1302
1303     QQuickAnchors::Anchors combined = acp->anchorSet->d_func()->usedAnchors |
1304                                             acp->anchorSet->d_func()->resetAnchors;
1305
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);
1314
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;
1322
1323     d->origWidth = acp->origWidth;
1324     d->origHeight = acp->origHeight;
1325     d->origX = acp->origX;
1326     d->origY = acp->origY;
1327
1328     d->oldBindings.clear();
1329     d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding
1330                 << acp->topBinding << acp->bottomBinding << acp->baselineBinding;
1331
1332     saveCurrentValues();
1333 }
1334
1335 void QQuickAnchorChanges::clearBindings()
1336 {
1337     Q_D(QQuickAnchorChanges);
1338     if (!d->target)
1339         return;
1340
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();
1346
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);
1356     }
1357     if (d->applyOrigRight || (combined & QQuickAnchors::RightAnchor)) {
1358         targetPrivate->anchors()->resetRight();
1359         QQmlPropertyPrivate::setBinding(d->rightProp, 0);
1360     }
1361     if (d->applyOrigHCenter || (combined & QQuickAnchors::HCenterAnchor)) {
1362         targetPrivate->anchors()->resetHorizontalCenter();
1363         QQmlPropertyPrivate::setBinding(d->hCenterProp, 0);
1364     }
1365     if (d->applyOrigTop || (combined & QQuickAnchors::TopAnchor)) {
1366         targetPrivate->anchors()->resetTop();
1367         QQmlPropertyPrivate::setBinding(d->topProp, 0);
1368     }
1369     if (d->applyOrigBottom || (combined & QQuickAnchors::BottomAnchor)) {
1370         targetPrivate->anchors()->resetBottom();
1371         QQmlPropertyPrivate::setBinding(d->bottomProp, 0);
1372     }
1373     if (d->applyOrigVCenter || (combined & QQuickAnchors::VCenterAnchor)) {
1374         targetPrivate->anchors()->resetVerticalCenter();
1375         QQmlPropertyPrivate::setBinding(d->vCenterProp, 0);
1376     }
1377     if (d->applyOrigBaseline || (combined & QQuickAnchors::BaselineAnchor)) {
1378         targetPrivate->anchors()->resetBaseline();
1379         QQmlPropertyPrivate::setBinding(d->baselineProp, 0);
1380     }
1381 }
1382
1383 bool QQuickAnchorChanges::override(QQuickActionEvent*other)
1384 {
1385     if (other->type() != AnchorChanges)
1386         return false;
1387     if (static_cast<QQuickActionEvent*>(this) == other)
1388         return true;
1389     if (static_cast<QQuickAnchorChanges*>(other)->object() == object())
1390         return true;
1391     return false;
1392 }
1393
1394 void QQuickAnchorChanges::rewind()
1395 {
1396     Q_D(QQuickAnchorChanges);
1397     if (!d->target)
1398         return;
1399
1400     QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1401
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);
1407     }
1408     if (targetPrivate->heightValid) {
1409         d->target->setHeight(d->rewindHeight);
1410     }
1411 }
1412
1413 void QQuickAnchorChanges::saveCurrentValues()
1414 {
1415     Q_D(QQuickAnchorChanges);
1416     if (!d->target)
1417         return;
1418
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();
1427
1428     d->rewindX = d->target->x();
1429     d->rewindY = d->target->y();
1430     d->rewindWidth = d->target->width();
1431     d->rewindHeight = d->target->height();
1432 }
1433
1434 void QQuickAnchorChanges::saveTargetValues()
1435 {
1436     Q_D(QQuickAnchorChanges);
1437     if (!d->target)
1438         return;
1439
1440     d->toX = d->target->x();
1441     d->toY = d->target->y();
1442     d->toWidth = d->target->width();
1443     d->toHeight = d->target->height();
1444 }
1445
1446 #include <moc_qquickstateoperations_p.cpp>
1447
1448 QT_END_NAMESPACE
1449