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