Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / qtquick1 / util / qdeclarativestateoperations.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 QtDeclarative 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 "QtQuick1/private/qdeclarativestateoperations_p.h"
43 #include "QtQuick1/private/qdeclarativeanchors_p_p.h"
44 #include "QtQuick1/private/qdeclarativeitem_p.h"
45 #include "QtDeclarative/private/qdeclarativenullablevalue_p_p.h"
46
47 #include <QtDeclarative/qdeclarative.h>
48 #include <QtDeclarative/qdeclarativecontext.h>
49 #include <QtDeclarative/qdeclarativeexpression.h>
50 #include <QtDeclarative/qdeclarativeinfo.h>
51 #include <QtDeclarative/private/qdeclarativeguard_p.h>
52 #include <QtDeclarative/private/qdeclarativecontext_p.h>
53 #include <QtDeclarative/private/qdeclarativeproperty_p.h>
54 #include <QtDeclarative/private/qdeclarativebinding_p.h>
55 #include <QtQuick1/private/qdeclarativestate_p_p.h>
56
57 #include <QtCore/qdebug.h>
58 #include <QtWidgets/qgraphicsitem.h>
59 #include <QtCore/qmath.h>
60
61 #include <private/qobject_p.h>
62
63 QT_BEGIN_NAMESPACE
64
65
66
67 class QDeclarative1ParentChangePrivate : public QDeclarative1StateOperationPrivate
68 {
69     Q_DECLARE_PUBLIC(QDeclarative1ParentChange)
70 public:
71     QDeclarative1ParentChangePrivate() : target(0), parent(0), origParent(0), origStackBefore(0),
72         rewindParent(0), rewindStackBefore(0) {}
73
74     QDeclarativeItem *target;
75     QDeclarativeGuard<QDeclarativeItem> parent;
76     QDeclarativeGuard<QDeclarativeItem> origParent;
77     QDeclarativeGuard<QDeclarativeItem> origStackBefore;
78     QDeclarativeItem *rewindParent;
79     QDeclarativeItem *rewindStackBefore;
80
81     QDeclarativeNullableValue<QDeclarativeScriptString> xString;
82     QDeclarativeNullableValue<QDeclarativeScriptString> yString;
83     QDeclarativeNullableValue<QDeclarativeScriptString> widthString;
84     QDeclarativeNullableValue<QDeclarativeScriptString> heightString;
85     QDeclarativeNullableValue<QDeclarativeScriptString> scaleString;
86     QDeclarativeNullableValue<QDeclarativeScriptString> rotationString;
87
88     QDeclarativeNullableValue<qreal> x;
89     QDeclarativeNullableValue<qreal> y;
90     QDeclarativeNullableValue<qreal> width;
91     QDeclarativeNullableValue<qreal> height;
92     QDeclarativeNullableValue<qreal> scale;
93     QDeclarativeNullableValue<qreal> rotation;
94
95     void doChange(QDeclarativeItem *targetParent, QDeclarativeItem *stackBefore = 0);
96 };
97
98 void QDeclarative1ParentChangePrivate::doChange(QDeclarativeItem *targetParent, QDeclarativeItem *stackBefore)
99 {
100     if (targetParent && target && target->parentItem()) {
101         Q_Q(QDeclarative1ParentChange);
102         bool ok;
103         const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok);
104         if (transform.type() >= QTransform::TxShear || !ok) {
105             qmlInfo(q) << QDeclarative1ParentChange::tr("Unable to preserve appearance under complex transform");
106             ok = false;
107         }
108
109         qreal scale = 1;
110         qreal rotation = 0;
111         bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
112         if (ok && !isRotate) {
113             if (transform.m11() == transform.m22())
114                 scale = transform.m11();
115             else {
116                 qmlInfo(q) << QDeclarative1ParentChange::tr("Unable to preserve appearance under non-uniform scale");
117                 ok = false;
118             }
119         } else if (ok && isRotate) {
120             if (transform.m11() == transform.m22())
121                 scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
122             else {
123                 qmlInfo(q) << QDeclarative1ParentChange::tr("Unable to preserve appearance under non-uniform scale");
124                 ok = false;
125             }
126
127             if (scale != 0)
128                 rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
129             else {
130                 qmlInfo(q) << QDeclarative1ParentChange::tr("Unable to preserve appearance under scale of 0");
131                 ok = false;
132             }
133         }
134
135         const QPointF &point = transform.map(QPointF(target->x(),target->y()));
136         qreal x = point.x();
137         qreal y = point.y();
138
139         // setParentItem will update the transformOriginPoint if needed
140         target->setParentItem(targetParent);
141
142         if (ok && target->transformOrigin() != QDeclarativeItem::TopLeft) {
143             qreal tempxt = target->transformOriginPoint().x();
144             qreal tempyt = target->transformOriginPoint().y();
145             QTransform t;
146             t.translate(-tempxt, -tempyt);
147             t.rotate(rotation);
148             t.scale(scale, scale);
149             t.translate(tempxt, tempyt);
150             const QPointF &offset = t.map(QPointF(0,0));
151             x += offset.x();
152             y += offset.y();
153         }
154
155         if (ok) {
156             //qDebug() << x << y << rotation << scale;
157             target->setX(x);
158             target->setY(y);
159             target->setRotation(target->rotation() + rotation);
160             target->setScale(target->scale() * scale);
161         }
162     } else if (target) {
163         target->setParentItem(targetParent);
164     }
165
166     //restore the original stack position.
167     //### if stackBefore has also been reparented this won't work
168     if (stackBefore)
169         target->stackBefore(stackBefore);
170 }
171
172 /*!
173     \preliminary
174     \qmlclass ParentChange QDeclarative1ParentChange
175     \inqmlmodule QtQuick 1
176     \ingroup qml-state-elements
177     \brief The ParentChange element allows you to reparent an Item in a state change.
178
179     ParentChange reparents an item while preserving its visual appearance (position, size,
180     rotation, and scale) on screen. You can then specify a transition to move/resize/rotate/scale
181     the item to its final intended appearance.
182
183     ParentChange can only preserve visual appearance if no complex transforms are involved.
184     More specifically, it will not work if the transform property has been set for any
185     items involved in the reparenting (i.e. items in the common ancestor tree
186     for the original and new parent).
187
188     The example below displays a large red rectangle and a small blue rectangle, side by side. 
189     When the \c blueRect is clicked, it changes to the "reparented" state: its parent is changed to \c redRect and it is 
190     positioned at (10, 10) within the red rectangle, as specified in the ParentChange.
191
192     \snippet doc/src/snippets/qtquick1/parentchange.qml 0
193
194     \image parentchange.png
195
196     You can specify at which point in a transition you want a ParentChange to occur by
197     using a ParentAnimation.
198 */
199
200
201 QDeclarative1ParentChange::QDeclarative1ParentChange(QObject *parent)
202     : QDeclarative1StateOperation(*(new QDeclarative1ParentChangePrivate), parent)
203 {
204 }
205
206 QDeclarative1ParentChange::~QDeclarative1ParentChange()
207 {
208 }
209
210 /*!
211     \qmlproperty real QtQuick1::ParentChange::x
212     \qmlproperty real QtQuick1::ParentChange::y
213     \qmlproperty real QtQuick1::ParentChange::width
214     \qmlproperty real QtQuick1::ParentChange::height
215     \qmlproperty real QtQuick1::ParentChange::scale
216     \qmlproperty real QtQuick1::ParentChange::rotation
217     These properties hold the new position, size, scale, and rotation
218     for the item in this state.
219 */
220 QDeclarativeScriptString QDeclarative1ParentChange::x() const
221 {
222     Q_D(const QDeclarative1ParentChange);
223     return d->xString.value;
224 }
225
226 void tryReal(QDeclarativeNullableValue<qreal> &value, const QString &string)
227 {
228     bool ok = false;
229     qreal realValue = string.toFloat(&ok);
230     if (ok)
231         value = realValue;
232     else
233         value.invalidate();
234 }
235
236 void QDeclarative1ParentChange::setX(QDeclarativeScriptString x)
237 {
238     Q_D(QDeclarative1ParentChange);
239     d->xString = x;
240     tryReal(d->x, x.script());
241 }
242
243 bool QDeclarative1ParentChange::xIsSet() const
244 {
245     Q_D(const QDeclarative1ParentChange);
246     return d->xString.isValid();
247 }
248
249 QDeclarativeScriptString QDeclarative1ParentChange::y() const
250 {
251     Q_D(const QDeclarative1ParentChange);
252     return d->yString.value;
253 }
254
255 void QDeclarative1ParentChange::setY(QDeclarativeScriptString y)
256 {
257     Q_D(QDeclarative1ParentChange);
258     d->yString = y;
259     tryReal(d->y, y.script());
260 }
261
262 bool QDeclarative1ParentChange::yIsSet() const
263 {
264     Q_D(const QDeclarative1ParentChange);
265     return d->yString.isValid();
266 }
267
268 QDeclarativeScriptString QDeclarative1ParentChange::width() const
269 {
270     Q_D(const QDeclarative1ParentChange);
271     return d->widthString.value;
272 }
273
274 void QDeclarative1ParentChange::setWidth(QDeclarativeScriptString width)
275 {
276     Q_D(QDeclarative1ParentChange);
277     d->widthString = width;
278     tryReal(d->width, width.script());
279 }
280
281 bool QDeclarative1ParentChange::widthIsSet() const
282 {
283     Q_D(const QDeclarative1ParentChange);
284     return d->widthString.isValid();
285 }
286
287 QDeclarativeScriptString QDeclarative1ParentChange::height() const
288 {
289     Q_D(const QDeclarative1ParentChange);
290     return d->heightString.value;
291 }
292
293 void QDeclarative1ParentChange::setHeight(QDeclarativeScriptString height)
294 {
295     Q_D(QDeclarative1ParentChange);
296     d->heightString = height;
297     tryReal(d->height, height.script());
298 }
299
300 bool QDeclarative1ParentChange::heightIsSet() const
301 {
302     Q_D(const QDeclarative1ParentChange);
303     return d->heightString.isValid();
304 }
305
306 QDeclarativeScriptString QDeclarative1ParentChange::scale() const
307 {
308     Q_D(const QDeclarative1ParentChange);
309     return d->scaleString.value;
310 }
311
312 void QDeclarative1ParentChange::setScale(QDeclarativeScriptString scale)
313 {
314     Q_D(QDeclarative1ParentChange);
315     d->scaleString = scale;
316     tryReal(d->scale, scale.script());
317 }
318
319 bool QDeclarative1ParentChange::scaleIsSet() const
320 {
321     Q_D(const QDeclarative1ParentChange);
322     return d->scaleString.isValid();
323 }
324
325 QDeclarativeScriptString QDeclarative1ParentChange::rotation() const
326 {
327     Q_D(const QDeclarative1ParentChange);
328     return d->rotationString.value;
329 }
330
331 void QDeclarative1ParentChange::setRotation(QDeclarativeScriptString rotation)
332 {
333     Q_D(QDeclarative1ParentChange);
334     d->rotationString = rotation;
335     tryReal(d->rotation, rotation.script());
336 }
337
338 bool QDeclarative1ParentChange::rotationIsSet() const
339 {
340     Q_D(const QDeclarative1ParentChange);
341     return d->rotationString.isValid();
342 }
343
344 QDeclarativeItem *QDeclarative1ParentChange::originalParent() const
345 {
346     Q_D(const QDeclarative1ParentChange);
347     return d->origParent;
348 }
349
350 /*!
351     \qmlproperty Item QtQuick1::ParentChange::target
352     This property holds the item to be reparented
353 */
354
355 QDeclarativeItem *QDeclarative1ParentChange::object() const
356 {
357     Q_D(const QDeclarative1ParentChange);
358     return d->target;
359 }
360
361 void QDeclarative1ParentChange::setObject(QDeclarativeItem *target)
362 {
363     Q_D(QDeclarative1ParentChange);
364     d->target = target;
365 }
366
367 /*!
368     \qmlproperty Item QtQuick1::ParentChange::parent
369     This property holds the new parent for the item in this state.
370 */
371
372 QDeclarativeItem *QDeclarative1ParentChange::parent() const
373 {
374     Q_D(const QDeclarative1ParentChange);
375     return d->parent;
376 }
377
378 void QDeclarative1ParentChange::setParent(QDeclarativeItem *parent)
379 {
380     Q_D(QDeclarative1ParentChange);
381     d->parent = parent;
382 }
383
384 QDeclarative1StateOperation::ActionList QDeclarative1ParentChange::actions()
385 {
386     Q_D(QDeclarative1ParentChange);
387     if (!d->target || !d->parent)
388         return ActionList();
389
390     ActionList actions;
391
392     QDeclarative1Action a;
393     a.event = this;
394     actions << a;
395
396     QDeclarativeContext *ctxt = qmlContext(this);
397
398     if (d->xString.isValid()) {
399         if (d->x.isValid()) {
400             QDeclarative1Action xa(d->target, QLatin1String("x"), ctxt, d->x.value);
401             actions << xa;
402         } else {
403             QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->xString.value.script(), d->target, ctxt);
404             newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("x"), ctxt));
405             QDeclarative1Action xa;
406             xa.property = newBinding->property();
407             xa.toBinding = newBinding;
408             xa.fromValue = xa.property.read();
409             xa.deletableToBinding = true;
410             actions << xa;
411         }
412     }
413
414     if (d->yString.isValid()) {
415         if (d->y.isValid()) {
416             QDeclarative1Action ya(d->target, QLatin1String("y"), ctxt, d->y.value);
417             actions << ya;
418         } else {
419             QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->yString.value.script(), d->target, ctxt);
420             newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("y"), ctxt));
421             QDeclarative1Action ya;
422             ya.property = newBinding->property();
423             ya.toBinding = newBinding;
424             ya.fromValue = ya.property.read();
425             ya.deletableToBinding = true;
426             actions << ya;
427         }
428     }
429
430     if (d->scaleString.isValid()) {
431         if (d->scale.isValid()) {
432             QDeclarative1Action sa(d->target, QLatin1String("scale"), ctxt, d->scale.value);
433             actions << sa;
434         } else {
435             QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->scaleString.value.script(), d->target, ctxt);
436             newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("scale"), ctxt));
437             QDeclarative1Action sa;
438             sa.property = newBinding->property();
439             sa.toBinding = newBinding;
440             sa.fromValue = sa.property.read();
441             sa.deletableToBinding = true;
442             actions << sa;
443         }
444     }
445
446     if (d->rotationString.isValid()) {
447         if (d->rotation.isValid()) {
448             QDeclarative1Action ra(d->target, QLatin1String("rotation"), ctxt, d->rotation.value);
449             actions << ra;
450         } else {
451             QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->rotationString.value.script(), d->target, ctxt);
452             newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("rotation"), ctxt));
453             QDeclarative1Action ra;
454             ra.property = newBinding->property();
455             ra.toBinding = newBinding;
456             ra.fromValue = ra.property.read();
457             ra.deletableToBinding = true;
458             actions << ra;
459         }
460     }
461
462     if (d->widthString.isValid()) {
463         if (d->width.isValid()) {
464             QDeclarative1Action wa(d->target, QLatin1String("width"), ctxt, d->width.value);
465             actions << wa;
466         } else {
467             QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->widthString.value.script(), d->target, ctxt);
468             newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("width"), ctxt));
469             QDeclarative1Action wa;
470             wa.property = newBinding->property();
471             wa.toBinding = newBinding;
472             wa.fromValue = wa.property.read();
473             wa.deletableToBinding = true;
474             actions << wa;
475         }
476     }
477
478     if (d->heightString.isValid()) {
479         if (d->height.isValid()) {
480             QDeclarative1Action ha(d->target, QLatin1String("height"), ctxt, d->height.value);
481             actions << ha;
482         } else {
483             QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->heightString.value.script(), d->target, ctxt);
484             newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("height"), ctxt));
485             QDeclarative1Action ha;
486             ha.property = newBinding->property();
487             ha.toBinding = newBinding;
488             ha.fromValue = ha.property.read();
489             ha.deletableToBinding = true;
490             actions << ha;
491         }
492     }
493
494     return actions;
495 }
496
497 class AccessibleFxItem : public QDeclarativeItem
498 {
499     Q_OBJECT
500     Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeItem)
501 public:
502     int siblingIndex() {
503         Q_D(QDeclarativeItem);
504         return d->siblingIndex;
505     }
506 };
507
508 void QDeclarative1ParentChange::saveOriginals()
509 {
510     Q_D(QDeclarative1ParentChange);
511     saveCurrentValues();
512     d->origParent = d->rewindParent;
513     d->origStackBefore = d->rewindStackBefore;
514 }
515
516 /*void QDeclarative1ParentChange::copyOriginals(QDeclarative1ActionEvent *other)
517 {
518     Q_D(QDeclarative1ParentChange);
519     QDeclarative1ParentChange *pc = static_cast<QDeclarative1ParentChange*>(other);
520
521     d->origParent = pc->d_func()->rewindParent;
522     d->origStackBefore = pc->d_func()->rewindStackBefore;
523
524     saveCurrentValues();
525 }*/
526
527 void QDeclarative1ParentChange::execute(Reason)
528 {
529     Q_D(QDeclarative1ParentChange);
530     d->doChange(d->parent);
531 }
532
533 bool QDeclarative1ParentChange::isReversable()
534 {
535     return true;
536 }
537
538 void QDeclarative1ParentChange::reverse(Reason)
539 {
540     Q_D(QDeclarative1ParentChange);
541     d->doChange(d->origParent, d->origStackBefore);
542 }
543
544 QString QDeclarative1ParentChange::typeName() const
545 {
546     return QLatin1String("ParentChange");
547 }
548
549 bool QDeclarative1ParentChange::override(QDeclarative1ActionEvent*other)
550 {
551     Q_D(QDeclarative1ParentChange);
552     if (other->typeName() != QLatin1String("ParentChange"))
553         return false;
554     if (QDeclarative1ParentChange *otherPC = static_cast<QDeclarative1ParentChange*>(other))
555         return (d->target == otherPC->object());
556     return false;
557 }
558
559 void QDeclarative1ParentChange::saveCurrentValues()
560 {
561     Q_D(QDeclarative1ParentChange);
562     if (!d->target) {
563         d->rewindParent = 0;
564         d->rewindStackBefore = 0;
565         return;
566     }
567
568     d->rewindParent = d->target->parentItem();
569     d->rewindStackBefore = 0;
570
571     if (!d->rewindParent)
572         return;
573
574     //try to determine the item's original stack position so we can restore it
575     int siblingIndex = ((AccessibleFxItem*)d->target)->siblingIndex() + 1;
576     QList<QGraphicsItem*> children = d->rewindParent->childItems();
577     for (int i = 0; i < children.count(); ++i) {
578         QDeclarativeItem *child = qobject_cast<QDeclarativeItem*>(children.at(i));
579         if (!child)
580             continue;
581         if (((AccessibleFxItem*)child)->siblingIndex() == siblingIndex) {
582             d->rewindStackBefore = child;
583             break;
584         }
585     }
586 }
587
588 void QDeclarative1ParentChange::rewind()
589 {
590     Q_D(QDeclarative1ParentChange);
591     d->doChange(d->rewindParent, d->rewindStackBefore);
592 }
593
594 class QDeclarative1StateChangeScriptPrivate : public QDeclarative1StateOperationPrivate
595 {
596 public:
597     QDeclarative1StateChangeScriptPrivate() {}
598
599     QDeclarativeScriptString script;
600     QString name;
601 };
602
603 /*!
604     \qmlclass StateChangeScript QDeclarative1StateChangeScript
605     \inqmlmodule QtQuick 1
606     \ingroup qml-state-elements
607     \brief The StateChangeScript element allows you to run a script in a state.
608
609     A StateChangeScript is run upon entering a state. You can optionally use
610     ScriptAction to specify the point in the transition at which
611     the StateChangeScript should to be run.
612
613     \snippet snippets/declarative/states/statechangescript.qml state and transition
614
615     \sa ScriptAction
616 */
617
618 QDeclarative1StateChangeScript::QDeclarative1StateChangeScript(QObject *parent)
619 : QDeclarative1StateOperation(*(new QDeclarative1StateChangeScriptPrivate), parent)
620 {
621 }
622
623 QDeclarative1StateChangeScript::~QDeclarative1StateChangeScript()
624 {
625 }
626
627 /*!
628     \qmlproperty script QtQuick1::StateChangeScript::script
629     This property holds the script to run when the state is current.
630 */
631 QDeclarativeScriptString QDeclarative1StateChangeScript::script() const
632 {
633     Q_D(const QDeclarative1StateChangeScript);
634     return d->script;
635 }
636
637 void QDeclarative1StateChangeScript::setScript(const QDeclarativeScriptString &s)
638 {
639     Q_D(QDeclarative1StateChangeScript);
640     d->script = s;
641 }
642
643 /*!
644     \qmlproperty string QtQuick1::StateChangeScript::name
645     This property holds the name of the script. This name can be used by a
646     ScriptAction to target a specific script.
647
648     \sa ScriptAction::scriptName
649 */
650 QString QDeclarative1StateChangeScript::name() const
651 {
652     Q_D(const QDeclarative1StateChangeScript);
653     return d->name;
654 }
655
656 void QDeclarative1StateChangeScript::setName(const QString &n)
657 {
658     Q_D(QDeclarative1StateChangeScript);
659     d->name = n;
660 }
661
662 void QDeclarative1StateChangeScript::execute(Reason)
663 {
664     Q_D(QDeclarative1StateChangeScript);
665     const QString &script = d->script.script();
666     if (!script.isEmpty()) {
667         QDeclarativeExpression expr(d->script.context(), d->script.scopeObject(), script);
668         QDeclarativeData *ddata = QDeclarativeData::get(this);
669         if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
670             expr.setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber, ddata->columnNumber);
671         expr.evaluate();
672         if (expr.hasError())
673             qmlInfo(this, expr.error());
674     }
675 }
676
677 QDeclarative1StateChangeScript::ActionList QDeclarative1StateChangeScript::actions()
678 {
679     ActionList rv;
680     QDeclarative1Action a;
681     a.event = this;
682     rv << a;
683     return rv;
684 }
685
686 QString QDeclarative1StateChangeScript::typeName() const
687 {
688     return QLatin1String("StateChangeScript");
689 }
690
691 /*!
692     \qmlclass AnchorChanges QDeclarative1AnchorChanges
693     \inqmlmodule QtQuick 1
694     \ingroup qml-state-elements
695     \brief The AnchorChanges element allows you to change the anchors of an item in a state.
696
697     The AnchorChanges element is used to modify the anchors of an item in a \l State.
698
699     AnchorChanges cannot be used to modify the margins on an item. For this, use
700     PropertyChanges intead.
701
702     In the following example we change the top and bottom anchors of an item
703     using AnchorChanges, and the top and bottom anchor margins using
704     PropertyChanges:
705
706     \snippet doc/src/snippets/qtquick1/anchorchanges.qml 0
707
708     \image anchorchanges.png
709
710     AnchorChanges can be animated using AnchorAnimation.
711     \qml
712     //animate our anchor changes
713     Transition {
714         AnchorAnimation {}
715     }
716     \endqml
717
718     Margin animations can be animated using NumberAnimation.
719
720     For more information on anchors see \l {anchor-layout}{Anchor Layouts}.
721 */
722
723 class QDeclarative1AnchorSetPrivate : public QObjectPrivate
724 {
725     Q_DECLARE_PUBLIC(QDeclarative1AnchorSet)
726 public:
727     QDeclarative1AnchorSetPrivate()
728       : usedAnchors(0), resetAnchors(0), fill(0),
729         centerIn(0)/*, leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
730         margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)*/
731     {
732     }
733
734     QDeclarative1Anchors::Anchors usedAnchors;
735     QDeclarative1Anchors::Anchors resetAnchors;
736
737     QDeclarativeItem *fill;
738     QDeclarativeItem *centerIn;
739
740     QDeclarativeScriptString leftScript;
741     QDeclarativeScriptString rightScript;
742     QDeclarativeScriptString topScript;
743     QDeclarativeScriptString bottomScript;
744     QDeclarativeScriptString hCenterScript;
745     QDeclarativeScriptString vCenterScript;
746     QDeclarativeScriptString baselineScript;
747
748     /*qreal leftMargin;
749     qreal rightMargin;
750     qreal topMargin;
751     qreal bottomMargin;
752     qreal margins;
753     qreal vCenterOffset;
754     qreal hCenterOffset;
755     qreal baselineOffset;*/
756 };
757
758 QDeclarative1AnchorSet::QDeclarative1AnchorSet(QObject *parent)
759   : QObject(*new QDeclarative1AnchorSetPrivate, parent)
760 {
761 }
762
763 QDeclarative1AnchorSet::~QDeclarative1AnchorSet()
764 {
765 }
766
767 QDeclarativeScriptString QDeclarative1AnchorSet::top() const
768 {
769     Q_D(const QDeclarative1AnchorSet);
770     return d->topScript;
771 }
772
773 void QDeclarative1AnchorSet::setTop(const QDeclarativeScriptString &edge)
774 {
775     Q_D(QDeclarative1AnchorSet);
776     d->usedAnchors |= QDeclarative1Anchors::TopAnchor;
777     d->topScript = edge;
778     if (edge.script() == QLatin1String("undefined"))
779         resetTop();
780 }
781
782 void QDeclarative1AnchorSet::resetTop()
783 {
784     Q_D(QDeclarative1AnchorSet);
785     d->usedAnchors &= ~QDeclarative1Anchors::TopAnchor;
786     d->topScript = QDeclarativeScriptString();
787     d->resetAnchors |= QDeclarative1Anchors::TopAnchor;
788 }
789
790 QDeclarativeScriptString QDeclarative1AnchorSet::bottom() const
791 {
792     Q_D(const QDeclarative1AnchorSet);
793     return d->bottomScript;
794 }
795
796 void QDeclarative1AnchorSet::setBottom(const QDeclarativeScriptString &edge)
797 {
798     Q_D(QDeclarative1AnchorSet);
799     d->usedAnchors |= QDeclarative1Anchors::BottomAnchor;
800     d->bottomScript = edge;
801     if (edge.script() == QLatin1String("undefined"))
802         resetBottom();
803 }
804
805 void QDeclarative1AnchorSet::resetBottom()
806 {
807     Q_D(QDeclarative1AnchorSet);
808     d->usedAnchors &= ~QDeclarative1Anchors::BottomAnchor;
809     d->bottomScript = QDeclarativeScriptString();
810     d->resetAnchors |= QDeclarative1Anchors::BottomAnchor;
811 }
812
813 QDeclarativeScriptString QDeclarative1AnchorSet::verticalCenter() const
814 {
815     Q_D(const QDeclarative1AnchorSet);
816     return d->vCenterScript;
817 }
818
819 void QDeclarative1AnchorSet::setVerticalCenter(const QDeclarativeScriptString &edge)
820 {
821     Q_D(QDeclarative1AnchorSet);
822     d->usedAnchors |= QDeclarative1Anchors::VCenterAnchor;
823     d->vCenterScript = edge;
824     if (edge.script() == QLatin1String("undefined"))
825         resetVerticalCenter();
826 }
827
828 void QDeclarative1AnchorSet::resetVerticalCenter()
829 {
830     Q_D(QDeclarative1AnchorSet);
831     d->usedAnchors &= ~QDeclarative1Anchors::VCenterAnchor;
832     d->vCenterScript = QDeclarativeScriptString();
833     d->resetAnchors |= QDeclarative1Anchors::VCenterAnchor;
834 }
835
836 QDeclarativeScriptString QDeclarative1AnchorSet::baseline() const
837 {
838     Q_D(const QDeclarative1AnchorSet);
839     return d->baselineScript;
840 }
841
842 void QDeclarative1AnchorSet::setBaseline(const QDeclarativeScriptString &edge)
843 {
844     Q_D(QDeclarative1AnchorSet);
845     d->usedAnchors |= QDeclarative1Anchors::BaselineAnchor;
846     d->baselineScript = edge;
847     if (edge.script() == QLatin1String("undefined"))
848         resetBaseline();
849 }
850
851 void QDeclarative1AnchorSet::resetBaseline()
852 {
853     Q_D(QDeclarative1AnchorSet);
854     d->usedAnchors &= ~QDeclarative1Anchors::BaselineAnchor;
855     d->baselineScript = QDeclarativeScriptString();
856     d->resetAnchors |= QDeclarative1Anchors::BaselineAnchor;
857 }
858
859 QDeclarativeScriptString QDeclarative1AnchorSet::left() const
860 {
861     Q_D(const QDeclarative1AnchorSet);
862     return d->leftScript;
863 }
864
865 void QDeclarative1AnchorSet::setLeft(const QDeclarativeScriptString &edge)
866 {
867     Q_D(QDeclarative1AnchorSet);
868     d->usedAnchors |= QDeclarative1Anchors::LeftAnchor;
869     d->leftScript = edge;
870     if (edge.script() == QLatin1String("undefined"))
871         resetLeft();
872 }
873
874 void QDeclarative1AnchorSet::resetLeft()
875 {
876     Q_D(QDeclarative1AnchorSet);
877     d->usedAnchors &= ~QDeclarative1Anchors::LeftAnchor;
878     d->leftScript = QDeclarativeScriptString();
879     d->resetAnchors |= QDeclarative1Anchors::LeftAnchor;
880 }
881
882 QDeclarativeScriptString QDeclarative1AnchorSet::right() const
883 {
884     Q_D(const QDeclarative1AnchorSet);
885     return d->rightScript;
886 }
887
888 void QDeclarative1AnchorSet::setRight(const QDeclarativeScriptString &edge)
889 {
890     Q_D(QDeclarative1AnchorSet);
891     d->usedAnchors |= QDeclarative1Anchors::RightAnchor;
892     d->rightScript = edge;
893     if (edge.script() == QLatin1String("undefined"))
894         resetRight();
895 }
896
897 void QDeclarative1AnchorSet::resetRight()
898 {
899     Q_D(QDeclarative1AnchorSet);
900     d->usedAnchors &= ~QDeclarative1Anchors::RightAnchor;
901     d->rightScript = QDeclarativeScriptString();
902     d->resetAnchors |= QDeclarative1Anchors::RightAnchor;
903 }
904
905 QDeclarativeScriptString QDeclarative1AnchorSet::horizontalCenter() const
906 {
907     Q_D(const QDeclarative1AnchorSet);
908     return d->hCenterScript;
909 }
910
911 void QDeclarative1AnchorSet::setHorizontalCenter(const QDeclarativeScriptString &edge)
912 {
913     Q_D(QDeclarative1AnchorSet);
914     d->usedAnchors |= QDeclarative1Anchors::HCenterAnchor;
915     d->hCenterScript = edge;
916     if (edge.script() == QLatin1String("undefined"))
917         resetHorizontalCenter();
918 }
919
920 void QDeclarative1AnchorSet::resetHorizontalCenter()
921 {
922     Q_D(QDeclarative1AnchorSet);
923     d->usedAnchors &= ~QDeclarative1Anchors::HCenterAnchor;
924     d->hCenterScript = QDeclarativeScriptString();
925     d->resetAnchors |= QDeclarative1Anchors::HCenterAnchor;
926 }
927
928 QDeclarativeItem *QDeclarative1AnchorSet::fill() const
929 {
930     Q_D(const QDeclarative1AnchorSet);
931     return d->fill;
932 }
933
934 void QDeclarative1AnchorSet::setFill(QDeclarativeItem *f)
935 {
936     Q_D(QDeclarative1AnchorSet);
937     d->fill = f;
938 }
939
940 void QDeclarative1AnchorSet::resetFill()
941 {
942     setFill(0);
943 }
944
945 QDeclarativeItem *QDeclarative1AnchorSet::centerIn() const
946 {
947     Q_D(const QDeclarative1AnchorSet);
948     return d->centerIn;
949 }
950
951 void QDeclarative1AnchorSet::setCenterIn(QDeclarativeItem* c)
952 {
953     Q_D(QDeclarative1AnchorSet);
954     d->centerIn = c;
955 }
956
957 void QDeclarative1AnchorSet::resetCenterIn()
958 {
959     setCenterIn(0);
960 }
961
962
963 class QDeclarative1AnchorChangesPrivate : public QDeclarative1StateOperationPrivate
964 {
965 public:
966     QDeclarative1AnchorChangesPrivate()
967         : target(0), anchorSet(new QDeclarative1AnchorSet),
968           leftBinding(0), rightBinding(0), hCenterBinding(0),
969           topBinding(0), bottomBinding(0), vCenterBinding(0), baselineBinding(0),
970           origLeftBinding(0), origRightBinding(0), origHCenterBinding(0),
971           origTopBinding(0), origBottomBinding(0), origVCenterBinding(0),
972           origBaselineBinding(0)
973     {
974
975     }
976     ~QDeclarative1AnchorChangesPrivate() { delete anchorSet; }
977
978     QDeclarativeItem *target;
979     QDeclarative1AnchorSet *anchorSet;
980
981     QDeclarativeBinding *leftBinding;
982     QDeclarativeBinding *rightBinding;
983     QDeclarativeBinding *hCenterBinding;
984     QDeclarativeBinding *topBinding;
985     QDeclarativeBinding *bottomBinding;
986     QDeclarativeBinding *vCenterBinding;
987     QDeclarativeBinding *baselineBinding;
988
989     QDeclarativeAbstractBinding *origLeftBinding;
990     QDeclarativeAbstractBinding *origRightBinding;
991     QDeclarativeAbstractBinding *origHCenterBinding;
992     QDeclarativeAbstractBinding *origTopBinding;
993     QDeclarativeAbstractBinding *origBottomBinding;
994     QDeclarativeAbstractBinding *origVCenterBinding;
995     QDeclarativeAbstractBinding *origBaselineBinding;
996
997     QDeclarative1AnchorLine rewindLeft;
998     QDeclarative1AnchorLine rewindRight;
999     QDeclarative1AnchorLine rewindHCenter;
1000     QDeclarative1AnchorLine rewindTop;
1001     QDeclarative1AnchorLine rewindBottom;
1002     QDeclarative1AnchorLine rewindVCenter;
1003     QDeclarative1AnchorLine rewindBaseline;
1004
1005     qreal fromX;
1006     qreal fromY;
1007     qreal fromWidth;
1008     qreal fromHeight;
1009
1010     qreal toX;
1011     qreal toY;
1012     qreal toWidth;
1013     qreal toHeight;
1014
1015     qreal rewindX;
1016     qreal rewindY;
1017     qreal rewindWidth;
1018     qreal rewindHeight;
1019
1020     bool applyOrigLeft;
1021     bool applyOrigRight;
1022     bool applyOrigHCenter;
1023     bool applyOrigTop;
1024     bool applyOrigBottom;
1025     bool applyOrigVCenter;
1026     bool applyOrigBaseline;
1027
1028     QDeclarativeNullableValue<qreal> origWidth;
1029     QDeclarativeNullableValue<qreal> origHeight;
1030     qreal origX;
1031     qreal origY;
1032
1033     QList<QDeclarativeAbstractBinding*> oldBindings;
1034
1035     QDeclarativeProperty leftProp;
1036     QDeclarativeProperty rightProp;
1037     QDeclarativeProperty hCenterProp;
1038     QDeclarativeProperty topProp;
1039     QDeclarativeProperty bottomProp;
1040     QDeclarativeProperty vCenterProp;
1041     QDeclarativeProperty baselineProp;
1042 };
1043
1044 /*!
1045     \qmlproperty Item QtQuick1::AnchorChanges::target
1046     This property holds the \l Item for which the anchor changes will be applied.
1047 */
1048
1049 QDeclarative1AnchorChanges::QDeclarative1AnchorChanges(QObject *parent)
1050  : QDeclarative1StateOperation(*(new QDeclarative1AnchorChangesPrivate), parent)
1051 {
1052 }
1053
1054 QDeclarative1AnchorChanges::~QDeclarative1AnchorChanges()
1055 {
1056 }
1057
1058 QDeclarative1AnchorChanges::ActionList QDeclarative1AnchorChanges::actions()
1059 {
1060     Q_D(QDeclarative1AnchorChanges);
1061     d->leftBinding = d->rightBinding = d->hCenterBinding = d->topBinding
1062                    = d->bottomBinding = d->vCenterBinding = d->baselineBinding = 0;
1063
1064     d->leftProp = QDeclarativeProperty(d->target, QLatin1String("anchors.left"));
1065     d->rightProp = QDeclarativeProperty(d->target, QLatin1String("anchors.right"));
1066     d->hCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.horizontalCenter"));
1067     d->topProp = QDeclarativeProperty(d->target, QLatin1String("anchors.top"));
1068     d->bottomProp = QDeclarativeProperty(d->target, QLatin1String("anchors.bottom"));
1069     d->vCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.verticalCenter"));
1070     d->baselineProp = QDeclarativeProperty(d->target, QLatin1String("anchors.baseline"));
1071
1072     QDeclarativeContext *ctxt = qmlContext(this);
1073
1074     if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::LeftAnchor) {
1075         d->leftBinding = new QDeclarativeBinding(d->anchorSet->d_func()->leftScript.script(), d->target, ctxt);
1076         d->leftBinding->setTarget(d->leftProp);
1077     }
1078     if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::RightAnchor) {
1079         d->rightBinding = new QDeclarativeBinding(d->anchorSet->d_func()->rightScript.script(), d->target, ctxt);
1080         d->rightBinding->setTarget(d->rightProp);
1081     }
1082     if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::HCenterAnchor) {
1083         d->hCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, ctxt);
1084         d->hCenterBinding->setTarget(d->hCenterProp);
1085     }
1086     if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::TopAnchor) {
1087         d->topBinding = new QDeclarativeBinding(d->anchorSet->d_func()->topScript.script(), d->target, ctxt);
1088         d->topBinding->setTarget(d->topProp);
1089     }
1090     if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::BottomAnchor) {
1091         d->bottomBinding = new QDeclarativeBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, ctxt);
1092         d->bottomBinding->setTarget(d->bottomProp);
1093     }
1094     if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::VCenterAnchor) {
1095         d->vCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, ctxt);
1096         d->vCenterBinding->setTarget(d->vCenterProp);
1097     }
1098     if (d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::BaselineAnchor) {
1099         d->baselineBinding = new QDeclarativeBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, ctxt);
1100         d->baselineBinding->setTarget(d->baselineProp);
1101     }
1102
1103     QDeclarative1Action a;
1104     a.event = this;
1105     return ActionList() << a;
1106 }
1107
1108 QDeclarative1AnchorSet *QDeclarative1AnchorChanges::anchors()
1109 {
1110     Q_D(QDeclarative1AnchorChanges);
1111     return d->anchorSet;
1112 }
1113
1114 QDeclarativeItem *QDeclarative1AnchorChanges::object() const
1115 {
1116     Q_D(const QDeclarative1AnchorChanges);
1117     return d->target;
1118 }
1119
1120 void QDeclarative1AnchorChanges::setObject(QDeclarativeItem *target)
1121 {
1122     Q_D(QDeclarative1AnchorChanges);
1123     d->target = target;
1124 }
1125
1126 /*!
1127     \qmlproperty AnchorLine QtQuick1::AnchorChanges::anchors.left
1128     \qmlproperty AnchorLine QtQuick1::AnchorChanges::anchors.right
1129     \qmlproperty AnchorLine QtQuick1::AnchorChanges::anchors.horizontalCenter
1130     \qmlproperty AnchorLine QtQuick1::AnchorChanges::anchors.top
1131     \qmlproperty AnchorLine QtQuick1::AnchorChanges::anchors.bottom
1132     \qmlproperty AnchorLine QtQuick1::AnchorChanges::anchors.verticalCenter
1133     \qmlproperty AnchorLine QtQuick1::AnchorChanges::anchors.baseline
1134
1135     These properties change the respective anchors of the item.
1136
1137     To reset an anchor you can assign \c undefined:
1138     \qml
1139     AnchorChanges {
1140         target: myItem
1141         anchors.left: undefined          //remove myItem's left anchor
1142         anchors.right: otherItem.right
1143     }
1144     \endqml
1145 */
1146
1147 void QDeclarative1AnchorChanges::execute(Reason reason)
1148 {
1149     Q_D(QDeclarative1AnchorChanges);
1150     if (!d->target)
1151         return;
1152
1153     QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
1154     //incorporate any needed "reverts"
1155     if (d->applyOrigLeft) {
1156         if (!d->origLeftBinding)
1157             targetPrivate->anchors()->resetLeft();
1158         QDeclarativePropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
1159     }
1160     if (d->applyOrigRight) {
1161         if (!d->origRightBinding)
1162             targetPrivate->anchors()->resetRight();
1163         QDeclarativePropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
1164     }
1165     if (d->applyOrigHCenter) {
1166         if (!d->origHCenterBinding)
1167             targetPrivate->anchors()->resetHorizontalCenter();
1168         QDeclarativePropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
1169     }
1170     if (d->applyOrigTop) {
1171         if (!d->origTopBinding)
1172             targetPrivate->anchors()->resetTop();
1173         QDeclarativePropertyPrivate::setBinding(d->topProp, d->origTopBinding);
1174     }
1175     if (d->applyOrigBottom) {
1176         if (!d->origBottomBinding)
1177             targetPrivate->anchors()->resetBottom();
1178         QDeclarativePropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
1179     }
1180     if (d->applyOrigVCenter) {
1181         if (!d->origVCenterBinding)
1182             targetPrivate->anchors()->resetVerticalCenter();
1183         QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
1184     }
1185     if (d->applyOrigBaseline) {
1186         if (!d->origBaselineBinding)
1187             targetPrivate->anchors()->resetBaseline();
1188         QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
1189     }
1190
1191     //destroy old bindings
1192     if (reason == ActualChange) {
1193         for (int i = 0; i < d->oldBindings.size(); ++i) {
1194             QDeclarativeAbstractBinding *binding = d->oldBindings.at(i);
1195             if (binding)
1196                 binding->destroy();
1197         }
1198         d->oldBindings.clear();
1199     }
1200
1201     //reset any anchors that have been specified as "undefined"
1202     if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::LeftAnchor) {
1203         targetPrivate->anchors()->resetLeft();
1204         QDeclarativePropertyPrivate::setBinding(d->leftProp, 0);
1205     }
1206     if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::RightAnchor) {
1207         targetPrivate->anchors()->resetRight();
1208         QDeclarativePropertyPrivate::setBinding(d->rightProp, 0);
1209     }
1210     if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::HCenterAnchor) {
1211         targetPrivate->anchors()->resetHorizontalCenter();
1212         QDeclarativePropertyPrivate::setBinding(d->hCenterProp, 0);
1213     }
1214     if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::TopAnchor) {
1215         targetPrivate->anchors()->resetTop();
1216         QDeclarativePropertyPrivate::setBinding(d->topProp, 0);
1217     }
1218     if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::BottomAnchor) {
1219         targetPrivate->anchors()->resetBottom();
1220         QDeclarativePropertyPrivate::setBinding(d->bottomProp, 0);
1221     }
1222     if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::VCenterAnchor) {
1223         targetPrivate->anchors()->resetVerticalCenter();
1224         QDeclarativePropertyPrivate::setBinding(d->vCenterProp, 0);
1225     }
1226     if (d->anchorSet->d_func()->resetAnchors & QDeclarative1Anchors::BaselineAnchor) {
1227         targetPrivate->anchors()->resetBaseline();
1228         QDeclarativePropertyPrivate::setBinding(d->baselineProp, 0);
1229     }
1230
1231     //set any anchors that have been specified
1232     if (d->leftBinding)
1233         QDeclarativePropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding);
1234     if (d->rightBinding)
1235         QDeclarativePropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding);
1236     if (d->hCenterBinding)
1237         QDeclarativePropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding);
1238     if (d->topBinding)
1239         QDeclarativePropertyPrivate::setBinding(d->topBinding->property(), d->topBinding);
1240     if (d->bottomBinding)
1241         QDeclarativePropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding);
1242     if (d->vCenterBinding)
1243         QDeclarativePropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding);
1244     if (d->baselineBinding)
1245         QDeclarativePropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding);
1246 }
1247
1248 bool QDeclarative1AnchorChanges::isReversable()
1249 {
1250     return true;
1251 }
1252
1253 void QDeclarative1AnchorChanges::reverse(Reason reason)
1254 {
1255     Q_D(QDeclarative1AnchorChanges);
1256     if (!d->target)
1257         return;
1258
1259     QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
1260     //reset any anchors set by the state
1261     if (d->leftBinding) {
1262         targetPrivate->anchors()->resetLeft();
1263         QDeclarativePropertyPrivate::setBinding(d->leftBinding->property(), 0);
1264         if (reason == ActualChange) {
1265             d->leftBinding->destroy(); d->leftBinding = 0;
1266         }
1267     }
1268     if (d->rightBinding) {
1269         targetPrivate->anchors()->resetRight();
1270         QDeclarativePropertyPrivate::setBinding(d->rightBinding->property(), 0);
1271         if (reason == ActualChange) {
1272             d->rightBinding->destroy(); d->rightBinding = 0;
1273         }
1274     }
1275     if (d->hCenterBinding) {
1276         targetPrivate->anchors()->resetHorizontalCenter();
1277         QDeclarativePropertyPrivate::setBinding(d->hCenterBinding->property(), 0);
1278         if (reason == ActualChange) {
1279             d->hCenterBinding->destroy(); d->hCenterBinding = 0;
1280         }
1281     }
1282     if (d->topBinding) {
1283         targetPrivate->anchors()->resetTop();
1284         QDeclarativePropertyPrivate::setBinding(d->topBinding->property(), 0);
1285         if (reason == ActualChange) {
1286             d->topBinding->destroy(); d->topBinding = 0;
1287         }
1288     }
1289     if (d->bottomBinding) {
1290         targetPrivate->anchors()->resetBottom();
1291         QDeclarativePropertyPrivate::setBinding(d->bottomBinding->property(), 0);
1292         if (reason == ActualChange) {
1293             d->bottomBinding->destroy(); d->bottomBinding = 0;
1294         }
1295     }
1296     if (d->vCenterBinding) {
1297         targetPrivate->anchors()->resetVerticalCenter();
1298         QDeclarativePropertyPrivate::setBinding(d->vCenterBinding->property(), 0);
1299         if (reason == ActualChange) {
1300             d->vCenterBinding->destroy(); d->vCenterBinding = 0;
1301         }
1302     }
1303     if (d->baselineBinding) {
1304         targetPrivate->anchors()->resetBaseline();
1305         QDeclarativePropertyPrivate::setBinding(d->baselineBinding->property(), 0);
1306         if (reason == ActualChange) {
1307             d->baselineBinding->destroy(); d->baselineBinding = 0;
1308         }
1309     }
1310
1311     //restore previous anchors
1312     if (d->origLeftBinding)
1313         QDeclarativePropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
1314     if (d->origRightBinding)
1315         QDeclarativePropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
1316     if (d->origHCenterBinding)
1317         QDeclarativePropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
1318     if (d->origTopBinding)
1319         QDeclarativePropertyPrivate::setBinding(d->topProp, d->origTopBinding);
1320     if (d->origBottomBinding)
1321         QDeclarativePropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
1322     if (d->origVCenterBinding)
1323         QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
1324     if (d->origBaselineBinding)
1325         QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
1326
1327     //restore any absolute geometry changed by the state's anchors
1328     QDeclarative1Anchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::Vertical_Mask;
1329     QDeclarative1Anchors::Anchors origVAnchors = targetPrivate->anchors()->usedAnchors() & QDeclarative1Anchors::Vertical_Mask;
1330     QDeclarative1Anchors::Anchors stateHAnchors = d->anchorSet->d_func()->usedAnchors & QDeclarative1Anchors::Horizontal_Mask;
1331     QDeclarative1Anchors::Anchors origHAnchors = targetPrivate->anchors()->usedAnchors() & QDeclarative1Anchors::Horizontal_Mask;
1332
1333     bool stateSetWidth = (stateHAnchors &&
1334                           stateHAnchors != QDeclarative1Anchors::LeftAnchor &&
1335                           stateHAnchors != QDeclarative1Anchors::RightAnchor &&
1336                           stateHAnchors != QDeclarative1Anchors::HCenterAnchor);
1337     bool origSetWidth = (origHAnchors &&
1338                          origHAnchors != QDeclarative1Anchors::LeftAnchor &&
1339                          origHAnchors != QDeclarative1Anchors::RightAnchor &&
1340                          origHAnchors != QDeclarative1Anchors::HCenterAnchor);
1341     if (d->origWidth.isValid() && stateSetWidth && !origSetWidth)
1342         d->target->setWidth(d->origWidth.value);
1343
1344     bool stateSetHeight = (stateVAnchors &&
1345                            stateVAnchors != QDeclarative1Anchors::TopAnchor &&
1346                            stateVAnchors != QDeclarative1Anchors::BottomAnchor &&
1347                            stateVAnchors != QDeclarative1Anchors::VCenterAnchor &&
1348                            stateVAnchors != QDeclarative1Anchors::BaselineAnchor);
1349     bool origSetHeight = (origVAnchors &&
1350                           origVAnchors != QDeclarative1Anchors::TopAnchor &&
1351                           origVAnchors != QDeclarative1Anchors::BottomAnchor &&
1352                           origVAnchors != QDeclarative1Anchors::VCenterAnchor &&
1353                           origVAnchors != QDeclarative1Anchors::BaselineAnchor);
1354     if (d->origHeight.isValid() && stateSetHeight && !origSetHeight)
1355         d->target->setHeight(d->origHeight.value);
1356
1357     if (stateHAnchors && !origHAnchors)
1358         d->target->setX(d->origX);
1359
1360     if (stateVAnchors && !origVAnchors)
1361         d->target->setY(d->origY);
1362 }
1363
1364 QString QDeclarative1AnchorChanges::typeName() const
1365 {
1366     return QLatin1String("AnchorChanges");
1367 }
1368
1369 QList<QDeclarative1Action> QDeclarative1AnchorChanges::additionalActions()
1370 {
1371     Q_D(QDeclarative1AnchorChanges);
1372     QList<QDeclarative1Action> extra;
1373
1374     QDeclarative1Anchors::Anchors combined = d->anchorSet->d_func()->usedAnchors | d->anchorSet->d_func()->resetAnchors;
1375     bool hChange = combined & QDeclarative1Anchors::Horizontal_Mask;
1376     bool vChange = combined & QDeclarative1Anchors::Vertical_Mask;
1377
1378     if (d->target) {
1379         QDeclarativeContext *ctxt = qmlContext(this);
1380         QDeclarative1Action a;
1381         if (hChange && d->fromX != d->toX) {
1382             a.property = QDeclarativeProperty(d->target, QLatin1String("x"), ctxt);
1383             a.toValue = d->toX;
1384             extra << a;
1385         }
1386         if (vChange && d->fromY != d->toY) {
1387             a.property = QDeclarativeProperty(d->target, QLatin1String("y"), ctxt);
1388             a.toValue = d->toY;
1389             extra << a;
1390         }
1391         if (hChange && d->fromWidth != d->toWidth) {
1392             a.property = QDeclarativeProperty(d->target, QLatin1String("width"), ctxt);
1393             a.toValue = d->toWidth;
1394             extra << a;
1395         }
1396         if (vChange && d->fromHeight != d->toHeight) {
1397             a.property = QDeclarativeProperty(d->target, QLatin1String("height"), ctxt);
1398             a.toValue = d->toHeight;
1399             extra << a;
1400         }
1401     }
1402
1403     return extra;
1404 }
1405
1406 bool QDeclarative1AnchorChanges::changesBindings()
1407 {
1408     return true;
1409 }
1410
1411 void QDeclarative1AnchorChanges::saveOriginals()
1412 {
1413     Q_D(QDeclarative1AnchorChanges);
1414     if (!d->target)
1415         return;
1416
1417     d->origLeftBinding = QDeclarativePropertyPrivate::binding(d->leftProp);
1418     d->origRightBinding = QDeclarativePropertyPrivate::binding(d->rightProp);
1419     d->origHCenterBinding = QDeclarativePropertyPrivate::binding(d->hCenterProp);
1420     d->origTopBinding = QDeclarativePropertyPrivate::binding(d->topProp);
1421     d->origBottomBinding = QDeclarativePropertyPrivate::binding(d->bottomProp);
1422     d->origVCenterBinding = QDeclarativePropertyPrivate::binding(d->vCenterProp);
1423     d->origBaselineBinding = QDeclarativePropertyPrivate::binding(d->baselineProp);
1424
1425     QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
1426     if (targetPrivate->widthValid)
1427         d->origWidth = d->target->width();
1428     if (targetPrivate->heightValid)
1429         d->origHeight = d->target->height();
1430     d->origX = d->target->x();
1431     d->origY = d->target->y();
1432
1433     d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop
1434       = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false;
1435
1436     saveCurrentValues();
1437 }
1438
1439 void QDeclarative1AnchorChanges::copyOriginals(QDeclarative1ActionEvent *other)
1440 {
1441     Q_D(QDeclarative1AnchorChanges);
1442     QDeclarative1AnchorChanges *ac = static_cast<QDeclarative1AnchorChanges*>(other);
1443     QDeclarative1AnchorChangesPrivate *acp = ac->d_func();
1444
1445     QDeclarative1Anchors::Anchors combined = acp->anchorSet->d_func()->usedAnchors |
1446                                             acp->anchorSet->d_func()->resetAnchors;
1447
1448     //probably also need to revert some things
1449     d->applyOrigLeft = (combined & QDeclarative1Anchors::LeftAnchor);
1450     d->applyOrigRight = (combined & QDeclarative1Anchors::RightAnchor);
1451     d->applyOrigHCenter = (combined & QDeclarative1Anchors::HCenterAnchor);
1452     d->applyOrigTop = (combined & QDeclarative1Anchors::TopAnchor);
1453     d->applyOrigBottom = (combined & QDeclarative1Anchors::BottomAnchor);
1454     d->applyOrigVCenter = (combined & QDeclarative1Anchors::VCenterAnchor);
1455     d->applyOrigBaseline = (combined & QDeclarative1Anchors::BaselineAnchor);
1456
1457     d->origLeftBinding = acp->origLeftBinding;
1458     d->origRightBinding = acp->origRightBinding;
1459     d->origHCenterBinding = acp->origHCenterBinding;
1460     d->origTopBinding = acp->origTopBinding;
1461     d->origBottomBinding = acp->origBottomBinding;
1462     d->origVCenterBinding = acp->origVCenterBinding;
1463     d->origBaselineBinding = acp->origBaselineBinding;
1464
1465     d->origWidth = acp->origWidth;
1466     d->origHeight = acp->origHeight;
1467     d->origX = acp->origX;
1468     d->origY = acp->origY;
1469
1470     d->oldBindings.clear();
1471     d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding
1472                 << acp->topBinding << acp->bottomBinding << acp->baselineBinding;
1473
1474     saveCurrentValues();
1475 }
1476
1477 void QDeclarative1AnchorChanges::clearBindings()
1478 {
1479     Q_D(QDeclarative1AnchorChanges);
1480     if (!d->target)
1481         return;
1482
1483     //### should this (saving "from" values) be moved to saveCurrentValues()?
1484     d->fromX = d->target->x();
1485     d->fromY = d->target->y();
1486     d->fromWidth = d->target->width();
1487     d->fromHeight = d->target->height();
1488
1489     QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
1490     //reset any anchors with corresponding reverts
1491     //reset any anchors that have been specified as "undefined"
1492     //reset any anchors that we'll be setting in the state
1493     QDeclarative1Anchors::Anchors combined = d->anchorSet->d_func()->resetAnchors |
1494                                             d->anchorSet->d_func()->usedAnchors;
1495     if (d->applyOrigLeft || (combined & QDeclarative1Anchors::LeftAnchor)) {
1496         targetPrivate->anchors()->resetLeft();
1497         QDeclarativePropertyPrivate::setBinding(d->leftProp, 0);
1498     }
1499     if (d->applyOrigRight || (combined & QDeclarative1Anchors::RightAnchor)) {
1500         targetPrivate->anchors()->resetRight();
1501         QDeclarativePropertyPrivate::setBinding(d->rightProp, 0);
1502     }
1503     if (d->applyOrigHCenter || (combined & QDeclarative1Anchors::HCenterAnchor)) {
1504         targetPrivate->anchors()->resetHorizontalCenter();
1505         QDeclarativePropertyPrivate::setBinding(d->hCenterProp, 0);
1506     }
1507     if (d->applyOrigTop || (combined & QDeclarative1Anchors::TopAnchor)) {
1508         targetPrivate->anchors()->resetTop();
1509         QDeclarativePropertyPrivate::setBinding(d->topProp, 0);
1510     }
1511     if (d->applyOrigBottom || (combined & QDeclarative1Anchors::BottomAnchor)) {
1512         targetPrivate->anchors()->resetBottom();
1513         QDeclarativePropertyPrivate::setBinding(d->bottomProp, 0);
1514     }
1515     if (d->applyOrigVCenter || (combined & QDeclarative1Anchors::VCenterAnchor)) {
1516         targetPrivate->anchors()->resetVerticalCenter();
1517         QDeclarativePropertyPrivate::setBinding(d->vCenterProp, 0);
1518     }
1519     if (d->applyOrigBaseline || (combined & QDeclarative1Anchors::BaselineAnchor)) {
1520         targetPrivate->anchors()->resetBaseline();
1521         QDeclarativePropertyPrivate::setBinding(d->baselineProp, 0);
1522     }
1523 }
1524
1525 bool QDeclarative1AnchorChanges::override(QDeclarative1ActionEvent*other)
1526 {
1527     if (other->typeName() != QLatin1String("AnchorChanges"))
1528         return false;
1529     if (static_cast<QDeclarative1ActionEvent*>(this) == other)
1530         return true;
1531     if (static_cast<QDeclarative1AnchorChanges*>(other)->object() == object())
1532         return true;
1533     return false;
1534 }
1535
1536 void QDeclarative1AnchorChanges::rewind()
1537 {
1538     Q_D(QDeclarative1AnchorChanges);
1539     if (!d->target)
1540         return;
1541
1542     QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
1543
1544     //restore previous values (but not previous bindings, i.e. anchors)
1545     d->target->setX(d->rewindX);
1546     d->target->setY(d->rewindY);
1547     if (targetPrivate->widthValid) {
1548         d->target->setWidth(d->rewindWidth);
1549     }
1550     if (targetPrivate->heightValid) {
1551         d->target->setHeight(d->rewindHeight);
1552     }
1553 }
1554
1555 void QDeclarative1AnchorChanges::saveCurrentValues()
1556 {
1557     Q_D(QDeclarative1AnchorChanges);
1558     if (!d->target)
1559         return;
1560
1561     QDeclarativeItemPrivate *targetPrivate = QDeclarativeItemPrivate::get(d->target);
1562     d->rewindLeft = targetPrivate->anchors()->left();
1563     d->rewindRight = targetPrivate->anchors()->right();
1564     d->rewindHCenter = targetPrivate->anchors()->horizontalCenter();
1565     d->rewindTop = targetPrivate->anchors()->top();
1566     d->rewindBottom = targetPrivate->anchors()->bottom();
1567     d->rewindVCenter = targetPrivate->anchors()->verticalCenter();
1568     d->rewindBaseline = targetPrivate->anchors()->baseline();
1569
1570     d->rewindX = d->target->x();
1571     d->rewindY = d->target->y();
1572     d->rewindWidth = d->target->width();
1573     d->rewindHeight = d->target->height();
1574 }
1575
1576 void QDeclarative1AnchorChanges::saveTargetValues()
1577 {
1578     Q_D(QDeclarative1AnchorChanges);
1579     if (!d->target)
1580         return;
1581
1582     d->toX = d->target->x();
1583     d->toY = d->target->y();
1584     d->toWidth = d->target->width();
1585     d->toHeight = d->target->height();
1586 }
1587
1588 #include <qdeclarativestateoperations.moc>
1589 #include <moc_qdeclarativestateoperations_p.cpp>
1590
1591
1592
1593 QT_END_NAMESPACE
1594