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

source code of qtdeclarative/src/quick/items/qquickstateoperations.cpp