Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickstateoperations.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "qquickitem_p.h"
6
7#include <private/qquickstate_p_p.h>
8
9#include <QtQml/qqmlinfo.h>
10
11#include <QtCore/qmath.h>
12#include <QtCore/qpointer.h>
13
14#include <memory>
15
16QT_BEGIN_NAMESPACE
17
18class QQuickParentChangePrivate : public QQuickStateOperationPrivate
19{
20 Q_DECLARE_PUBLIC(QQuickParentChange)
21public:
22 QQuickItem *target = nullptr;
23 QPointer<QQuickItem> parent;
24
25 struct StateSnapshot {
26 QPointer<QQuickItem> parent;
27 QPointer<QQuickItem> stackBefore;
28 qreal x = 0, y = 0, width = 0, height = 0, scale = 0, rotation = 0;
29 };
30
31 std::unique_ptr<StateSnapshot> orig;
32 std::unique_ptr<StateSnapshot> rewind;
33
34 QQmlNullableValue<QQmlScriptString> xString;
35 QQmlNullableValue<QQmlScriptString> yString;
36 QQmlNullableValue<QQmlScriptString> widthString;
37 QQmlNullableValue<QQmlScriptString> heightString;
38 QQmlNullableValue<QQmlScriptString> scaleString;
39 QQmlNullableValue<QQmlScriptString> rotationString;
40
41 void doChange(QQuickItem *targetParent);
42 void reverseRewindHelper(const std::unique_ptr<StateSnapshot> &snapshot);
43};
44
45void QQuickParentChangePrivate::doChange(QQuickItem *targetParent)
46{
47 if (targetParent && target && target->parentItem()) {
48 Q_Q(QQuickParentChange);
49 bool ok;
50 const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok);
51 if (transform.type() >= QTransform::TxShear || !ok) {
52 qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under complex transform");
53 ok = false;
54 }
55
56 qreal scale = 1;
57 qreal rotation = 0;
58 bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
59 if (ok && !isRotate) {
60 if (transform.m11() == transform.m22())
61 scale = transform.m11();
62 else {
63 qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
64 ok = false;
65 }
66 } else if (ok && isRotate) {
67 if (transform.m11() == transform.m22())
68 scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
69 else {
70 qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under non-uniform scale");
71 ok = false;
72 }
73
74 if (scale != 0)
75 rotation = qRadiansToDegrees(qAtan2(transform.m12() / scale, transform.m11() / scale));
76 else {
77 qmlWarning(q) << QQuickParentChange::tr("Unable to preserve appearance under scale of 0");
78 ok = false;
79 }
80 }
81
82 const QPointF &point = transform.map(QPointF(target->x(),target->y()));
83 qreal x = point.x();
84 qreal y = point.y();
85
86 // setParentItem will update the transformOriginPoint if needed
87 target->setParentItem(targetParent);
88
89 if (ok && target->transformOrigin() != QQuickItem::TopLeft) {
90 qreal tempxt = target->transformOriginPoint().x();
91 qreal tempyt = target->transformOriginPoint().y();
92 QTransform t;
93 t.translate(-tempxt, -tempyt);
94 t.rotate(rotation);
95 t.scale(scale, scale);
96 t.translate(tempxt, tempyt);
97 const QPointF &offset = t.map(QPointF(0,0));
98 x += offset.x();
99 y += offset.y();
100 }
101
102 if (ok) {
103 //qDebug() << x << y << rotation << scale;
104 target->setPosition(QPointF(x, y));
105 target->setRotation(target->rotation() + rotation);
106 target->setScale(target->scale() * scale);
107 }
108 } else if (target) {
109 target->setParentItem(targetParent);
110 }
111}
112
113/*!
114 \qmltype ParentChange
115 \nativetype QQuickParentChange
116 \inqmlmodule QtQuick
117 \ingroup qtquick-states
118 \brief Specifies how to reparent an Item in a state change.
119
120 ParentChange reparents an item while preserving its visual appearance (position, size,
121 rotation, and scale) on screen. You can then specify a transition to move/resize/rotate/scale
122 the item to its final intended appearance.
123
124 ParentChange can only preserve visual appearance if no complex transforms are involved.
125 More specifically, it will not work if the transform property has been set for any
126 items involved in the reparenting (i.e. items in the common ancestor tree
127 for the original and new parent).
128
129 The example below displays a large red rectangle and a small blue rectangle, side by side.
130 When the \c blueRect is clicked, it changes to the "reparented" state: its parent is changed to \c redRect and it is
131 positioned at (10, 10) within the red rectangle, as specified in the ParentChange.
132
133 \snippet qml/parentchange.qml 0
134
135 \image parentchange.png
136
137 You can specify at which point in a transition you want a ParentChange to occur by
138 using a ParentAnimation.
139
140 Note that unlike PropertyChanges, ParentChange expects an Item-based target; it will not work with
141 arbitrary objects (for example, you couldn't use it to reparent a Timer).
142*/
143
144QQuickParentChange::QQuickParentChange(QObject *parent)
145 : QQuickStateOperation(*(new QQuickParentChangePrivate), parent)
146{
147}
148
149/*!
150 \qmlproperty real QtQuick::ParentChange::x
151 \qmlproperty real QtQuick::ParentChange::y
152 \qmlproperty real QtQuick::ParentChange::width
153 \qmlproperty real QtQuick::ParentChange::height
154 \qmlproperty real QtQuick::ParentChange::scale
155 \qmlproperty real QtQuick::ParentChange::rotation
156 These properties hold the new position, size, scale, and rotation
157 for the item in this state.
158*/
159QQmlScriptString QQuickParentChange::x() const
160{
161 Q_D(const QQuickParentChange);
162 return d->xString.value();
163}
164
165void QQuickParentChange::setX(const QQmlScriptString &x)
166{
167 Q_D(QQuickParentChange);
168 d->xString = x;
169}
170
171bool QQuickParentChange::xIsSet() const
172{
173 Q_D(const QQuickParentChange);
174 return d->xString.isValid();
175}
176
177QQmlScriptString QQuickParentChange::y() const
178{
179 Q_D(const QQuickParentChange);
180 return d->yString.value();
181}
182
183void QQuickParentChange::setY(const QQmlScriptString &y)
184{
185 Q_D(QQuickParentChange);
186 d->yString = y;
187}
188
189bool QQuickParentChange::yIsSet() const
190{
191 Q_D(const QQuickParentChange);
192 return d->yString.isValid();
193}
194
195QQmlScriptString QQuickParentChange::width() const
196{
197 Q_D(const QQuickParentChange);
198 return d->widthString.value();
199}
200
201void QQuickParentChange::setWidth(const QQmlScriptString &width)
202{
203 Q_D(QQuickParentChange);
204 d->widthString = width;
205}
206
207bool QQuickParentChange::widthIsSet() const
208{
209 Q_D(const QQuickParentChange);
210 return d->widthString.isValid();
211}
212
213QQmlScriptString QQuickParentChange::height() const
214{
215 Q_D(const QQuickParentChange);
216 return d->heightString.value();
217}
218
219void QQuickParentChange::setHeight(const QQmlScriptString &height)
220{
221 Q_D(QQuickParentChange);
222 d->heightString = height;
223}
224
225bool QQuickParentChange::heightIsSet() const
226{
227 Q_D(const QQuickParentChange);
228 return d->heightString.isValid();
229}
230
231QQmlScriptString QQuickParentChange::scale() const
232{
233 Q_D(const QQuickParentChange);
234 return d->scaleString.value();
235}
236
237void QQuickParentChange::setScale(const QQmlScriptString &scale)
238{
239 Q_D(QQuickParentChange);
240 d->scaleString = scale;
241}
242
243bool QQuickParentChange::scaleIsSet() const
244{
245 Q_D(const QQuickParentChange);
246 return d->scaleString.isValid();
247}
248
249QQmlScriptString QQuickParentChange::rotation() const
250{
251 Q_D(const QQuickParentChange);
252 return d->rotationString.value();
253}
254
255void QQuickParentChange::setRotation(const QQmlScriptString &rotation)
256{
257 Q_D(QQuickParentChange);
258 d->rotationString = rotation;
259}
260
261bool QQuickParentChange::rotationIsSet() const
262{
263 Q_D(const QQuickParentChange);
264 return d->rotationString.isValid();
265}
266
267QQuickItem *QQuickParentChange::originalParent() const
268{
269 Q_D(const QQuickParentChange);
270 return d->orig ? d->orig->parent : nullptr;
271}
272
273/*!
274 \qmlproperty Item QtQuick::ParentChange::target
275 This property holds the item to be reparented
276*/
277QQuickItem *QQuickParentChange::object() const
278{
279 Q_D(const QQuickParentChange);
280 return d->target;
281}
282
283void QQuickParentChange::setObject(QQuickItem *target)
284{
285 Q_D(QQuickParentChange);
286 d->target = target;
287}
288
289/*!
290 \qmlproperty Item QtQuick::ParentChange::parent
291 This property holds the new parent for the item in this state.
292*/
293QQuickItem *QQuickParentChange::parent() const
294{
295 Q_D(const QQuickParentChange);
296 return d->parent;
297}
298
299void QQuickParentChange::setParent(QQuickItem *parent)
300{
301 Q_D(QQuickParentChange);
302 d->parent = parent;
303}
304
305QQuickStateOperation::ActionList QQuickParentChange::actions()
306{
307 Q_D(QQuickParentChange);
308 if (!d->target || !d->parent)
309 return ActionList();
310
311 ActionList actions;
312
313 QQuickStateAction a;
314 a.event = this;
315 actions << a;
316
317 if (d->xString.isValid()) {
318 bool ok = false;
319 qreal x = d->xString.value().numberLiteral(&ok);
320 if (ok) {
321 QQuickStateAction xa(d->target, QLatin1String("x"), x);
322 actions << xa;
323 } else {
324 QQmlProperty property(d->target, QLatin1String("x"));
325 auto newBinding = QQmlAnyBinding::createFromScriptString(
326 property, d->xString.value(), d->target, qmlContext(this));
327 QQuickStateAction xa;
328 xa.property = property;
329 xa.toBinding = newBinding;
330 xa.fromValue = xa.property.read();
331 xa.deletableToBinding = true;
332 actions << xa;
333 }
334 }
335
336 if (d->yString.isValid()) {
337 bool ok = false;
338 qreal y = d->yString.value().numberLiteral(&ok);
339 if (ok) {
340 QQuickStateAction ya(d->target, QLatin1String("y"), y);
341 actions << ya;
342 } else {
343 QQmlProperty property(d->target, QLatin1String("y"));
344 auto newBinding = QQmlAnyBinding::createFromScriptString(
345 property, d->yString.value(), d->target, qmlContext(this));
346 QQuickStateAction ya;
347 ya.property = property;
348 ya.toBinding = newBinding;
349 ya.fromValue = ya.property.read();
350 ya.deletableToBinding = true;
351 actions << ya;
352 }
353 }
354
355 if (d->scaleString.isValid()) {
356 bool ok = false;
357 qreal scale = d->scaleString.value().numberLiteral(&ok);
358 if (ok) {
359 QQuickStateAction sa(d->target, QLatin1String("scale"), scale);
360 actions << sa;
361 } else {
362 QQmlProperty property(d->target, QLatin1String("scale"));
363 auto newBinding = QQmlAnyBinding::createFromScriptString(
364 property, d->scaleString.value(), d->target, qmlContext(this));
365 QQuickStateAction sa;
366 sa.property = property;
367 sa.toBinding = newBinding;
368 sa.fromValue = sa.property.read();
369 sa.deletableToBinding = true;
370 actions << sa;
371 }
372 }
373
374 if (d->rotationString.isValid()) {
375 bool ok = false;
376 qreal rotation = d->rotationString.value().numberLiteral(&ok);
377 if (ok) {
378 QQuickStateAction ra(d->target, QLatin1String("rotation"), rotation);
379 actions << ra;
380 } else {
381 QQmlProperty property(d->target, QLatin1String("rotation"));
382 auto newBinding = QQmlAnyBinding::createFromScriptString(
383 property, d->rotationString.value(), d->target, qmlContext(this));
384 QQuickStateAction ra;
385 ra.property = property;
386 ra.toBinding = newBinding;
387 ra.fromValue = ra.property.read();
388 ra.deletableToBinding = true;
389 actions << ra;
390 }
391 }
392
393 if (d->widthString.isValid()) {
394 bool ok = false;
395 qreal width = d->widthString.value().numberLiteral(&ok);
396 if (ok) {
397 QQuickStateAction wa(d->target, QLatin1String("width"), width);
398 actions << wa;
399 } else {
400 QQmlProperty property(d->target, QLatin1String("width"));
401 auto newBinding = QQmlAnyBinding::createFromScriptString(property, d->widthString, d->target, qmlContext(this));
402 QQuickStateAction wa;
403 wa.property = property;
404 wa.toBinding = newBinding;
405 wa.fromValue = wa.property.read();
406 wa.deletableToBinding = true;
407 actions << wa;
408 }
409 }
410
411 if (d->heightString.isValid()) {
412 bool ok = false;
413 qreal height = d->heightString.value().numberLiteral(&ok);
414 if (ok) {
415 QQuickStateAction ha(d->target, QLatin1String("height"), height);
416 actions << ha;
417 } else {
418 QQmlProperty property(d->target, QLatin1String("height"));
419 auto newBinding = QQmlAnyBinding::createFromScriptString(property, d->heightString, d->target, qmlContext(this));
420 QQuickStateAction ha;
421 ha.property = property;
422 ha.toBinding = newBinding;
423 ha.fromValue = ha.property.read();
424 ha.deletableToBinding = true;
425 actions << ha;
426 }
427 }
428
429 return actions;
430}
431
432void QQuickParentChange::saveOriginals()
433{
434 Q_D(QQuickParentChange);
435 saveCurrentValues();
436 if (!d->orig)
437 d->orig.reset(new QQuickParentChangePrivate::StateSnapshot);
438 *d->orig = *d->rewind;
439}
440
441void QQuickParentChange::execute()
442{
443 Q_D(QQuickParentChange);
444 d->doChange(d->parent);
445}
446
447bool QQuickParentChange::isReversable()
448{
449 return true;
450}
451
452void QQuickParentChangePrivate::reverseRewindHelper(const std::unique_ptr<QQuickParentChangePrivate::StateSnapshot> &snapshot)
453{
454 if (!target || !snapshot)
455 return;
456
457 // leave existing bindings alive; new bindings are applied in applyBindings
458 // setPosition and setSize update the geometry without invalidating bindings
459 target->setPosition(QPointF(snapshot->x, snapshot->y));
460 target->setSize(QSizeF(snapshot->width, snapshot->height));
461
462 target->setScale(snapshot->scale);
463 target->setRotation(snapshot->rotation);
464 target->setParentItem(snapshot->parent);
465 if (snapshot->stackBefore)
466 target->stackBefore(snapshot->stackBefore);
467}
468
469
470void QQuickParentChange::reverse()
471{
472 Q_D(QQuickParentChange);
473 d->reverseRewindHelper(d->orig);
474}
475
476QQuickStateActionEvent::EventType QQuickParentChange::type() const
477{
478 return ParentChange;
479}
480
481bool QQuickParentChange::mayOverride(QQuickStateActionEvent*other)
482{
483 Q_D(QQuickParentChange);
484 if (other->type() != ParentChange)
485 return false;
486 if (QQuickParentChange *otherPC = static_cast<QQuickParentChange*>(other))
487 return (d->target == otherPC->object());
488 return false;
489}
490
491void QQuickParentChange::saveCurrentValues()
492{
493 Q_D(QQuickParentChange);
494 if (!d->target) {
495 d->rewind = nullptr;
496 return;
497 }
498
499 d->rewind.reset(new QQuickParentChangePrivate::StateSnapshot);
500 d->rewind->x = d->target->x();
501 d->rewind->y = d->target->y();
502 d->rewind->scale = d->target->scale();
503 d->rewind->width = d->target->width();
504 d->rewind->height = d->target->height();
505 d->rewind->rotation = d->target->rotation();
506
507 d->rewind->parent = d->target->parentItem();
508 d->rewind->stackBefore = nullptr;
509
510 if (!d->rewind->parent)
511 return;
512
513 QList<QQuickItem *> children = d->rewind->parent->childItems();
514 for (int ii = 0; ii < children.size() - 1; ++ii) {
515 if (children.at(ii) == d->target) {
516 d->rewind->stackBefore = children.at(ii + 1);
517 break;
518 }
519 }
520}
521
522void QQuickParentChange::rewind()
523{
524 Q_D(QQuickParentChange);
525 d->reverseRewindHelper(d->rewind);
526 d->rewind.reset();
527}
528
529/*!
530 \qmltype AnchorChanges
531 \nativetype QQuickAnchorChanges
532 \inqmlmodule QtQuick
533 \ingroup qtquick-states
534 \brief Specifies how to change the anchors of an item in a state.
535
536 The AnchorChanges type is used to modify the anchors of an item in a \l State.
537
538 AnchorChanges cannot be used to modify the margins on an item. For this, use
539 PropertyChanges instead.
540
541 In the following example we change the top and bottom anchors of an item
542 using AnchorChanges, and the top and bottom anchor margins using
543 PropertyChanges:
544
545 \snippet qml/anchorchanges.qml 0
546
547 \image anchorchanges.png
548
549 AnchorChanges can be animated using AnchorAnimation.
550 \qml
551 //animate our anchor changes
552 Transition {
553 AnchorAnimation {}
554 }
555 \endqml
556
557 Changes to anchor margins can be animated using NumberAnimation.
558
559 For more information on anchors see \l {anchor-layout}{Anchor Layouts}.
560*/
561
577
578QQuickAnchorSet::QQuickAnchorSet(QObject *parent)
579 : QObject(*new QQuickAnchorSetPrivate, parent)
580{
581}
582
583QQuickAnchorSet::~QQuickAnchorSet()
584{
585}
586
587QQmlScriptString QQuickAnchorSet::top() const
588{
589 Q_D(const QQuickAnchorSet);
590 return d->topScript;
591}
592
593void QQuickAnchorSet::setTop(const QQmlScriptString &edge)
594{
595 Q_D(QQuickAnchorSet);
596 d->usedAnchors |= QQuickAnchors::TopAnchor;
597 d->topScript = edge;
598 if (edge.isUndefinedLiteral())
599 resetTop();
600}
601
602void QQuickAnchorSet::resetTop()
603{
604 Q_D(QQuickAnchorSet);
605 d->usedAnchors &= ~QQuickAnchors::TopAnchor;
606 d->resetAnchors |= QQuickAnchors::TopAnchor;
607}
608
609QQmlScriptString QQuickAnchorSet::bottom() const
610{
611 Q_D(const QQuickAnchorSet);
612 return d->bottomScript;
613}
614
615void QQuickAnchorSet::setBottom(const QQmlScriptString &edge)
616{
617 Q_D(QQuickAnchorSet);
618 d->usedAnchors |= QQuickAnchors::BottomAnchor;
619 d->bottomScript = edge;
620 if (edge.isUndefinedLiteral())
621 resetBottom();
622}
623
624void QQuickAnchorSet::resetBottom()
625{
626 Q_D(QQuickAnchorSet);
627 d->usedAnchors &= ~QQuickAnchors::BottomAnchor;
628 d->resetAnchors |= QQuickAnchors::BottomAnchor;
629}
630
631QQmlScriptString QQuickAnchorSet::verticalCenter() const
632{
633 Q_D(const QQuickAnchorSet);
634 return d->vCenterScript;
635}
636
637void QQuickAnchorSet::setVerticalCenter(const QQmlScriptString &edge)
638{
639 Q_D(QQuickAnchorSet);
640 d->usedAnchors |= QQuickAnchors::VCenterAnchor;
641 d->vCenterScript = edge;
642 if (edge.isUndefinedLiteral())
643 resetVerticalCenter();
644}
645
646void QQuickAnchorSet::resetVerticalCenter()
647{
648 Q_D(QQuickAnchorSet);
649 d->usedAnchors &= ~QQuickAnchors::VCenterAnchor;
650 d->resetAnchors |= QQuickAnchors::VCenterAnchor;
651}
652
653QQmlScriptString QQuickAnchorSet::baseline() const
654{
655 Q_D(const QQuickAnchorSet);
656 return d->baselineScript;
657}
658
659void QQuickAnchorSet::setBaseline(const QQmlScriptString &edge)
660{
661 Q_D(QQuickAnchorSet);
662 d->usedAnchors |= QQuickAnchors::BaselineAnchor;
663 d->baselineScript = edge;
664 if (edge.isUndefinedLiteral())
665 resetBaseline();
666}
667
668void QQuickAnchorSet::resetBaseline()
669{
670 Q_D(QQuickAnchorSet);
671 d->usedAnchors &= ~QQuickAnchors::BaselineAnchor;
672 d->resetAnchors |= QQuickAnchors::BaselineAnchor;
673}
674
675QQmlScriptString QQuickAnchorSet::left() const
676{
677 Q_D(const QQuickAnchorSet);
678 return d->leftScript;
679}
680
681void QQuickAnchorSet::setLeft(const QQmlScriptString &edge)
682{
683 Q_D(QQuickAnchorSet);
684 d->usedAnchors |= QQuickAnchors::LeftAnchor;
685 d->leftScript = edge;
686 if (edge.isUndefinedLiteral())
687 resetLeft();
688}
689
690void QQuickAnchorSet::resetLeft()
691{
692 Q_D(QQuickAnchorSet);
693 d->usedAnchors &= ~QQuickAnchors::LeftAnchor;
694 d->resetAnchors |= QQuickAnchors::LeftAnchor;
695}
696
697QQmlScriptString QQuickAnchorSet::right() const
698{
699 Q_D(const QQuickAnchorSet);
700 return d->rightScript;
701}
702
703void QQuickAnchorSet::setRight(const QQmlScriptString &edge)
704{
705 Q_D(QQuickAnchorSet);
706 d->usedAnchors |= QQuickAnchors::RightAnchor;
707 d->rightScript = edge;
708 if (edge.isUndefinedLiteral())
709 resetRight();
710}
711
712void QQuickAnchorSet::resetRight()
713{
714 Q_D(QQuickAnchorSet);
715 d->usedAnchors &= ~QQuickAnchors::RightAnchor;
716 d->resetAnchors |= QQuickAnchors::RightAnchor;
717}
718
719QQmlScriptString QQuickAnchorSet::horizontalCenter() const
720{
721 Q_D(const QQuickAnchorSet);
722 return d->hCenterScript;
723}
724
725void QQuickAnchorSet::setHorizontalCenter(const QQmlScriptString &edge)
726{
727 Q_D(QQuickAnchorSet);
728 d->usedAnchors |= QQuickAnchors::HCenterAnchor;
729 d->hCenterScript = edge;
730 if (edge.isUndefinedLiteral())
731 resetHorizontalCenter();
732}
733
734void QQuickAnchorSet::resetHorizontalCenter()
735{
736 Q_D(QQuickAnchorSet);
737 d->usedAnchors &= ~QQuickAnchors::HCenterAnchor;
738 d->resetAnchors |= QQuickAnchors::HCenterAnchor;
739}
740
742{
743public:
745 : target(nullptr), anchorSet(new QQuickAnchorSet)
746 {
747
748 }
749 ~QQuickAnchorChangesPrivate() { delete anchorSet; }
750
751 QQuickItem *target;
753
761
769
770 QQuickAnchorLine rewindLeft;
771 QQuickAnchorLine rewindRight;
772 QQuickAnchorLine rewindHCenter;
773 QQuickAnchorLine rewindTop;
774 QQuickAnchorLine rewindBottom;
775 QQuickAnchorLine rewindVCenter;
776 QQuickAnchorLine rewindBaseline;
777
782
787
792
800
805
813};
814
815QQuickAnchorChanges::QQuickAnchorChanges(QObject *parent)
816 : QQuickStateOperation(*(new QQuickAnchorChangesPrivate), parent)
817{
818}
819
820QQuickAnchorChanges::ActionList QQuickAnchorChanges::actions()
821{
822 Q_D(QQuickAnchorChanges);
823 //### ASSERT these are all 0?
824 d->leftBinding = d->rightBinding = d->hCenterBinding = d->topBinding
825 = d->bottomBinding = d->vCenterBinding = d->baselineBinding = nullptr;
826
827 d->leftProp = QQmlProperty(d->target, QLatin1String("anchors.left"));
828 d->rightProp = QQmlProperty(d->target, QLatin1String("anchors.right"));
829 d->hCenterProp = QQmlProperty(d->target, QLatin1String("anchors.horizontalCenter"));
830 d->topProp = QQmlProperty(d->target, QLatin1String("anchors.top"));
831 d->bottomProp = QQmlProperty(d->target, QLatin1String("anchors.bottom"));
832 d->vCenterProp = QQmlProperty(d->target, QLatin1String("anchors.verticalCenter"));
833 d->baselineProp = QQmlProperty(d->target, QLatin1String("anchors.baseline"));
834
835 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::LeftAnchor) {
836 d->leftBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->leftProp)->core, d->anchorSet->d_func()->leftScript, d->target, qmlContext(this));
837 d->leftBinding->setTarget(d->leftProp);
838 }
839 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::RightAnchor) {
840 d->rightBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->rightProp)->core, d->anchorSet->d_func()->rightScript, d->target, qmlContext(this));
841 d->rightBinding->setTarget(d->rightProp);
842 }
843 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::HCenterAnchor) {
844 d->hCenterBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->hCenterProp)->core, d->anchorSet->d_func()->hCenterScript, d->target, qmlContext(this));
845 d->hCenterBinding->setTarget(d->hCenterProp);
846 }
847 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::TopAnchor) {
848 d->topBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->topProp)->core, d->anchorSet->d_func()->topScript, d->target, qmlContext(this));
849 d->topBinding->setTarget(d->topProp);
850 }
851 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::BottomAnchor) {
852 d->bottomBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->bottomProp)->core, d->anchorSet->d_func()->bottomScript, d->target, qmlContext(this));
853 d->bottomBinding->setTarget(d->bottomProp);
854 }
855 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::VCenterAnchor) {
856 d->vCenterBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->vCenterProp)->core, d->anchorSet->d_func()->vCenterScript, d->target, qmlContext(this));
857 d->vCenterBinding->setTarget(d->vCenterProp);
858 }
859 if (d->anchorSet->d_func()->usedAnchors & QQuickAnchors::BaselineAnchor) {
860 d->baselineBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(d->baselineProp)->core, d->anchorSet->d_func()->baselineScript, d->target, qmlContext(this));
861 d->baselineBinding->setTarget(d->baselineProp);
862 }
863
864 QQuickStateAction a;
865 a.event = this;
866 return ActionList() << a;
867}
868
869QQuickAnchorSet *QQuickAnchorChanges::anchors() const
870{
871 Q_D(const QQuickAnchorChanges);
872 return d->anchorSet;
873}
874
875/*!
876 \qmlproperty Item QtQuick::AnchorChanges::target
877 This property holds the \l Item for which the anchor changes will be applied.
878*/
879QQuickItem *QQuickAnchorChanges::object() const
880{
881 Q_D(const QQuickAnchorChanges);
882 return d->target;
883}
884
885void QQuickAnchorChanges::setObject(QQuickItem *target)
886{
887 Q_D(QQuickAnchorChanges);
888 d->target = target;
889}
890
891/*!
892 \qmlpropertygroup QtQuick::AnchorChanges::anchors
893 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.left
894 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.right
895 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.horizontalCenter
896 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.top
897 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.bottom
898 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.verticalCenter
899 \qmlproperty AnchorLine QtQuick::AnchorChanges::anchors.baseline
900
901 These properties change the respective anchors of the item.
902
903 To reset an anchor you can assign \c undefined:
904 \qml
905 AnchorChanges {
906 target: myItem
907 anchors.left: undefined //remove myItem's left anchor
908 anchors.right: otherItem.right
909 }
910 \endqml
911*/
912
913void QQuickAnchorChanges::execute()
914{
915 Q_D(QQuickAnchorChanges);
916 if (!d->target)
917 return;
918
919 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
920 //incorporate any needed "reverts"
921 if (d->applyOrigLeft) {
922 if (!d->origLeftBinding)
923 targetPrivate->anchors()->resetLeft();
924 QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data());
925 }
926 if (d->applyOrigRight) {
927 if (!d->origRightBinding)
928 targetPrivate->anchors()->resetRight();
929 QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data());
930 }
931 if (d->applyOrigHCenter) {
932 if (!d->origHCenterBinding)
933 targetPrivate->anchors()->resetHorizontalCenter();
934 QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data());
935 }
936 if (d->applyOrigTop) {
937 if (!d->origTopBinding)
938 targetPrivate->anchors()->resetTop();
939 QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data());
940 }
941 if (d->applyOrigBottom) {
942 if (!d->origBottomBinding)
943 targetPrivate->anchors()->resetBottom();
944 QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data());
945 }
946 if (d->applyOrigVCenter) {
947 if (!d->origVCenterBinding)
948 targetPrivate->anchors()->resetVerticalCenter();
949 QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data());
950 }
951 if (d->applyOrigBaseline) {
952 if (!d->origBaselineBinding)
953 targetPrivate->anchors()->resetBaseline();
954 QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data());
955 }
956
957 //reset any anchors that have been specified as "undefined"
958 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::LeftAnchor) {
959 targetPrivate->anchors()->resetLeft();
960 QQmlPropertyPrivate::removeBinding(d->leftProp);
961 }
962 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::RightAnchor) {
963 targetPrivate->anchors()->resetRight();
964 QQmlPropertyPrivate::removeBinding(d->rightProp);
965 }
966 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::HCenterAnchor) {
967 targetPrivate->anchors()->resetHorizontalCenter();
968 QQmlPropertyPrivate::removeBinding(d->hCenterProp);
969 }
970 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::TopAnchor) {
971 targetPrivate->anchors()->resetTop();
972 QQmlPropertyPrivate::removeBinding(d->topProp);
973 }
974 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BottomAnchor) {
975 targetPrivate->anchors()->resetBottom();
976 QQmlPropertyPrivate::removeBinding(d->bottomProp);
977 }
978 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::VCenterAnchor) {
979 targetPrivate->anchors()->resetVerticalCenter();
980 QQmlPropertyPrivate::removeBinding(d->vCenterProp);
981 }
982 if (d->anchorSet->d_func()->resetAnchors & QQuickAnchors::BaselineAnchor) {
983 targetPrivate->anchors()->resetBaseline();
984 QQmlPropertyPrivate::removeBinding(d->baselineProp);
985 }
986
987 //set any anchors that have been specified
988 if (d->leftBinding)
989 QQmlPropertyPrivate::setBinding(d->leftBinding.data());
990 if (d->rightBinding)
991 QQmlPropertyPrivate::setBinding(d->rightBinding.data());
992 if (d->hCenterBinding)
993 QQmlPropertyPrivate::setBinding(d->hCenterBinding.data());
994 if (d->topBinding)
995 QQmlPropertyPrivate::setBinding(d->topBinding.data());
996 if (d->bottomBinding)
997 QQmlPropertyPrivate::setBinding(d->bottomBinding.data());
998 if (d->vCenterBinding)
999 QQmlPropertyPrivate::setBinding(d->vCenterBinding.data());
1000 if (d->baselineBinding)
1001 QQmlPropertyPrivate::setBinding(d->baselineBinding.data());
1002}
1003
1004bool QQuickAnchorChanges::isReversable()
1005{
1006 return true;
1007}
1008
1009void QQuickAnchorChanges::reverse()
1010{
1011 Q_D(QQuickAnchorChanges);
1012 if (!d->target)
1013 return;
1014
1015 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1016 //reset any anchors set by the state
1017 if (d->leftBinding) {
1018 targetPrivate->anchors()->resetLeft();
1019 QQmlPropertyPrivate::removeBinding(d->leftBinding.data());
1020 }
1021 if (d->rightBinding) {
1022 targetPrivate->anchors()->resetRight();
1023 QQmlPropertyPrivate::removeBinding(d->rightBinding.data());
1024 }
1025 if (d->hCenterBinding) {
1026 targetPrivate->anchors()->resetHorizontalCenter();
1027 QQmlPropertyPrivate::removeBinding(d->hCenterBinding.data());
1028 }
1029 if (d->topBinding) {
1030 targetPrivate->anchors()->resetTop();
1031 QQmlPropertyPrivate::removeBinding(d->topBinding.data());
1032 }
1033 if (d->bottomBinding) {
1034 targetPrivate->anchors()->resetBottom();
1035 QQmlPropertyPrivate::removeBinding(d->bottomBinding.data());
1036 }
1037 if (d->vCenterBinding) {
1038 targetPrivate->anchors()->resetVerticalCenter();
1039 QQmlPropertyPrivate::removeBinding(d->vCenterBinding.data());
1040 }
1041 if (d->baselineBinding) {
1042 targetPrivate->anchors()->resetBaseline();
1043 QQmlPropertyPrivate::removeBinding(d->baselineBinding.data());
1044 }
1045
1046 //restore previous anchors
1047 if (d->origLeftBinding)
1048 QQmlPropertyPrivate::setBinding(d->leftProp, d->origLeftBinding.data());
1049 if (d->origRightBinding)
1050 QQmlPropertyPrivate::setBinding(d->rightProp, d->origRightBinding.data());
1051 if (d->origHCenterBinding)
1052 QQmlPropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding.data());
1053 if (d->origTopBinding)
1054 QQmlPropertyPrivate::setBinding(d->topProp, d->origTopBinding.data());
1055 if (d->origBottomBinding)
1056 QQmlPropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding.data());
1057 if (d->origVCenterBinding)
1058 QQmlPropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding.data());
1059 if (d->origBaselineBinding)
1060 QQmlPropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding.data());
1061
1062 //restore any absolute geometry changed by the state's anchors
1063 QQuickAnchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Vertical_Mask;
1064 QQuickAnchors::Anchors origVAnchors = targetPrivate->anchors()->usedAnchors() & QQuickAnchors::Vertical_Mask;
1065 QQuickAnchors::Anchors resetVAnchors = d->anchorSet->d_func()->resetAnchors & QQuickAnchors::Vertical_Mask;
1066 QQuickAnchors::Anchors stateHAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Horizontal_Mask;
1067 QQuickAnchors::Anchors origHAnchors = targetPrivate->anchors()->usedAnchors() & QQuickAnchors::Horizontal_Mask;
1068 QQuickAnchors::Anchors resetHAnchors = d->anchorSet->d_func()->resetAnchors & QQuickAnchors::Horizontal_Mask;
1069
1070 const QRectF oldGeometry(d->target->position(), d->target->size());
1071 bool stateSetWidth = (stateHAnchors &&
1072 stateHAnchors != QQuickAnchors::LeftAnchor &&
1073 stateHAnchors != QQuickAnchors::RightAnchor &&
1074 stateHAnchors != QQuickAnchors::HCenterAnchor);
1075 // in case of an additive AnchorChange, we _did_ end up modifying the width, unless opposite
1076 // edge was set to undefined in state
1077 stateSetWidth |= ((stateHAnchors & QQuickAnchors::LeftAnchor)
1078 && (origHAnchors & QQuickAnchors::RightAnchor)
1079 && !(resetHAnchors & QQuickAnchors::RightAnchor))
1080 || ((stateHAnchors & QQuickAnchors::RightAnchor)
1081 && (origHAnchors & QQuickAnchors::LeftAnchor)
1082 && !(resetHAnchors & QQuickAnchors::LeftAnchor));
1083 bool origSetWidth = (origHAnchors &&
1084 origHAnchors != QQuickAnchors::LeftAnchor &&
1085 origHAnchors != QQuickAnchors::RightAnchor &&
1086 origHAnchors != QQuickAnchors::HCenterAnchor);
1087 if (d->origWidth.isValid() && stateSetWidth && !origSetWidth && !qt_is_nan(d->origWidth)) {
1088 targetPrivate->widthValidFlag = true;
1089 if (targetPrivate->width != d->origWidth)
1090 targetPrivate->width.setValueBypassingBindings(d->origWidth);
1091 }
1092
1093 bool stateSetHeight = (stateVAnchors &&
1094 stateVAnchors != QQuickAnchors::TopAnchor &&
1095 stateVAnchors != QQuickAnchors::BottomAnchor &&
1096 stateVAnchors != QQuickAnchors::VCenterAnchor &&
1097 stateVAnchors != QQuickAnchors::BaselineAnchor);
1098 // in case of an additive AnchorChange, we _did_ end up modifying the height, unless opposite
1099 // edge was set to undefined in state
1100 stateSetHeight |= ((stateVAnchors & QQuickAnchors::TopAnchor)
1101 && (origVAnchors & QQuickAnchors::BottomAnchor)
1102 && !(resetVAnchors & QQuickAnchors::BottomAnchor))
1103 || ((stateVAnchors & QQuickAnchors::BottomAnchor)
1104 && (origVAnchors & QQuickAnchors::TopAnchor)
1105 && !(resetVAnchors & QQuickAnchors::TopAnchor));
1106 bool origSetHeight = (origVAnchors &&
1107 origVAnchors != QQuickAnchors::TopAnchor &&
1108 origVAnchors != QQuickAnchors::BottomAnchor &&
1109 origVAnchors != QQuickAnchors::VCenterAnchor &&
1110 origVAnchors != QQuickAnchors::BaselineAnchor);
1111 if (d->origHeight.isValid() && stateSetHeight && !origSetHeight && !qt_is_nan(d->origHeight)) {
1112 targetPrivate->heightValidFlag = true;
1113 if (targetPrivate->height != d->origHeight)
1114 targetPrivate->height.setValueBypassingBindings(d->origHeight);
1115 }
1116
1117 if (stateHAnchors && !origHAnchors && !qt_is_nan(d->origX) && d->origX != targetPrivate->x)
1118 targetPrivate->x.setValueBypassingBindings(d->origX);
1119
1120 if (stateVAnchors && !origVAnchors && !qt_is_nan(d->origY) && d->origY != targetPrivate->y)
1121 targetPrivate->y.setValueBypassingBindings(d->origY);
1122
1123 const QRectF newGeometry(d->target->position(), d->target->size());
1124 if (newGeometry != oldGeometry) {
1125 QQuickItemPrivate::DirtyType dirtyFlags {};
1126 if (newGeometry.topLeft() != oldGeometry.topLeft())
1127 dirtyFlags = QQuickItemPrivate::DirtyType(dirtyFlags | QQuickItemPrivate::Position);
1128 if (newGeometry.size() != oldGeometry.size())
1129 dirtyFlags = QQuickItemPrivate::DirtyType(dirtyFlags | QQuickItemPrivate::Size);
1130 targetPrivate->dirty(dirtyFlags);
1131 d->target->geometryChange(newGeometry, oldGeometry);
1132 }
1133}
1134
1135QQuickStateActionEvent::EventType QQuickAnchorChanges::type() const
1136{
1137 return AnchorChanges;
1138}
1139
1140QList<QQuickStateAction> QQuickAnchorChanges::additionalActions() const
1141{
1142 Q_D(const QQuickAnchorChanges);
1143 QList<QQuickStateAction> extra;
1144
1145 QQuickAnchors::Anchors combined = d->anchorSet->d_func()->usedAnchors | d->anchorSet->d_func()->resetAnchors;
1146 bool hChange = combined & QQuickAnchors::Horizontal_Mask;
1147 bool vChange = combined & QQuickAnchors::Vertical_Mask;
1148
1149 if (d->target) {
1150 QQuickStateAction a;
1151 if (hChange && d->fromX != d->toX) {
1152 a.property = QQmlProperty(d->target, QLatin1String("x"));
1153 a.toValue = d->toX;
1154 extra << a;
1155 }
1156 if (vChange && d->fromY != d->toY) {
1157 a.property = QQmlProperty(d->target, QLatin1String("y"));
1158 a.toValue = d->toY;
1159 extra << a;
1160 }
1161 if (hChange && d->fromWidth != d->toWidth) {
1162 a.property = QQmlProperty(d->target, QLatin1String("width"));
1163 a.toValue = d->toWidth;
1164 extra << a;
1165 }
1166 if (vChange && d->fromHeight != d->toHeight) {
1167 a.property = QQmlProperty(d->target, QLatin1String("height"));
1168 a.toValue = d->toHeight;
1169 extra << a;
1170 }
1171 }
1172
1173 return extra;
1174}
1175
1176bool QQuickAnchorChanges::changesBindings()
1177{
1178 return true;
1179}
1180
1181void QQuickAnchorChanges::saveOriginals()
1182{
1183 Q_D(QQuickAnchorChanges);
1184 if (!d->target)
1185 return;
1186
1187 d->origLeftBinding = QQmlPropertyPrivate::binding(d->leftProp);
1188 d->origRightBinding = QQmlPropertyPrivate::binding(d->rightProp);
1189 d->origHCenterBinding = QQmlPropertyPrivate::binding(d->hCenterProp);
1190 d->origTopBinding = QQmlPropertyPrivate::binding(d->topProp);
1191 d->origBottomBinding = QQmlPropertyPrivate::binding(d->bottomProp);
1192 d->origVCenterBinding = QQmlPropertyPrivate::binding(d->vCenterProp);
1193 d->origBaselineBinding = QQmlPropertyPrivate::binding(d->baselineProp);
1194
1195 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1196 if (targetPrivate->widthValid())
1197 d->origWidth = d->target->width();
1198 if (targetPrivate->heightValid())
1199 d->origHeight = d->target->height();
1200 d->origX = d->target->x();
1201 d->origY = d->target->y();
1202
1203 d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop
1204 = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false;
1205
1206 saveCurrentValues();
1207}
1208
1209void QQuickAnchorChanges::copyOriginals(QQuickStateActionEvent *other)
1210{
1211 Q_D(QQuickAnchorChanges);
1212 QQuickAnchorChanges *ac = static_cast<QQuickAnchorChanges*>(other);
1213 QQuickAnchorChangesPrivate *acp = ac->d_func();
1214
1215 QQuickAnchors::Anchors combined = acp->anchorSet->d_func()->usedAnchors |
1216 acp->anchorSet->d_func()->resetAnchors;
1217
1218 //probably also need to revert some things
1219 d->applyOrigLeft = (combined & QQuickAnchors::LeftAnchor);
1220 d->applyOrigRight = (combined & QQuickAnchors::RightAnchor);
1221 d->applyOrigHCenter = (combined & QQuickAnchors::HCenterAnchor);
1222 d->applyOrigTop = (combined & QQuickAnchors::TopAnchor);
1223 d->applyOrigBottom = (combined & QQuickAnchors::BottomAnchor);
1224 d->applyOrigVCenter = (combined & QQuickAnchors::VCenterAnchor);
1225 d->applyOrigBaseline = (combined & QQuickAnchors::BaselineAnchor);
1226
1227 d->origLeftBinding = acp->origLeftBinding;
1228 d->origRightBinding = acp->origRightBinding;
1229 d->origHCenterBinding = acp->origHCenterBinding;
1230 d->origTopBinding = acp->origTopBinding;
1231 d->origBottomBinding = acp->origBottomBinding;
1232 d->origVCenterBinding = acp->origVCenterBinding;
1233 d->origBaselineBinding = acp->origBaselineBinding;
1234
1235 d->origWidth = acp->origWidth;
1236 d->origHeight = acp->origHeight;
1237 d->origX = acp->origX;
1238 d->origY = acp->origY;
1239
1240 //clear old values from other
1241 //### could this be generalized for all QQuickStateActionEvents, and called after copyOriginals?
1242 acp->leftBinding = nullptr;
1243 acp->rightBinding = nullptr;
1244 acp->hCenterBinding = nullptr;
1245 acp->topBinding = nullptr;
1246 acp->bottomBinding = nullptr;
1247 acp->vCenterBinding = nullptr;
1248 acp->baselineBinding = nullptr;
1249 acp->origLeftBinding = nullptr;
1250 acp->origRightBinding = nullptr;
1251 acp->origHCenterBinding = nullptr;
1252 acp->origTopBinding = nullptr;
1253 acp->origBottomBinding = nullptr;
1254 acp->origVCenterBinding = nullptr;
1255 acp->origBaselineBinding = nullptr;
1256
1257 saveCurrentValues();
1258}
1259
1260void QQuickAnchorChanges::clearBindings()
1261{
1262 Q_D(QQuickAnchorChanges);
1263 if (!d->target)
1264 return;
1265
1266 //### should this (saving "from" values) be moved to saveCurrentValues()?
1267 d->fromX = d->target->x();
1268 d->fromY = d->target->y();
1269 d->fromWidth = d->target->width();
1270 d->fromHeight = d->target->height();
1271
1272 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1273 //reset any anchors with corresponding reverts
1274 //reset any anchors that have been specified as "undefined"
1275 //reset any anchors that we'll be setting in the state
1276 QQuickAnchors::Anchors combined = d->anchorSet->d_func()->resetAnchors |
1277 d->anchorSet->d_func()->usedAnchors;
1278 if (d->applyOrigLeft || (combined & QQuickAnchors::LeftAnchor)) {
1279 targetPrivate->anchors()->resetLeft();
1280 QQmlPropertyPrivate::removeBinding(d->leftProp);
1281 }
1282 if (d->applyOrigRight || (combined & QQuickAnchors::RightAnchor)) {
1283 targetPrivate->anchors()->resetRight();
1284 QQmlPropertyPrivate::removeBinding(d->rightProp);
1285 }
1286 if (d->applyOrigHCenter || (combined & QQuickAnchors::HCenterAnchor)) {
1287 targetPrivate->anchors()->resetHorizontalCenter();
1288 QQmlPropertyPrivate::removeBinding(d->hCenterProp);
1289 }
1290 if (d->applyOrigTop || (combined & QQuickAnchors::TopAnchor)) {
1291 targetPrivate->anchors()->resetTop();
1292 QQmlPropertyPrivate::removeBinding(d->topProp);
1293 }
1294 if (d->applyOrigBottom || (combined & QQuickAnchors::BottomAnchor)) {
1295 targetPrivate->anchors()->resetBottom();
1296 QQmlPropertyPrivate::removeBinding(d->bottomProp);
1297 }
1298 if (d->applyOrigVCenter || (combined & QQuickAnchors::VCenterAnchor)) {
1299 targetPrivate->anchors()->resetVerticalCenter();
1300 QQmlPropertyPrivate::removeBinding(d->vCenterProp);
1301 }
1302 if (d->applyOrigBaseline || (combined & QQuickAnchors::BaselineAnchor)) {
1303 targetPrivate->anchors()->resetBaseline();
1304 QQmlPropertyPrivate::removeBinding(d->baselineProp);
1305 }
1306}
1307
1308bool QQuickAnchorChanges::mayOverride(QQuickStateActionEvent*other)
1309{
1310 if (other->type() != AnchorChanges)
1311 return false;
1312 if (static_cast<QQuickStateActionEvent*>(this) == other)
1313 return true;
1314 if (static_cast<QQuickAnchorChanges*>(other)->object() == object())
1315 return true;
1316 return false;
1317}
1318
1319void QQuickAnchorChanges::rewind()
1320{
1321 Q_D(QQuickAnchorChanges);
1322 if (!d->target)
1323 return;
1324
1325 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1326 const QRectF oldGeometry(d->target->position(), d->target->size());
1327
1328 // Restore previous values (but not previous bindings, i.e. anchors).
1329 // Also, don't drop any new bindings.
1330 if (!qt_is_nan(d->rewindX) && d->rewindX != targetPrivate->x)
1331 targetPrivate->x.setValueBypassingBindings(d->rewindX);
1332 if (!qt_is_nan(d->rewindY) && d->rewindY != targetPrivate->y)
1333 targetPrivate->y.setValueBypassingBindings(d->rewindY);
1334
1335 if (targetPrivate->widthValid() && !qt_is_nan(d->rewindWidth)) {
1336 targetPrivate->widthValidFlag = true;
1337 if (d->rewindWidth != targetPrivate->width)
1338 targetPrivate->width.setValueBypassingBindings(d->rewindWidth);
1339 }
1340
1341 if (targetPrivate->heightValid() && !qt_is_nan(d->rewindHeight)) {
1342 targetPrivate->heightValidFlag = true;
1343 if (d->rewindHeight != targetPrivate->height)
1344 targetPrivate->height.setValueBypassingBindings(d->rewindHeight);
1345 }
1346
1347 const QRectF newGeometry(d->target->position(), d->target->size());
1348 if (newGeometry != oldGeometry) {
1349 targetPrivate->dirty(QQuickItemPrivate::Position);
1350 d->target->geometryChange(newGeometry, oldGeometry);
1351 }
1352}
1353
1354void QQuickAnchorChanges::saveCurrentValues()
1355{
1356 Q_D(QQuickAnchorChanges);
1357 if (!d->target)
1358 return;
1359
1360 QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target);
1361 d->rewindLeft = targetPrivate->anchors()->left();
1362 d->rewindRight = targetPrivate->anchors()->right();
1363 d->rewindHCenter = targetPrivate->anchors()->horizontalCenter();
1364 d->rewindTop = targetPrivate->anchors()->top();
1365 d->rewindBottom = targetPrivate->anchors()->bottom();
1366 d->rewindVCenter = targetPrivate->anchors()->verticalCenter();
1367 d->rewindBaseline = targetPrivate->anchors()->baseline();
1368
1369 d->rewindX = d->target->x();
1370 d->rewindY = d->target->y();
1371 d->rewindWidth = d->target->width();
1372 d->rewindHeight = d->target->height();
1373}
1374
1375void QQuickAnchorChanges::saveTargetValues()
1376{
1377 Q_D(QQuickAnchorChanges);
1378 if (!d->target)
1379 return;
1380
1381 d->toX = d->target->x();
1382 d->toY = d->target->y();
1383 d->toWidth = d->target->width();
1384 d->toHeight = d->target->height();
1385}
1386
1387QT_END_NAMESPACE
1388
1389#include <moc_qquickstateoperations_p.cpp>
QQmlNullableValue< qreal > origWidth
QQmlAbstractBinding::Ptr origLeftBinding
QQmlAbstractBinding::Ptr origBottomBinding
QQmlAbstractBinding::Ptr origTopBinding
QQmlAbstractBinding::Ptr origHCenterBinding
QQmlAbstractBinding::Ptr origRightBinding
QQmlNullableValue< qreal > origHeight
QQmlAbstractBinding::Ptr origVCenterBinding
QQmlAbstractBinding::Ptr origBaselineBinding
QQuickAnchors::Anchors resetAnchors