1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qsgstateoperations_p.h"
43 #include "qsgitem_p.h"
45 #include <private/qdeclarativestate_p_p.h>
47 #include <QtDeclarative/qdeclarativeinfo.h>
48 #include <QtCore/qmath.h>
52 class QSGParentChangePrivate : public QDeclarativeStateOperationPrivate
54 Q_DECLARE_PUBLIC(QSGParentChange)
56 QSGParentChangePrivate() : target(0), parent(0), origParent(0), origStackBefore(0),
57 rewindParent(0), rewindStackBefore(0) {}
60 QDeclarativeGuard<QSGItem> parent;
61 QDeclarativeGuard<QSGItem> origParent;
62 QDeclarativeGuard<QSGItem> origStackBefore;
63 QSGItem *rewindParent;
64 QSGItem *rewindStackBefore;
66 QDeclarativeNullableValue<QDeclarativeScriptString> xString;
67 QDeclarativeNullableValue<QDeclarativeScriptString> yString;
68 QDeclarativeNullableValue<QDeclarativeScriptString> widthString;
69 QDeclarativeNullableValue<QDeclarativeScriptString> heightString;
70 QDeclarativeNullableValue<QDeclarativeScriptString> scaleString;
71 QDeclarativeNullableValue<QDeclarativeScriptString> rotationString;
73 void doChange(QSGItem *targetParent, QSGItem *stackBefore = 0);
76 void QSGParentChangePrivate::doChange(QSGItem *targetParent, QSGItem *stackBefore)
78 if (targetParent && target && target->parentItem()) {
81 const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok);
82 if (transform.type() >= QTransform::TxShear || !ok) {
83 qmlInfo(q) << QSGParentChange::tr("Unable to preserve appearance under complex transform");
89 bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
90 if (ok && !isRotate) {
91 if (transform.m11() == transform.m22())
92 scale = transform.m11();
94 qmlInfo(q) << QSGParentChange::tr("Unable to preserve appearance under non-uniform scale");
97 } else if (ok && isRotate) {
98 if (transform.m11() == transform.m22())
99 scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
101 qmlInfo(q) << QSGParentChange::tr("Unable to preserve appearance under non-uniform scale");
106 rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
108 qmlInfo(q) << QSGParentChange::tr("Unable to preserve appearance under scale of 0");
113 const QPointF &point = transform.map(QPointF(target->x(),target->y()));
117 // setParentItem will update the transformOriginPoint if needed
118 target->setParentItem(targetParent);
120 if (ok && target->transformOrigin() != QSGItem::TopLeft) {
121 qreal tempxt = target->transformOriginPoint().x();
122 qreal tempyt = target->transformOriginPoint().y();
124 t.translate(-tempxt, -tempyt);
126 t.scale(scale, scale);
127 t.translate(tempxt, tempyt);
128 const QPointF &offset = t.map(QPointF(0,0));
134 //qDebug() << x << y << rotation << scale;
137 target->setRotation(target->rotation() + rotation);
138 target->setScale(target->scale() * scale);
141 target->setParentItem(targetParent);
144 //restore the original stack position.
145 //### if stackBefore has also been reparented this won't work
147 target->stackBefore(stackBefore);
150 QSGParentChange::QSGParentChange(QObject *parent)
151 : QDeclarativeStateOperation(*(new QSGParentChangePrivate), parent)
155 QSGParentChange::~QSGParentChange()
159 QDeclarativeScriptString QSGParentChange::x() const
161 Q_D(const QSGParentChange);
162 return d->xString.value;
165 void QSGParentChange::setX(QDeclarativeScriptString x)
167 Q_D(QSGParentChange);
171 bool QSGParentChange::xIsSet() const
173 Q_D(const QSGParentChange);
174 return d->xString.isValid();
177 QDeclarativeScriptString QSGParentChange::y() const
179 Q_D(const QSGParentChange);
180 return d->yString.value;
183 void QSGParentChange::setY(QDeclarativeScriptString y)
185 Q_D(QSGParentChange);
189 bool QSGParentChange::yIsSet() const
191 Q_D(const QSGParentChange);
192 return d->yString.isValid();
195 QDeclarativeScriptString QSGParentChange::width() const
197 Q_D(const QSGParentChange);
198 return d->widthString.value;
201 void QSGParentChange::setWidth(QDeclarativeScriptString width)
203 Q_D(QSGParentChange);
204 d->widthString = width;
207 bool QSGParentChange::widthIsSet() const
209 Q_D(const QSGParentChange);
210 return d->widthString.isValid();
213 QDeclarativeScriptString QSGParentChange::height() const
215 Q_D(const QSGParentChange);
216 return d->heightString.value;
219 void QSGParentChange::setHeight(QDeclarativeScriptString height)
221 Q_D(QSGParentChange);
222 d->heightString = height;
225 bool QSGParentChange::heightIsSet() const
227 Q_D(const QSGParentChange);
228 return d->heightString.isValid();
231 QDeclarativeScriptString QSGParentChange::scale() const
233 Q_D(const QSGParentChange);
234 return d->scaleString.value;
237 void QSGParentChange::setScale(QDeclarativeScriptString scale)
239 Q_D(QSGParentChange);
240 d->scaleString = scale;
243 bool QSGParentChange::scaleIsSet() const
245 Q_D(const QSGParentChange);
246 return d->scaleString.isValid();
249 QDeclarativeScriptString QSGParentChange::rotation() const
251 Q_D(const QSGParentChange);
252 return d->rotationString.value;
255 void QSGParentChange::setRotation(QDeclarativeScriptString rotation)
257 Q_D(QSGParentChange);
258 d->rotationString = rotation;
261 bool QSGParentChange::rotationIsSet() const
263 Q_D(const QSGParentChange);
264 return d->rotationString.isValid();
267 QSGItem *QSGParentChange::originalParent() const
269 Q_D(const QSGParentChange);
270 return d->origParent;
273 QSGItem *QSGParentChange::object() const
275 Q_D(const QSGParentChange);
279 void QSGParentChange::setObject(QSGItem *target)
281 Q_D(QSGParentChange);
285 QSGItem *QSGParentChange::parent() const
287 Q_D(const QSGParentChange);
291 void QSGParentChange::setParent(QSGItem *parent)
293 Q_D(QSGParentChange);
297 QDeclarativeStateOperation::ActionList QSGParentChange::actions()
299 Q_D(QSGParentChange);
300 if (!d->target || !d->parent)
305 QDeclarativeAction a;
309 if (d->xString.isValid()) {
311 QString script = d->xString.value.script();
312 qreal x = script.toFloat(&ok);
314 QDeclarativeAction xa(d->target, QLatin1String("x"), x);
317 QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this));
318 newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("x")));
319 QDeclarativeAction xa;
320 xa.property = newBinding->property();
321 xa.toBinding = newBinding;
322 xa.fromValue = xa.property.read();
323 xa.deletableToBinding = true;
328 if (d->yString.isValid()) {
330 QString script = d->yString.value.script();
331 qreal y = script.toFloat(&ok);
333 QDeclarativeAction ya(d->target, QLatin1String("y"), y);
336 QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this));
337 newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("y")));
338 QDeclarativeAction ya;
339 ya.property = newBinding->property();
340 ya.toBinding = newBinding;
341 ya.fromValue = ya.property.read();
342 ya.deletableToBinding = true;
347 if (d->scaleString.isValid()) {
349 QString script = d->scaleString.value.script();
350 qreal scale = script.toFloat(&ok);
352 QDeclarativeAction sa(d->target, QLatin1String("scale"), scale);
355 QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this));
356 newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("scale")));
357 QDeclarativeAction sa;
358 sa.property = newBinding->property();
359 sa.toBinding = newBinding;
360 sa.fromValue = sa.property.read();
361 sa.deletableToBinding = true;
366 if (d->rotationString.isValid()) {
368 QString script = d->rotationString.value.script();
369 qreal rotation = script.toFloat(&ok);
371 QDeclarativeAction ra(d->target, QLatin1String("rotation"), rotation);
374 QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this));
375 newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("rotation")));
376 QDeclarativeAction ra;
377 ra.property = newBinding->property();
378 ra.toBinding = newBinding;
379 ra.fromValue = ra.property.read();
380 ra.deletableToBinding = true;
385 if (d->widthString.isValid()) {
387 QString script = d->widthString.value.script();
388 qreal width = script.toFloat(&ok);
390 QDeclarativeAction wa(d->target, QLatin1String("width"), width);
393 QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this));
394 newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("width")));
395 QDeclarativeAction wa;
396 wa.property = newBinding->property();
397 wa.toBinding = newBinding;
398 wa.fromValue = wa.property.read();
399 wa.deletableToBinding = true;
404 if (d->heightString.isValid()) {
406 QString script = d->heightString.value.script();
407 qreal height = script.toFloat(&ok);
409 QDeclarativeAction ha(d->target, QLatin1String("height"), height);
412 QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this));
413 newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("height")));
414 QDeclarativeAction ha;
415 ha.property = newBinding->property();
416 ha.toBinding = newBinding;
417 ha.fromValue = ha.property.read();
418 ha.deletableToBinding = true;
426 void QSGParentChange::saveOriginals()
428 Q_D(QSGParentChange);
430 d->origParent = d->rewindParent;
431 d->origStackBefore = d->rewindStackBefore;
434 /*void QSGParentChange::copyOriginals(QDeclarativeActionEvent *other)
436 Q_D(QSGParentChange);
437 QSGParentChange *pc = static_cast<QSGParentChange*>(other);
439 d->origParent = pc->d_func()->rewindParent;
440 d->origStackBefore = pc->d_func()->rewindStackBefore;
445 void QSGParentChange::execute(Reason)
447 Q_D(QSGParentChange);
448 d->doChange(d->parent);
451 bool QSGParentChange::isReversable()
456 void QSGParentChange::reverse(Reason)
458 Q_D(QSGParentChange);
459 d->doChange(d->origParent, d->origStackBefore);
462 QString QSGParentChange::typeName() const
464 return QLatin1String("ParentChange");
467 bool QSGParentChange::override(QDeclarativeActionEvent*other)
469 Q_D(QSGParentChange);
470 if (other->typeName() != QLatin1String("ParentChange"))
472 if (QSGParentChange *otherPC = static_cast<QSGParentChange*>(other))
473 return (d->target == otherPC->object());
477 void QSGParentChange::saveCurrentValues()
479 Q_D(QSGParentChange);
482 d->rewindStackBefore = 0;
486 d->rewindParent = d->target->parentItem();
487 d->rewindStackBefore = 0;
489 if (!d->rewindParent)
492 QList<QSGItem *> children = d->rewindParent->childItems();
493 for (int ii = 0; ii < children.count() - 1; ++ii) {
494 if (children.at(ii) == d->target) {
495 d->rewindStackBefore = children.at(ii + 1);
501 void QSGParentChange::rewind()
503 Q_D(QSGParentChange);
504 d->doChange(d->rewindParent, d->rewindStackBefore);
507 class QSGAnchorSetPrivate : public QObjectPrivate
509 Q_DECLARE_PUBLIC(QSGAnchorSet)
511 QSGAnchorSetPrivate()
512 : usedAnchors(0), resetAnchors(0), fill(0),
513 centerIn(0)/*, leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
514 margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)*/
518 QSGAnchors::Anchors usedAnchors;
519 QSGAnchors::Anchors resetAnchors;
524 QDeclarativeScriptString leftScript;
525 QDeclarativeScriptString rightScript;
526 QDeclarativeScriptString topScript;
527 QDeclarativeScriptString bottomScript;
528 QDeclarativeScriptString hCenterScript;
529 QDeclarativeScriptString vCenterScript;
530 QDeclarativeScriptString baselineScript;
539 qreal baselineOffset;*/
542 QSGAnchorSet::QSGAnchorSet(QObject *parent)
543 : QObject(*new QSGAnchorSetPrivate, parent)
547 QSGAnchorSet::~QSGAnchorSet()
551 QDeclarativeScriptString QSGAnchorSet::top() const
553 Q_D(const QSGAnchorSet);
557 void QSGAnchorSet::setTop(const QDeclarativeScriptString &edge)
560 d->usedAnchors |= QSGAnchors::TopAnchor;
562 if (edge.script() == QLatin1String("undefined"))
566 void QSGAnchorSet::resetTop()
569 d->usedAnchors &= ~QSGAnchors::TopAnchor;
570 d->topScript = QDeclarativeScriptString();
571 d->resetAnchors |= QSGAnchors::TopAnchor;
574 QDeclarativeScriptString QSGAnchorSet::bottom() const
576 Q_D(const QSGAnchorSet);
577 return d->bottomScript;
580 void QSGAnchorSet::setBottom(const QDeclarativeScriptString &edge)
583 d->usedAnchors |= QSGAnchors::BottomAnchor;
584 d->bottomScript = edge;
585 if (edge.script() == QLatin1String("undefined"))
589 void QSGAnchorSet::resetBottom()
592 d->usedAnchors &= ~QSGAnchors::BottomAnchor;
593 d->bottomScript = QDeclarativeScriptString();
594 d->resetAnchors |= QSGAnchors::BottomAnchor;
597 QDeclarativeScriptString QSGAnchorSet::verticalCenter() const
599 Q_D(const QSGAnchorSet);
600 return d->vCenterScript;
603 void QSGAnchorSet::setVerticalCenter(const QDeclarativeScriptString &edge)
606 d->usedAnchors |= QSGAnchors::VCenterAnchor;
607 d->vCenterScript = edge;
608 if (edge.script() == QLatin1String("undefined"))
609 resetVerticalCenter();
612 void QSGAnchorSet::resetVerticalCenter()
615 d->usedAnchors &= ~QSGAnchors::VCenterAnchor;
616 d->vCenterScript = QDeclarativeScriptString();
617 d->resetAnchors |= QSGAnchors::VCenterAnchor;
620 QDeclarativeScriptString QSGAnchorSet::baseline() const
622 Q_D(const QSGAnchorSet);
623 return d->baselineScript;
626 void QSGAnchorSet::setBaseline(const QDeclarativeScriptString &edge)
629 d->usedAnchors |= QSGAnchors::BaselineAnchor;
630 d->baselineScript = edge;
631 if (edge.script() == QLatin1String("undefined"))
635 void QSGAnchorSet::resetBaseline()
638 d->usedAnchors &= ~QSGAnchors::BaselineAnchor;
639 d->baselineScript = QDeclarativeScriptString();
640 d->resetAnchors |= QSGAnchors::BaselineAnchor;
643 QDeclarativeScriptString QSGAnchorSet::left() const
645 Q_D(const QSGAnchorSet);
646 return d->leftScript;
649 void QSGAnchorSet::setLeft(const QDeclarativeScriptString &edge)
652 d->usedAnchors |= QSGAnchors::LeftAnchor;
653 d->leftScript = edge;
654 if (edge.script() == QLatin1String("undefined"))
658 void QSGAnchorSet::resetLeft()
661 d->usedAnchors &= ~QSGAnchors::LeftAnchor;
662 d->leftScript = QDeclarativeScriptString();
663 d->resetAnchors |= QSGAnchors::LeftAnchor;
666 QDeclarativeScriptString QSGAnchorSet::right() const
668 Q_D(const QSGAnchorSet);
669 return d->rightScript;
672 void QSGAnchorSet::setRight(const QDeclarativeScriptString &edge)
675 d->usedAnchors |= QSGAnchors::RightAnchor;
676 d->rightScript = edge;
677 if (edge.script() == QLatin1String("undefined"))
681 void QSGAnchorSet::resetRight()
684 d->usedAnchors &= ~QSGAnchors::RightAnchor;
685 d->rightScript = QDeclarativeScriptString();
686 d->resetAnchors |= QSGAnchors::RightAnchor;
689 QDeclarativeScriptString QSGAnchorSet::horizontalCenter() const
691 Q_D(const QSGAnchorSet);
692 return d->hCenterScript;
695 void QSGAnchorSet::setHorizontalCenter(const QDeclarativeScriptString &edge)
698 d->usedAnchors |= QSGAnchors::HCenterAnchor;
699 d->hCenterScript = edge;
700 if (edge.script() == QLatin1String("undefined"))
701 resetHorizontalCenter();
704 void QSGAnchorSet::resetHorizontalCenter()
707 d->usedAnchors &= ~QSGAnchors::HCenterAnchor;
708 d->hCenterScript = QDeclarativeScriptString();
709 d->resetAnchors |= QSGAnchors::HCenterAnchor;
712 QSGItem *QSGAnchorSet::fill() const
714 Q_D(const QSGAnchorSet);
718 void QSGAnchorSet::setFill(QSGItem *f)
724 void QSGAnchorSet::resetFill()
729 QSGItem *QSGAnchorSet::centerIn() const
731 Q_D(const QSGAnchorSet);
735 void QSGAnchorSet::setCenterIn(QSGItem* c)
741 void QSGAnchorSet::resetCenterIn()
747 class QSGAnchorChangesPrivate : public QDeclarativeStateOperationPrivate
750 QSGAnchorChangesPrivate()
751 : target(0), anchorSet(new QSGAnchorSet),
752 leftBinding(0), rightBinding(0), hCenterBinding(0),
753 topBinding(0), bottomBinding(0), vCenterBinding(0), baselineBinding(0),
754 origLeftBinding(0), origRightBinding(0), origHCenterBinding(0),
755 origTopBinding(0), origBottomBinding(0), origVCenterBinding(0),
756 origBaselineBinding(0)
760 ~QSGAnchorChangesPrivate() { delete anchorSet; }
763 QSGAnchorSet *anchorSet;
765 QDeclarativeBinding *leftBinding;
766 QDeclarativeBinding *rightBinding;
767 QDeclarativeBinding *hCenterBinding;
768 QDeclarativeBinding *topBinding;
769 QDeclarativeBinding *bottomBinding;
770 QDeclarativeBinding *vCenterBinding;
771 QDeclarativeBinding *baselineBinding;
773 QDeclarativeAbstractBinding *origLeftBinding;
774 QDeclarativeAbstractBinding *origRightBinding;
775 QDeclarativeAbstractBinding *origHCenterBinding;
776 QDeclarativeAbstractBinding *origTopBinding;
777 QDeclarativeAbstractBinding *origBottomBinding;
778 QDeclarativeAbstractBinding *origVCenterBinding;
779 QDeclarativeAbstractBinding *origBaselineBinding;
781 QSGAnchorLine rewindLeft;
782 QSGAnchorLine rewindRight;
783 QSGAnchorLine rewindHCenter;
784 QSGAnchorLine rewindTop;
785 QSGAnchorLine rewindBottom;
786 QSGAnchorLine rewindVCenter;
787 QSGAnchorLine rewindBaseline;
806 bool applyOrigHCenter;
808 bool applyOrigBottom;
809 bool applyOrigVCenter;
810 bool applyOrigBaseline;
812 QDeclarativeNullableValue<qreal> origWidth;
813 QDeclarativeNullableValue<qreal> origHeight;
817 QList<QDeclarativeAbstractBinding*> oldBindings;
819 QDeclarativeProperty leftProp;
820 QDeclarativeProperty rightProp;
821 QDeclarativeProperty hCenterProp;
822 QDeclarativeProperty topProp;
823 QDeclarativeProperty bottomProp;
824 QDeclarativeProperty vCenterProp;
825 QDeclarativeProperty baselineProp;
828 QSGAnchorChanges::QSGAnchorChanges(QObject *parent)
829 : QDeclarativeStateOperation(*(new QSGAnchorChangesPrivate), parent)
833 QSGAnchorChanges::~QSGAnchorChanges()
837 QSGAnchorChanges::ActionList QSGAnchorChanges::actions()
839 Q_D(QSGAnchorChanges);
840 d->leftBinding = d->rightBinding = d->hCenterBinding = d->topBinding
841 = d->bottomBinding = d->vCenterBinding = d->baselineBinding = 0;
843 d->leftProp = QDeclarativeProperty(d->target, QLatin1String("anchors.left"));
844 d->rightProp = QDeclarativeProperty(d->target, QLatin1String("anchors.right"));
845 d->hCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.horizontalCenter"));
846 d->topProp = QDeclarativeProperty(d->target, QLatin1String("anchors.top"));
847 d->bottomProp = QDeclarativeProperty(d->target, QLatin1String("anchors.bottom"));
848 d->vCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.verticalCenter"));
849 d->baselineProp = QDeclarativeProperty(d->target, QLatin1String("anchors.baseline"));
851 if (d->anchorSet->d_func()->usedAnchors & QSGAnchors::LeftAnchor) {
852 d->leftBinding = new QDeclarativeBinding(d->anchorSet->d_func()->leftScript.script(), d->target, qmlContext(this));
853 d->leftBinding->setTarget(d->leftProp);
855 if (d->anchorSet->d_func()->usedAnchors & QSGAnchors::RightAnchor) {
856 d->rightBinding = new QDeclarativeBinding(d->anchorSet->d_func()->rightScript.script(), d->target, qmlContext(this));
857 d->rightBinding->setTarget(d->rightProp);
859 if (d->anchorSet->d_func()->usedAnchors & QSGAnchors::HCenterAnchor) {
860 d->hCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, qmlContext(this));
861 d->hCenterBinding->setTarget(d->hCenterProp);
863 if (d->anchorSet->d_func()->usedAnchors & QSGAnchors::TopAnchor) {
864 d->topBinding = new QDeclarativeBinding(d->anchorSet->d_func()->topScript.script(), d->target, qmlContext(this));
865 d->topBinding->setTarget(d->topProp);
867 if (d->anchorSet->d_func()->usedAnchors & QSGAnchors::BottomAnchor) {
868 d->bottomBinding = new QDeclarativeBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, qmlContext(this));
869 d->bottomBinding->setTarget(d->bottomProp);
871 if (d->anchorSet->d_func()->usedAnchors & QSGAnchors::VCenterAnchor) {
872 d->vCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, qmlContext(this));
873 d->vCenterBinding->setTarget(d->vCenterProp);
875 if (d->anchorSet->d_func()->usedAnchors & QSGAnchors::BaselineAnchor) {
876 d->baselineBinding = new QDeclarativeBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, qmlContext(this));
877 d->baselineBinding->setTarget(d->baselineProp);
880 QDeclarativeAction a;
882 return ActionList() << a;
885 QSGAnchorSet *QSGAnchorChanges::anchors()
887 Q_D(QSGAnchorChanges);
891 QSGItem *QSGAnchorChanges::object() const
893 Q_D(const QSGAnchorChanges);
897 void QSGAnchorChanges::setObject(QSGItem *target)
899 Q_D(QSGAnchorChanges);
903 void QSGAnchorChanges::execute(Reason reason)
905 Q_D(QSGAnchorChanges);
909 QSGItemPrivate *targetPrivate = QSGItemPrivate::get(d->target);
910 //incorporate any needed "reverts"
911 if (d->applyOrigLeft) {
912 if (!d->origLeftBinding)
913 targetPrivate->anchors()->resetLeft();
914 QDeclarativePropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
916 if (d->applyOrigRight) {
917 if (!d->origRightBinding)
918 targetPrivate->anchors()->resetRight();
919 QDeclarativePropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
921 if (d->applyOrigHCenter) {
922 if (!d->origHCenterBinding)
923 targetPrivate->anchors()->resetHorizontalCenter();
924 QDeclarativePropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
926 if (d->applyOrigTop) {
927 if (!d->origTopBinding)
928 targetPrivate->anchors()->resetTop();
929 QDeclarativePropertyPrivate::setBinding(d->topProp, d->origTopBinding);
931 if (d->applyOrigBottom) {
932 if (!d->origBottomBinding)
933 targetPrivate->anchors()->resetBottom();
934 QDeclarativePropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
936 if (d->applyOrigVCenter) {
937 if (!d->origVCenterBinding)
938 targetPrivate->anchors()->resetVerticalCenter();
939 QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
941 if (d->applyOrigBaseline) {
942 if (!d->origBaselineBinding)
943 targetPrivate->anchors()->resetBaseline();
944 QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
947 //destroy old bindings
948 if (reason == ActualChange) {
949 for (int i = 0; i < d->oldBindings.size(); ++i) {
950 QDeclarativeAbstractBinding *binding = d->oldBindings.at(i);
954 d->oldBindings.clear();
957 //reset any anchors that have been specified as "undefined"
958 if (d->anchorSet->d_func()->resetAnchors & QSGAnchors::LeftAnchor) {
959 targetPrivate->anchors()->resetLeft();
960 QDeclarativePropertyPrivate::setBinding(d->leftProp, 0);
962 if (d->anchorSet->d_func()->resetAnchors & QSGAnchors::RightAnchor) {
963 targetPrivate->anchors()->resetRight();
964 QDeclarativePropertyPrivate::setBinding(d->rightProp, 0);
966 if (d->anchorSet->d_func()->resetAnchors & QSGAnchors::HCenterAnchor) {
967 targetPrivate->anchors()->resetHorizontalCenter();
968 QDeclarativePropertyPrivate::setBinding(d->hCenterProp, 0);
970 if (d->anchorSet->d_func()->resetAnchors & QSGAnchors::TopAnchor) {
971 targetPrivate->anchors()->resetTop();
972 QDeclarativePropertyPrivate::setBinding(d->topProp, 0);
974 if (d->anchorSet->d_func()->resetAnchors & QSGAnchors::BottomAnchor) {
975 targetPrivate->anchors()->resetBottom();
976 QDeclarativePropertyPrivate::setBinding(d->bottomProp, 0);
978 if (d->anchorSet->d_func()->resetAnchors & QSGAnchors::VCenterAnchor) {
979 targetPrivate->anchors()->resetVerticalCenter();
980 QDeclarativePropertyPrivate::setBinding(d->vCenterProp, 0);
982 if (d->anchorSet->d_func()->resetAnchors & QSGAnchors::BaselineAnchor) {
983 targetPrivate->anchors()->resetBaseline();
984 QDeclarativePropertyPrivate::setBinding(d->baselineProp, 0);
987 //set any anchors that have been specified
989 QDeclarativePropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding);
991 QDeclarativePropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding);
992 if (d->hCenterBinding)
993 QDeclarativePropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding);
995 QDeclarativePropertyPrivate::setBinding(d->topBinding->property(), d->topBinding);
996 if (d->bottomBinding)
997 QDeclarativePropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding);
998 if (d->vCenterBinding)
999 QDeclarativePropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding);
1000 if (d->baselineBinding)
1001 QDeclarativePropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding);
1004 bool QSGAnchorChanges::isReversable()
1009 void QSGAnchorChanges::reverse(Reason reason)
1011 Q_D(QSGAnchorChanges);
1015 QSGItemPrivate *targetPrivate = QSGItemPrivate::get(d->target);
1016 //reset any anchors set by the state
1017 if (d->leftBinding) {
1018 targetPrivate->anchors()->resetLeft();
1019 QDeclarativePropertyPrivate::setBinding(d->leftBinding->property(), 0);
1020 if (reason == ActualChange) {
1021 d->leftBinding->destroy(); d->leftBinding = 0;
1024 if (d->rightBinding) {
1025 targetPrivate->anchors()->resetRight();
1026 QDeclarativePropertyPrivate::setBinding(d->rightBinding->property(), 0);
1027 if (reason == ActualChange) {
1028 d->rightBinding->destroy(); d->rightBinding = 0;
1031 if (d->hCenterBinding) {
1032 targetPrivate->anchors()->resetHorizontalCenter();
1033 QDeclarativePropertyPrivate::setBinding(d->hCenterBinding->property(), 0);
1034 if (reason == ActualChange) {
1035 d->hCenterBinding->destroy(); d->hCenterBinding = 0;
1038 if (d->topBinding) {
1039 targetPrivate->anchors()->resetTop();
1040 QDeclarativePropertyPrivate::setBinding(d->topBinding->property(), 0);
1041 if (reason == ActualChange) {
1042 d->topBinding->destroy(); d->topBinding = 0;
1045 if (d->bottomBinding) {
1046 targetPrivate->anchors()->resetBottom();
1047 QDeclarativePropertyPrivate::setBinding(d->bottomBinding->property(), 0);
1048 if (reason == ActualChange) {
1049 d->bottomBinding->destroy(); d->bottomBinding = 0;
1052 if (d->vCenterBinding) {
1053 targetPrivate->anchors()->resetVerticalCenter();
1054 QDeclarativePropertyPrivate::setBinding(d->vCenterBinding->property(), 0);
1055 if (reason == ActualChange) {
1056 d->vCenterBinding->destroy(); d->vCenterBinding = 0;
1059 if (d->baselineBinding) {
1060 targetPrivate->anchors()->resetBaseline();
1061 QDeclarativePropertyPrivate::setBinding(d->baselineBinding->property(), 0);
1062 if (reason == ActualChange) {
1063 d->baselineBinding->destroy(); d->baselineBinding = 0;
1067 //restore previous anchors
1068 if (d->origLeftBinding)
1069 QDeclarativePropertyPrivate::setBinding(d->leftProp, d->origLeftBinding);
1070 if (d->origRightBinding)
1071 QDeclarativePropertyPrivate::setBinding(d->rightProp, d->origRightBinding);
1072 if (d->origHCenterBinding)
1073 QDeclarativePropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding);
1074 if (d->origTopBinding)
1075 QDeclarativePropertyPrivate::setBinding(d->topProp, d->origTopBinding);
1076 if (d->origBottomBinding)
1077 QDeclarativePropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding);
1078 if (d->origVCenterBinding)
1079 QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding);
1080 if (d->origBaselineBinding)
1081 QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding);
1083 //restore any absolute geometry changed by the state's anchors
1084 QSGAnchors::Anchors stateVAnchors = d->anchorSet->d_func()->usedAnchors & QSGAnchors::Vertical_Mask;
1085 QSGAnchors::Anchors origVAnchors = targetPrivate->anchors()->usedAnchors() & QSGAnchors::Vertical_Mask;
1086 QSGAnchors::Anchors stateHAnchors = d->anchorSet->d_func()->usedAnchors & QSGAnchors::Horizontal_Mask;
1087 QSGAnchors::Anchors origHAnchors = targetPrivate->anchors()->usedAnchors() & QSGAnchors::Horizontal_Mask;
1089 bool stateSetWidth = (stateHAnchors &&
1090 stateHAnchors != QSGAnchors::LeftAnchor &&
1091 stateHAnchors != QSGAnchors::RightAnchor &&
1092 stateHAnchors != QSGAnchors::HCenterAnchor);
1093 bool origSetWidth = (origHAnchors &&
1094 origHAnchors != QSGAnchors::LeftAnchor &&
1095 origHAnchors != QSGAnchors::RightAnchor &&
1096 origHAnchors != QSGAnchors::HCenterAnchor);
1097 if (d->origWidth.isValid() && stateSetWidth && !origSetWidth)
1098 d->target->setWidth(d->origWidth.value);
1100 bool stateSetHeight = (stateVAnchors &&
1101 stateVAnchors != QSGAnchors::TopAnchor &&
1102 stateVAnchors != QSGAnchors::BottomAnchor &&
1103 stateVAnchors != QSGAnchors::VCenterAnchor &&
1104 stateVAnchors != QSGAnchors::BaselineAnchor);
1105 bool origSetHeight = (origVAnchors &&
1106 origVAnchors != QSGAnchors::TopAnchor &&
1107 origVAnchors != QSGAnchors::BottomAnchor &&
1108 origVAnchors != QSGAnchors::VCenterAnchor &&
1109 origVAnchors != QSGAnchors::BaselineAnchor);
1110 if (d->origHeight.isValid() && stateSetHeight && !origSetHeight)
1111 d->target->setHeight(d->origHeight.value);
1113 if (stateHAnchors && !origHAnchors)
1114 d->target->setX(d->origX);
1116 if (stateVAnchors && !origVAnchors)
1117 d->target->setY(d->origY);
1120 QString QSGAnchorChanges::typeName() const
1122 return QLatin1String("AnchorChanges");
1125 QList<QDeclarativeAction> QSGAnchorChanges::additionalActions()
1127 Q_D(QSGAnchorChanges);
1128 QList<QDeclarativeAction> extra;
1130 QSGAnchors::Anchors combined = d->anchorSet->d_func()->usedAnchors | d->anchorSet->d_func()->resetAnchors;
1131 bool hChange = combined & QSGAnchors::Horizontal_Mask;
1132 bool vChange = combined & QSGAnchors::Vertical_Mask;
1135 QDeclarativeAction a;
1136 if (hChange && d->fromX != d->toX) {
1137 a.property = QDeclarativeProperty(d->target, QLatin1String("x"));
1141 if (vChange && d->fromY != d->toY) {
1142 a.property = QDeclarativeProperty(d->target, QLatin1String("y"));
1146 if (hChange && d->fromWidth != d->toWidth) {
1147 a.property = QDeclarativeProperty(d->target, QLatin1String("width"));
1148 a.toValue = d->toWidth;
1151 if (vChange && d->fromHeight != d->toHeight) {
1152 a.property = QDeclarativeProperty(d->target, QLatin1String("height"));
1153 a.toValue = d->toHeight;
1161 bool QSGAnchorChanges::changesBindings()
1166 void QSGAnchorChanges::saveOriginals()
1168 Q_D(QSGAnchorChanges);
1172 d->origLeftBinding = QDeclarativePropertyPrivate::binding(d->leftProp);
1173 d->origRightBinding = QDeclarativePropertyPrivate::binding(d->rightProp);
1174 d->origHCenterBinding = QDeclarativePropertyPrivate::binding(d->hCenterProp);
1175 d->origTopBinding = QDeclarativePropertyPrivate::binding(d->topProp);
1176 d->origBottomBinding = QDeclarativePropertyPrivate::binding(d->bottomProp);
1177 d->origVCenterBinding = QDeclarativePropertyPrivate::binding(d->vCenterProp);
1178 d->origBaselineBinding = QDeclarativePropertyPrivate::binding(d->baselineProp);
1180 QSGItemPrivate *targetPrivate = QSGItemPrivate::get(d->target);
1181 if (targetPrivate->widthValid)
1182 d->origWidth = d->target->width();
1183 if (targetPrivate->heightValid)
1184 d->origHeight = d->target->height();
1185 d->origX = d->target->x();
1186 d->origY = d->target->y();
1188 d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop
1189 = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false;
1191 saveCurrentValues();
1194 void QSGAnchorChanges::copyOriginals(QDeclarativeActionEvent *other)
1196 Q_D(QSGAnchorChanges);
1197 QSGAnchorChanges *ac = static_cast<QSGAnchorChanges*>(other);
1198 QSGAnchorChangesPrivate *acp = ac->d_func();
1200 QSGAnchors::Anchors combined = acp->anchorSet->d_func()->usedAnchors |
1201 acp->anchorSet->d_func()->resetAnchors;
1203 //probably also need to revert some things
1204 d->applyOrigLeft = (combined & QSGAnchors::LeftAnchor);
1205 d->applyOrigRight = (combined & QSGAnchors::RightAnchor);
1206 d->applyOrigHCenter = (combined & QSGAnchors::HCenterAnchor);
1207 d->applyOrigTop = (combined & QSGAnchors::TopAnchor);
1208 d->applyOrigBottom = (combined & QSGAnchors::BottomAnchor);
1209 d->applyOrigVCenter = (combined & QSGAnchors::VCenterAnchor);
1210 d->applyOrigBaseline = (combined & QSGAnchors::BaselineAnchor);
1212 d->origLeftBinding = acp->origLeftBinding;
1213 d->origRightBinding = acp->origRightBinding;
1214 d->origHCenterBinding = acp->origHCenterBinding;
1215 d->origTopBinding = acp->origTopBinding;
1216 d->origBottomBinding = acp->origBottomBinding;
1217 d->origVCenterBinding = acp->origVCenterBinding;
1218 d->origBaselineBinding = acp->origBaselineBinding;
1220 d->origWidth = acp->origWidth;
1221 d->origHeight = acp->origHeight;
1222 d->origX = acp->origX;
1223 d->origY = acp->origY;
1225 d->oldBindings.clear();
1226 d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding
1227 << acp->topBinding << acp->bottomBinding << acp->baselineBinding;
1229 saveCurrentValues();
1232 void QSGAnchorChanges::clearBindings()
1234 Q_D(QSGAnchorChanges);
1238 //### should this (saving "from" values) be moved to saveCurrentValues()?
1239 d->fromX = d->target->x();
1240 d->fromY = d->target->y();
1241 d->fromWidth = d->target->width();
1242 d->fromHeight = d->target->height();
1244 QSGItemPrivate *targetPrivate = QSGItemPrivate::get(d->target);
1245 //reset any anchors with corresponding reverts
1246 //reset any anchors that have been specified as "undefined"
1247 //reset any anchors that we'll be setting in the state
1248 QSGAnchors::Anchors combined = d->anchorSet->d_func()->resetAnchors |
1249 d->anchorSet->d_func()->usedAnchors;
1250 if (d->applyOrigLeft || (combined & QSGAnchors::LeftAnchor)) {
1251 targetPrivate->anchors()->resetLeft();
1252 QDeclarativePropertyPrivate::setBinding(d->leftProp, 0);
1254 if (d->applyOrigRight || (combined & QSGAnchors::RightAnchor)) {
1255 targetPrivate->anchors()->resetRight();
1256 QDeclarativePropertyPrivate::setBinding(d->rightProp, 0);
1258 if (d->applyOrigHCenter || (combined & QSGAnchors::HCenterAnchor)) {
1259 targetPrivate->anchors()->resetHorizontalCenter();
1260 QDeclarativePropertyPrivate::setBinding(d->hCenterProp, 0);
1262 if (d->applyOrigTop || (combined & QSGAnchors::TopAnchor)) {
1263 targetPrivate->anchors()->resetTop();
1264 QDeclarativePropertyPrivate::setBinding(d->topProp, 0);
1266 if (d->applyOrigBottom || (combined & QSGAnchors::BottomAnchor)) {
1267 targetPrivate->anchors()->resetBottom();
1268 QDeclarativePropertyPrivate::setBinding(d->bottomProp, 0);
1270 if (d->applyOrigVCenter || (combined & QSGAnchors::VCenterAnchor)) {
1271 targetPrivate->anchors()->resetVerticalCenter();
1272 QDeclarativePropertyPrivate::setBinding(d->vCenterProp, 0);
1274 if (d->applyOrigBaseline || (combined & QSGAnchors::BaselineAnchor)) {
1275 targetPrivate->anchors()->resetBaseline();
1276 QDeclarativePropertyPrivate::setBinding(d->baselineProp, 0);
1280 bool QSGAnchorChanges::override(QDeclarativeActionEvent*other)
1282 if (other->typeName() != QLatin1String("AnchorChanges"))
1284 if (static_cast<QDeclarativeActionEvent*>(this) == other)
1286 if (static_cast<QSGAnchorChanges*>(other)->object() == object())
1291 void QSGAnchorChanges::rewind()
1293 Q_D(QSGAnchorChanges);
1297 QSGItemPrivate *targetPrivate = QSGItemPrivate::get(d->target);
1299 //restore previous values (but not previous bindings, i.e. anchors)
1300 d->target->setX(d->rewindX);
1301 d->target->setY(d->rewindY);
1302 if (targetPrivate->widthValid) {
1303 d->target->setWidth(d->rewindWidth);
1305 if (targetPrivate->heightValid) {
1306 d->target->setHeight(d->rewindHeight);
1310 void QSGAnchorChanges::saveCurrentValues()
1312 Q_D(QSGAnchorChanges);
1316 QSGItemPrivate *targetPrivate = QSGItemPrivate::get(d->target);
1317 d->rewindLeft = targetPrivate->anchors()->left();
1318 d->rewindRight = targetPrivate->anchors()->right();
1319 d->rewindHCenter = targetPrivate->anchors()->horizontalCenter();
1320 d->rewindTop = targetPrivate->anchors()->top();
1321 d->rewindBottom = targetPrivate->anchors()->bottom();
1322 d->rewindVCenter = targetPrivate->anchors()->verticalCenter();
1323 d->rewindBaseline = targetPrivate->anchors()->baseline();
1325 d->rewindX = d->target->x();
1326 d->rewindY = d->target->y();
1327 d->rewindWidth = d->target->width();
1328 d->rewindHeight = d->target->height();
1331 void QSGAnchorChanges::saveTargetValues()
1333 Q_D(QSGAnchorChanges);
1337 d->toX = d->target->x();
1338 d->toY = d->target->y();
1339 d->toWidth = d->target->width();
1340 d->toHeight = d->target->height();
1343 #include <moc_qsgstateoperations_p.cpp>