source: trunk/src/declarative/util/qdeclarativestateoperations.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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