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