source: trunk/src/declarative/util/qdeclarativeanimation.cpp@ 986

Last change on this file since 986 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 98.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "private/qdeclarativeanimation_p.h"
43#include "private/qdeclarativeanimation_p_p.h"
44
45#include "private/qdeclarativebehavior_p.h"
46#include "private/qdeclarativestateoperations_p.h"
47#include "private/qdeclarativecontext_p.h"
48
49#include <qdeclarativepropertyvaluesource.h>
50#include <qdeclarative.h>
51#include <qdeclarativeinfo.h>
52#include <qdeclarativeexpression.h>
53#include <qdeclarativestringconverters_p.h>
54#include <qdeclarativeglobal_p.h>
55#include <qdeclarativemetatype_p.h>
56#include <qdeclarativevaluetype_p.h>
57#include <qdeclarativeproperty_p.h>
58#include <qdeclarativeengine_p.h>
59
60#include <qvariant.h>
61#include <qcolor.h>
62#include <qfile.h>
63#include <QParallelAnimationGroup>
64#include <QSequentialAnimationGroup>
65#include <QtCore/qset.h>
66#include <QtCore/qrect.h>
67#include <QtCore/qpoint.h>
68#include <QtCore/qsize.h>
69#include <QtCore/qmath.h>
70
71#include <private/qvariantanimation_p.h>
72
73QT_BEGIN_NAMESPACE
74
75/*!
76 \qmlclass Animation QDeclarativeAbstractAnimation
77 \ingroup qml-animation-transition
78 \since 4.7
79 \brief The Animation element is the base of all QML animations.
80
81 The Animation element cannot be used directly in a QML file. It exists
82 to provide a set of common properties and methods, available across all the
83 other animation types that inherit from it. Attempting to use the Animation
84 element directly will result in an error.
85*/
86
87QDeclarativeAbstractAnimation::QDeclarativeAbstractAnimation(QObject *parent)
88: QObject(*(new QDeclarativeAbstractAnimationPrivate), parent)
89{
90}
91
92QDeclarativeAbstractAnimation::~QDeclarativeAbstractAnimation()
93{
94}
95
96QDeclarativeAbstractAnimation::QDeclarativeAbstractAnimation(QDeclarativeAbstractAnimationPrivate &dd, QObject *parent)
97: QObject(dd, parent)
98{
99}
100
101/*!
102 \qmlproperty bool Animation::running
103 This property holds whether the animation is currently running.
104
105 The \c running property can be set to declaratively control whether or not
106 an animation is running. The following example will animate a rectangle
107 whenever the \l MouseArea is pressed.
108
109 \code
110 Rectangle {
111 width: 100; height: 100
112 NumberAnimation on x {
113 running: myMouse.pressed
114 from: 0; to: 100
115 }
116 MouseArea { id: myMouse }
117 }
118 \endcode
119
120 Likewise, the \c running property can be read to determine if the animation
121 is running. In the following example the text element will indicate whether
122 or not the animation is running.
123
124 \code
125 NumberAnimation { id: myAnimation }
126 Text { text: myAnimation.running ? "Animation is running" : "Animation is not running" }
127 \endcode
128
129 Animations can also be started and stopped imperatively from JavaScript
130 using the \c start() and \c stop() methods.
131
132 By default, animations are not running. Though, when the animations are assigned to properties,
133 as property value sources using the \e on syntax, they are set to running by default.
134*/
135bool QDeclarativeAbstractAnimation::isRunning() const
136{
137 Q_D(const QDeclarativeAbstractAnimation);
138 return d->running;
139}
140
141// the behavior calls this function
142void QDeclarativeAbstractAnimation::notifyRunningChanged(bool running)
143{
144 Q_D(QDeclarativeAbstractAnimation);
145 if (d->disableUserControl && d->running != running) {
146 d->running = running;
147 emit runningChanged(running);
148 }
149}
150
151//commence is called to start an animation when it is used as a
152//simple animation, and not as part of a transition
153void QDeclarativeAbstractAnimationPrivate::commence()
154{
155 Q_Q(QDeclarativeAbstractAnimation);
156
157 QDeclarativeStateActions actions;
158 QDeclarativeProperties properties;
159 q->transition(actions, properties, QDeclarativeAbstractAnimation::Forward);
160
161 q->qtAnimation()->start();
162 if (q->qtAnimation()->state() != QAbstractAnimation::Running) {
163 running = false;
164 emit q->completed();
165 }
166}
167
168QDeclarativeProperty QDeclarativeAbstractAnimationPrivate::createProperty(QObject *obj, const QString &str, QObject *infoObj)
169{
170 QDeclarativeProperty prop(obj, str, qmlContext(infoObj));
171 if (!prop.isValid()) {
172 qmlInfo(infoObj) << QDeclarativeAbstractAnimation::tr("Cannot animate non-existent property \"%1\"").arg(str);
173 return QDeclarativeProperty();
174 } else if (!prop.isWritable()) {
175 qmlInfo(infoObj) << QDeclarativeAbstractAnimation::tr("Cannot animate read-only property \"%1\"").arg(str);
176 return QDeclarativeProperty();
177 }
178 return prop;
179}
180
181void QDeclarativeAbstractAnimation::setRunning(bool r)
182{
183 Q_D(QDeclarativeAbstractAnimation);
184 if (!d->componentComplete) {
185 if (d->running && r == d->running) //don't re-register
186 return;
187 d->running = r;
188 if (r == false)
189 d->avoidPropertyValueSourceStart = true;
190 else {
191 QDeclarativeEnginePrivate *engPriv = QDeclarativeEnginePrivate::get(qmlEngine(this));
192 engPriv->registerFinalizedParserStatusObject(this, this->metaObject()->indexOfSlot("componentFinalized()"));
193 }
194 return;
195 }
196
197 if (d->running == r)
198 return;
199
200 if (d->group || d->disableUserControl) {
201 qmlInfo(this) << "setRunning() cannot be used on non-root animation nodes.";
202 return;
203 }
204
205 d->running = r;
206 if (d->running) {
207 if (d->alwaysRunToEnd && d->loopCount != 1
208 && qtAnimation()->state() == QAbstractAnimation::Running) {
209 //we've restarted before the final loop finished; restore proper loop count
210 if (d->loopCount == -1)
211 qtAnimation()->setLoopCount(d->loopCount);
212 else
213 qtAnimation()->setLoopCount(qtAnimation()->currentLoop() + d->loopCount);
214 }
215
216 if (!d->connectedTimeLine) {
217 QObject::connect(qtAnimation(), SIGNAL(finished()),
218 this, SLOT(timelineComplete()));
219 d->connectedTimeLine = true;
220 }
221 d->commence();
222 emit started();
223 } else {
224 if (d->alwaysRunToEnd) {
225 if (d->loopCount != 1)
226 qtAnimation()->setLoopCount(qtAnimation()->currentLoop()+1); //finish the current loop
227 } else
228 qtAnimation()->stop();
229
230 emit completed();
231 }
232
233 emit runningChanged(d->running);
234}
235
236/*!
237 \qmlproperty bool Animation::paused
238 This property holds whether the animation is currently paused.
239
240 The \c paused property can be set to declaratively control whether or not
241 an animation is paused.
242
243 Animations can also be paused and resumed imperatively from JavaScript
244 using the \c pause() and \c resume() methods.
245
246 By default, animations are not paused.
247*/
248bool QDeclarativeAbstractAnimation::isPaused() const
249{
250 Q_D(const QDeclarativeAbstractAnimation);
251 return d->paused;
252}
253
254void QDeclarativeAbstractAnimation::setPaused(bool p)
255{
256 Q_D(QDeclarativeAbstractAnimation);
257 if (d->paused == p)
258 return;
259
260 if (d->group || d->disableUserControl) {
261 qmlInfo(this) << "setPaused() cannot be used on non-root animation nodes.";
262 return;
263 }
264
265 d->paused = p;
266 if (d->paused)
267 qtAnimation()->pause();
268 else
269 qtAnimation()->resume();
270
271 emit pausedChanged(d->paused);
272}
273
274void QDeclarativeAbstractAnimation::classBegin()
275{
276 Q_D(QDeclarativeAbstractAnimation);
277 d->componentComplete = false;
278}
279
280void QDeclarativeAbstractAnimation::componentComplete()
281{
282 Q_D(QDeclarativeAbstractAnimation);
283 d->componentComplete = true;
284}
285
286void QDeclarativeAbstractAnimation::componentFinalized()
287{
288 Q_D(QDeclarativeAbstractAnimation);
289 if (d->running) {
290 d->running = false;
291 setRunning(true);
292 }
293}
294
295/*!
296 \qmlproperty bool Animation::alwaysRunToEnd
297 This property holds whether the animation should run to completion when it is stopped.
298
299 If this true the animation will complete its current iteration when it
300 is stopped - either by setting the \c running property to false, or by
301 calling the \c stop() method. The \c complete() method is not effected
302 by this value.
303
304 This behavior is most useful when the \c repeat property is set, as the
305 animation will finish playing normally but not restart.
306
307 By default, the alwaysRunToEnd property is not set.
308
309 \note alwaysRunToEnd has no effect on animations in a Transition.
310*/
311bool QDeclarativeAbstractAnimation::alwaysRunToEnd() const
312{
313 Q_D(const QDeclarativeAbstractAnimation);
314 return d->alwaysRunToEnd;
315}
316
317void QDeclarativeAbstractAnimation::setAlwaysRunToEnd(bool f)
318{
319 Q_D(QDeclarativeAbstractAnimation);
320 if (d->alwaysRunToEnd == f)
321 return;
322
323 d->alwaysRunToEnd = f;
324 emit alwaysRunToEndChanged(f);
325}
326
327/*!
328 \qmlproperty int Animation::loops
329 This property holds the number of times the animation should play.
330
331 By default, \c loops is 1: the animation will play through once and then stop.
332
333 If set to Animation.Infinite, the animation will continuously repeat until it is explicitly
334 stopped - either by setting the \c running property to false, or by calling
335 the \c stop() method.
336
337 In the following example, the rectangle will spin indefinitely.
338
339 \code
340 Rectangle {
341 width: 100; height: 100; color: "green"
342 RotationAnimation on rotation {
343 loops: Animation.Infinite
344 from: 0
345 to: 360
346 }
347 }
348 \endcode
349*/
350int QDeclarativeAbstractAnimation::loops() const
351{
352 Q_D(const QDeclarativeAbstractAnimation);
353 return d->loopCount;
354}
355
356void QDeclarativeAbstractAnimation::setLoops(int loops)
357{
358 Q_D(QDeclarativeAbstractAnimation);
359 if (loops < 0)
360 loops = -1;
361
362 if (loops == d->loopCount)
363 return;
364
365 d->loopCount = loops;
366 qtAnimation()->setLoopCount(loops);
367 emit loopCountChanged(loops);
368}
369
370
371int QDeclarativeAbstractAnimation::currentTime()
372{
373 return qtAnimation()->currentLoopTime();
374}
375
376void QDeclarativeAbstractAnimation::setCurrentTime(int time)
377{
378 qtAnimation()->setCurrentTime(time);
379}
380
381QDeclarativeAnimationGroup *QDeclarativeAbstractAnimation::group() const
382{
383 Q_D(const QDeclarativeAbstractAnimation);
384 return d->group;
385}
386
387void QDeclarativeAbstractAnimation::setGroup(QDeclarativeAnimationGroup *g)
388{
389 Q_D(QDeclarativeAbstractAnimation);
390 if (d->group == g)
391 return;
392 if (d->group)
393 static_cast<QDeclarativeAnimationGroupPrivate *>(d->group->d_func())->animations.removeAll(this);
394
395 d->group = g;
396
397 if (d->group && !static_cast<QDeclarativeAnimationGroupPrivate *>(d->group->d_func())->animations.contains(this))
398 static_cast<QDeclarativeAnimationGroupPrivate *>(d->group->d_func())->animations.append(this);
399
400 //if (g) //if removed from a group, then the group should no longer be the parent
401 setParent(g);
402}
403
404/*!
405 \qmlmethod Animation::start()
406 \brief Starts the animation.
407
408 If the animation is already running, calling this method has no effect. The
409 \c running property will be true following a call to \c start().
410*/
411void QDeclarativeAbstractAnimation::start()
412{
413 setRunning(true);
414}
415
416/*!
417 \qmlmethod Animation::pause()
418 \brief Pauses the animation.
419
420 If the animation is already paused, calling this method has no effect. The
421 \c paused property will be true following a call to \c pause().
422*/
423void QDeclarativeAbstractAnimation::pause()
424{
425 setPaused(true);
426}
427
428/*!
429 \qmlmethod Animation::resume()
430 \brief Resumes a paused animation.
431
432 If the animation is not paused, calling this method has no effect. The
433 \c paused property will be false following a call to \c resume().
434*/
435void QDeclarativeAbstractAnimation::resume()
436{
437 setPaused(false);
438}
439
440/*!
441 \qmlmethod Animation::stop()
442 \brief Stops the animation.
443
444 If the animation is not running, calling this method has no effect. The
445 \c running property will be false following a call to \c stop().
446
447 Normally \c stop() stops the animation immediately, and the animation has
448 no further influence on property values. In this example animation
449 \code
450 Rectangle {
451 NumberAnimation on x { from: 0; to: 100; duration: 500 }
452 }
453 \endcode
454 was stopped at time 250ms, the \c x property will have a value of 50.
455
456 However, if the \c alwaysRunToEnd property is set, the animation will
457 continue running until it completes and then stop. The \c running property
458 will still become false immediately.
459*/
460void QDeclarativeAbstractAnimation::stop()
461{
462 setRunning(false);
463}
464
465/*!
466 \qmlmethod Animation::restart()
467 \brief Restarts the animation.
468
469 This is a convenience method, and is equivalent to calling \c stop() and
470 then \c start().
471*/
472void QDeclarativeAbstractAnimation::restart()
473{
474 stop();
475 start();
476}
477
478/*!
479 \qmlmethod Animation::complete()
480 \brief Stops the animation, jumping to the final property values.
481
482 If the animation is not running, calling this method has no effect. The
483 \c running property will be false following a call to \c complete().
484
485 Unlike \c stop(), \c complete() immediately fast-forwards the animation to
486 its end. In the following example,
487 \code
488 Rectangle {
489 NumberAnimation on x { from: 0; to: 100; duration: 500 }
490 }
491 \endcode
492 calling \c stop() at time 250ms will result in the \c x property having
493 a value of 50, while calling \c complete() will set the \c x property to
494 100, exactly as though the animation had played the whole way through.
495*/
496void QDeclarativeAbstractAnimation::complete()
497{
498 if (isRunning()) {
499 qtAnimation()->setCurrentTime(qtAnimation()->duration());
500 }
501}
502
503void QDeclarativeAbstractAnimation::setTarget(const QDeclarativeProperty &p)
504{
505 Q_D(QDeclarativeAbstractAnimation);
506 d->defaultProperty = p;
507
508 if (!d->avoidPropertyValueSourceStart)
509 setRunning(true);
510}
511
512/*
513 we rely on setTarget only being called when used as a value source
514 so this function allows us to do the same thing as setTarget without
515 that assumption
516*/
517void QDeclarativeAbstractAnimation::setDefaultTarget(const QDeclarativeProperty &p)
518{
519 Q_D(QDeclarativeAbstractAnimation);
520 d->defaultProperty = p;
521}
522
523/*
524 don't allow start/stop/pause/resume to be manually invoked,
525 because something else (like a Behavior) already has control
526 over the animation.
527*/
528void QDeclarativeAbstractAnimation::setDisableUserControl()
529{
530 Q_D(QDeclarativeAbstractAnimation);
531 d->disableUserControl = true;
532}
533
534void QDeclarativeAbstractAnimation::transition(QDeclarativeStateActions &actions,
535 QDeclarativeProperties &modified,
536 TransitionDirection direction)
537{
538 Q_UNUSED(actions);
539 Q_UNUSED(modified);
540 Q_UNUSED(direction);
541}
542
543void QDeclarativeAbstractAnimation::timelineComplete()
544{
545 Q_D(QDeclarativeAbstractAnimation);
546 setRunning(false);
547 if (d->alwaysRunToEnd && d->loopCount != 1) {
548 //restore the proper loopCount for the next run
549 qtAnimation()->setLoopCount(d->loopCount);
550 }
551}
552
553/*!
554 \qmlclass PauseAnimation QDeclarativePauseAnimation
555 \ingroup qml-animation-transition
556 \since 4.7
557 \inherits Animation
558 \brief The PauseAnimation element provides a pause for an animation.
559
560 When used in a SequentialAnimation, PauseAnimation is a step when
561 nothing happens, for a specified duration.
562
563 A 500ms animation sequence, with a 100ms pause between two animations:
564 \code
565 SequentialAnimation {
566 NumberAnimation { ... duration: 200 }
567 PauseAnimation { duration: 100 }
568 NumberAnimation { ... duration: 200 }
569 }
570 \endcode
571
572 \sa {QML Animation}, {declarative/animation/basics}{Animation basics example}
573*/
574QDeclarativePauseAnimation::QDeclarativePauseAnimation(QObject *parent)
575: QDeclarativeAbstractAnimation(*(new QDeclarativePauseAnimationPrivate), parent)
576{
577 Q_D(QDeclarativePauseAnimation);
578 d->init();
579}
580
581QDeclarativePauseAnimation::~QDeclarativePauseAnimation()
582{
583}
584
585void QDeclarativePauseAnimationPrivate::init()
586{
587 Q_Q(QDeclarativePauseAnimation);
588 pa = new QPauseAnimation;
589 QDeclarative_setParent_noEvent(pa, q);
590}
591
592/*!
593 \qmlproperty int PauseAnimation::duration
594 This property holds the duration of the pause in milliseconds
595
596 The default value is 250.
597*/
598int QDeclarativePauseAnimation::duration() const
599{
600 Q_D(const QDeclarativePauseAnimation);
601 return d->pa->duration();
602}
603
604void QDeclarativePauseAnimation::setDuration(int duration)
605{
606 if (duration < 0) {
607 qmlInfo(this) << tr("Cannot set a duration of < 0");
608 return;
609 }
610
611 Q_D(QDeclarativePauseAnimation);
612 if (d->pa->duration() == duration)
613 return;
614 d->pa->setDuration(duration);
615 emit durationChanged(duration);
616}
617
618QAbstractAnimation *QDeclarativePauseAnimation::qtAnimation()
619{
620 Q_D(QDeclarativePauseAnimation);
621 return d->pa;
622}
623
624/*!
625 \qmlclass ColorAnimation QDeclarativeColorAnimation
626 \ingroup qml-animation-transition
627 \since 4.7
628 \inherits PropertyAnimation
629 \brief The ColorAnimation element animates changes in color values.
630
631 ColorAnimation is a specialized PropertyAnimation that defines an
632 animation to be applied when a color value changes.
633
634 Here is a ColorAnimation applied to the \c color property of a \l Rectangle
635 as a property value source. It animates the \c color property's value from
636 its current value to a value of "red", over 1000 milliseconds:
637
638 \snippet doc/src/snippets/declarative/coloranimation.qml 0
639
640 Like any other animation element, a ColorAnimation can be applied in a
641 number of ways, including transitions, behaviors and property value
642 sources. The \l {QML Animation} documentation shows a variety of methods
643 for creating animations.
644
645 For convenience, when a ColorAnimation is used in a \l Transition, it will
646 animate any \c color properties that have been modified during the state
647 change. If a \l{PropertyAnimation::}{property} or
648 \l{PropertyAnimation::}{properties} are explicitly set for the animation,
649 then those are used instead.
650
651 \sa {QML Animation}, {declarative/animation/basics}{Animation basics example}
652*/
653QDeclarativeColorAnimation::QDeclarativeColorAnimation(QObject *parent)
654: QDeclarativePropertyAnimation(parent)
655{
656 Q_D(QDeclarativePropertyAnimation);
657 d->interpolatorType = QMetaType::QColor;
658 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
659 d->defaultToInterpolatorType = true;
660}
661
662QDeclarativeColorAnimation::~QDeclarativeColorAnimation()
663{
664}
665
666/*!
667 \qmlproperty color ColorAnimation::from
668 This property holds the color value at which the animation should begin.
669
670 For example, the following animation is not applied until a color value
671 has reached "#c0c0c0":
672
673 \qml
674 Item {
675 states: [ ... ]
676
677 transition: Transition {
678 NumberAnimation { from: "#c0c0c0"; duration: 2000 }
679 }
680 }
681 \endqml
682
683 If the ColorAnimation is defined within a \l Transition or \l Behavior,
684 this value defaults to the value defined in the starting state of the
685 \l Transition, or the current value of the property at the moment the
686 \l Behavior is triggered.
687
688 \sa {QML Animation}
689*/
690QColor QDeclarativeColorAnimation::from() const
691{
692 Q_D(const QDeclarativePropertyAnimation);
693 return d->from.value<QColor>();
694}
695
696void QDeclarativeColorAnimation::setFrom(const QColor &f)
697{
698 QDeclarativePropertyAnimation::setFrom(f);
699}
700
701/*!
702 \qmlproperty color ColorAnimation::to
703
704 This property holds the color value at which the animation should end.
705
706 If the ColorAnimation is defined within a \l Transition or \l Behavior,
707 this value defaults to the value defined in the end state of the
708 \l Transition, or the value of the property change that triggered the
709 \l Behavior.
710
711 \sa {QML Animation}
712*/
713QColor QDeclarativeColorAnimation::to() const
714{
715 Q_D(const QDeclarativePropertyAnimation);
716 return d->to.value<QColor>();
717}
718
719void QDeclarativeColorAnimation::setTo(const QColor &t)
720{
721 QDeclarativePropertyAnimation::setTo(t);
722}
723
724
725
726/*!
727 \qmlclass ScriptAction QDeclarativeScriptAction
728 \ingroup qml-animation-transition
729 \since 4.7
730 \inherits Animation
731 \brief The ScriptAction element allows scripts to be run during an animation.
732
733 ScriptAction can be used to run script at a specific point in an animation.
734
735 \qml
736 SequentialAnimation {
737 NumberAnimation { ... }
738 ScriptAction { script: doSomething(); }
739 NumberAnimation { ... }
740 }
741 \endqml
742
743 When used as part of a Transition, you can also target a specific
744 StateChangeScript to run using the \c scriptName property.
745
746 \qml
747 State {
748 StateChangeScript {
749 name: "myScript"
750 script: doStateStuff();
751 }
752 }
753 ...
754 Transition {
755 SequentialAnimation {
756 NumberAnimation { ... }
757 ScriptAction { scriptName: "myScript" }
758 NumberAnimation { ... }
759 }
760 }
761 \endqml
762
763 \sa StateChangeScript
764*/
765QDeclarativeScriptAction::QDeclarativeScriptAction(QObject *parent)
766 :QDeclarativeAbstractAnimation(*(new QDeclarativeScriptActionPrivate), parent)
767{
768 Q_D(QDeclarativeScriptAction);
769 d->init();
770}
771
772QDeclarativeScriptAction::~QDeclarativeScriptAction()
773{
774}
775
776void QDeclarativeScriptActionPrivate::init()
777{
778 Q_Q(QDeclarativeScriptAction);
779 rsa = new QActionAnimation(&proxy);
780 QDeclarative_setParent_noEvent(rsa, q);
781}
782
783/*!
784 \qmlproperty script ScriptAction::script
785 This property holds the script to run.
786*/
787QDeclarativeScriptString QDeclarativeScriptAction::script() const
788{
789 Q_D(const QDeclarativeScriptAction);
790 return d->script;
791}
792
793void QDeclarativeScriptAction::setScript(const QDeclarativeScriptString &script)
794{
795 Q_D(QDeclarativeScriptAction);
796 d->script = script;
797}
798
799/*!
800 \qmlproperty string ScriptAction::scriptName
801 This property holds the the name of the StateChangeScript to run.
802
803 This property is only valid when ScriptAction is used as part of a transition.
804 If both script and scriptName are set, scriptName will be used.
805
806 \note When using scriptName in a reversible transition, the script will only
807 be run when the transition is being run forwards.
808*/
809QString QDeclarativeScriptAction::stateChangeScriptName() const
810{
811 Q_D(const QDeclarativeScriptAction);
812 return d->name;
813}
814
815void QDeclarativeScriptAction::setStateChangeScriptName(const QString &name)
816{
817 Q_D(QDeclarativeScriptAction);
818 d->name = name;
819}
820
821void QDeclarativeScriptActionPrivate::execute()
822{
823 Q_Q(QDeclarativeScriptAction);
824 if (hasRunScriptScript && reversing)
825 return;
826
827 QDeclarativeScriptString scriptStr = hasRunScriptScript ? runScriptScript : script;
828
829 const QString &str = scriptStr.script();
830 if (!str.isEmpty()) {
831 QDeclarativeExpression expr(scriptStr.context(), scriptStr.scopeObject(), str);
832 QDeclarativeData *ddata = QDeclarativeData::get(q);
833 if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
834 expr.setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber);
835 expr.evaluate();
836 if (expr.hasError())
837 qmlInfo(q) << expr.error();
838 }
839}
840
841void QDeclarativeScriptAction::transition(QDeclarativeStateActions &actions,
842 QDeclarativeProperties &modified,
843 TransitionDirection direction)
844{
845 Q_D(QDeclarativeScriptAction);
846 Q_UNUSED(modified);
847
848 d->hasRunScriptScript = false;
849 d->reversing = (direction == Backward);
850 for (int ii = 0; ii < actions.count(); ++ii) {
851 QDeclarativeAction &action = actions[ii];
852
853 if (action.event && action.event->typeName() == QLatin1String("StateChangeScript")
854 && static_cast<QDeclarativeStateChangeScript*>(action.event)->name() == d->name) {
855 d->runScriptScript = static_cast<QDeclarativeStateChangeScript*>(action.event)->script();
856 d->hasRunScriptScript = true;
857 action.actionDone = true;
858 break; //only match one (names should be unique)
859 }
860 }
861}
862
863QAbstractAnimation *QDeclarativeScriptAction::qtAnimation()
864{
865 Q_D(QDeclarativeScriptAction);
866 return d->rsa;
867}
868
869
870
871/*!
872 \qmlclass PropertyAction QDeclarativePropertyAction
873 \ingroup qml-animation-transition
874 \since 4.7
875 \inherits Animation
876 \brief The PropertyAction element allows immediate property changes during animation.
877
878 PropertyAction is used to specify an immediate property change during an
879 animation. The property change is not animated.
880
881 It is useful for setting non-animated property values during an animation.
882
883 For example, here is a SequentialAnimation that sets the image's
884 \l {Image::}{smooth} property to \c true, animates the width of the image,
885 then sets \l {Image::}{smooth} back to \c false:
886
887 \snippet doc/src/snippets/declarative/propertyaction.qml standalone
888
889 PropertyAction is also useful for setting the exact point at which a property
890 change should occur during a \l Transition. For example, if PropertyChanges
891 was used in a \l State to rotate an item around a particular
892 \l {Item::}{transformOrigin}, it might be implemented like this:
893
894 \snippet doc/src/snippets/declarative/propertyaction.qml transition
895
896 However, with this code, the \c transformOrigin is not set until \e after
897 the animation, as a \l State is taken to define the values at the \e end of
898 a transition. The animation would rotate at the default \c transformOrigin,
899 then jump to \c Item.BottomRight. To fix this, insert a PropertyChanges
900 before the RotationAnimation begins:
901
902 \qml
903 transitions: Transition {
904 SequentialAnimation {
905 PropertyAction { target: rect; property: "transformOrigin" }
906 RotationAnimation { ... }
907 }
908 }
909 \endqml
910
911 This immediately sets the \c transformOrigin property to the value defined
912 in the end state of the \l Transition (i.e. the value defined in the
913 PropertyChanges object) so that the rotation animation begins with the
914 correct transform origin.
915
916 \sa {QML Animation}, QtDeclarative
917*/
918QDeclarativePropertyAction::QDeclarativePropertyAction(QObject *parent)
919: QDeclarativeAbstractAnimation(*(new QDeclarativePropertyActionPrivate), parent)
920{
921 Q_D(QDeclarativePropertyAction);
922 d->init();
923}
924
925QDeclarativePropertyAction::~QDeclarativePropertyAction()
926{
927}
928
929void QDeclarativePropertyActionPrivate::init()
930{
931 Q_Q(QDeclarativePropertyAction);
932 spa = new QActionAnimation;
933 QDeclarative_setParent_noEvent(spa, q);
934}
935
936QObject *QDeclarativePropertyAction::target() const
937{
938 Q_D(const QDeclarativePropertyAction);
939 return d->target;
940}
941
942void QDeclarativePropertyAction::setTarget(QObject *o)
943{
944 Q_D(QDeclarativePropertyAction);
945 if (d->target == o)
946 return;
947 d->target = o;
948 emit targetChanged();
949}
950
951QString QDeclarativePropertyAction::property() const
952{
953 Q_D(const QDeclarativePropertyAction);
954 return d->propertyName;
955}
956
957void QDeclarativePropertyAction::setProperty(const QString &n)
958{
959 Q_D(QDeclarativePropertyAction);
960 if (d->propertyName == n)
961 return;
962 d->propertyName = n;
963 emit propertyChanged();
964}
965
966/*!
967 \qmlproperty Object PropertyAction::target
968 \qmlproperty list<Object> PropertyAction::targets
969 \qmlproperty string PropertyAction::property
970 \qmlproperty string PropertyAction::properties
971
972 These properties determine the items and their properties that are
973 affected by this action.
974
975 The details of how these properties are interpreted in different situations
976 is covered in the \l{PropertyAnimation::properties}{corresponding} PropertyAnimation
977 documentation.
978
979 \sa exclude
980*/
981QString QDeclarativePropertyAction::properties() const
982{
983 Q_D(const QDeclarativePropertyAction);
984 return d->properties;
985}
986
987void QDeclarativePropertyAction::setProperties(const QString &p)
988{
989 Q_D(QDeclarativePropertyAction);
990 if (d->properties == p)
991 return;
992 d->properties = p;
993 emit propertiesChanged(p);
994}
995
996QDeclarativeListProperty<QObject> QDeclarativePropertyAction::targets()
997{
998 Q_D(QDeclarativePropertyAction);
999 return QDeclarativeListProperty<QObject>(this, d->targets);
1000}
1001
1002/*!
1003 \qmlproperty list<Object> PropertyAction::exclude
1004 This property holds the objects that should not be affected by this action.
1005
1006 \sa targets
1007*/
1008QDeclarativeListProperty<QObject> QDeclarativePropertyAction::exclude()
1009{
1010 Q_D(QDeclarativePropertyAction);
1011 return QDeclarativeListProperty<QObject>(this, d->exclude);
1012}
1013
1014/*!
1015 \qmlproperty any PropertyAction::value
1016 This property holds the value to be set on the property.
1017
1018 If the PropertyAction is defined within a \l Transition or \l Behavior,
1019 this value defaults to the value defined in the end state of the
1020 \l Transition, or the value of the property change that triggered the
1021 \l Behavior.
1022*/
1023QVariant QDeclarativePropertyAction::value() const
1024{
1025 Q_D(const QDeclarativePropertyAction);
1026 return d->value;
1027}
1028
1029void QDeclarativePropertyAction::setValue(const QVariant &v)
1030{
1031 Q_D(QDeclarativePropertyAction);
1032 if (d->value.isNull || d->value != v) {
1033 d->value = v;
1034 emit valueChanged(v);
1035 }
1036}
1037
1038QAbstractAnimation *QDeclarativePropertyAction::qtAnimation()
1039{
1040 Q_D(QDeclarativePropertyAction);
1041 return d->spa;
1042}
1043
1044void QDeclarativePropertyAction::transition(QDeclarativeStateActions &actions,
1045 QDeclarativeProperties &modified,
1046 TransitionDirection direction)
1047{
1048 Q_D(QDeclarativePropertyAction);
1049 Q_UNUSED(direction);
1050
1051 struct QDeclarativeSetPropertyAnimationAction : public QAbstractAnimationAction
1052 {
1053 QDeclarativeStateActions actions;
1054 virtual void doAction()
1055 {
1056 for (int ii = 0; ii < actions.count(); ++ii) {
1057 const QDeclarativeAction &action = actions.at(ii);
1058 QDeclarativePropertyPrivate::write(action.property, action.toValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
1059 }
1060 }
1061 };
1062
1063 QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(','));
1064 for (int ii = 0; ii < props.count(); ++ii)
1065 props[ii] = props.at(ii).trimmed();
1066 if (!d->propertyName.isEmpty())
1067 props << d->propertyName;
1068
1069 QList<QObject*> targets = d->targets;
1070 if (d->target)
1071 targets.append(d->target);
1072
1073 bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty();
1074
1075 if (d->defaultProperty.isValid() && !hasSelectors) {
1076 props << d->defaultProperty.name();
1077 targets << d->defaultProperty.object();
1078 }
1079
1080 QDeclarativeSetPropertyAnimationAction *data = new QDeclarativeSetPropertyAnimationAction;
1081
1082 bool hasExplicit = false;
1083 //an explicit animation has been specified
1084 if (d->value.isValid()) {
1085 for (int i = 0; i < props.count(); ++i) {
1086 for (int j = 0; j < targets.count(); ++j) {
1087 QDeclarativeAction myAction;
1088 myAction.property = d->createProperty(targets.at(j), props.at(i), this);
1089 if (myAction.property.isValid()) {
1090 myAction.toValue = d->value;
1091 QDeclarativePropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyType());
1092 data->actions << myAction;
1093 hasExplicit = true;
1094 for (int ii = 0; ii < actions.count(); ++ii) {
1095 QDeclarativeAction &action = actions[ii];
1096 if (action.property.object() == myAction.property.object() &&
1097 myAction.property.name() == action.property.name()) {
1098 modified << action.property;
1099 break; //### any chance there could be multiples?
1100 }
1101 }
1102 }
1103 }
1104 }
1105 }
1106
1107 if (!hasExplicit)
1108 for (int ii = 0; ii < actions.count(); ++ii) {
1109 QDeclarativeAction &action = actions[ii];
1110
1111 QObject *obj = action.property.object();
1112 QString propertyName = action.property.name();
1113 QObject *sObj = action.specifiedObject;
1114 QString sPropertyName = action.specifiedProperty;
1115 bool same = (obj == sObj);
1116
1117 if ((targets.isEmpty() || targets.contains(obj) || (!same && targets.contains(sObj))) &&
1118 (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) &&
1119 (props.contains(propertyName) || (!same && props.contains(sPropertyName)))) {
1120 QDeclarativeAction myAction = action;
1121
1122 if (d->value.isValid())
1123 myAction.toValue = d->value;
1124 QDeclarativePropertyAnimationPrivate::convertVariant(myAction.toValue, myAction.property.propertyType());
1125
1126 modified << action.property;
1127 data->actions << myAction;
1128 action.fromValue = myAction.toValue;
1129 }
1130 }
1131
1132 if (data->actions.count()) {
1133 d->spa->setAnimAction(data, QAbstractAnimation::DeleteWhenStopped);
1134 } else {
1135 delete data;
1136 }
1137}
1138
1139/*!
1140 \qmlclass NumberAnimation QDeclarativeNumberAnimation
1141 \ingroup qml-animation-transition
1142 \since 4.7
1143 \inherits PropertyAnimation
1144 \brief The NumberAnimation element animates changes in qreal-type values.
1145
1146 NumberAnimation is a specialized PropertyAnimation that defines an
1147 animation to be applied when a numerical value changes.
1148
1149 Here is a NumberAnimation applied to the \c x property of a \l Rectangle
1150 as a property value source. It animates the \c x value from its current
1151 value to a value of 50, over 1000 milliseconds:
1152
1153 \snippet doc/src/snippets/declarative/numberanimation.qml 0
1154
1155 Like any other animation element, a NumberAnimation can be applied in a
1156 number of ways, including transitions, behaviors and property value
1157 sources. The \l {QML Animation} documentation shows a variety of methods
1158 for creating animations.
1159
1160 Note that NumberAnimation may not animate smoothly if there are irregular
1161 changes in the number value that it is tracking. If this is the case, use
1162 SmoothedAnimation instead.
1163
1164 \sa {QML Animation}, {declarative/animation/basics}{Animation basics example}
1165*/
1166QDeclarativeNumberAnimation::QDeclarativeNumberAnimation(QObject *parent)
1167: QDeclarativePropertyAnimation(parent)
1168{
1169 init();
1170}
1171
1172QDeclarativeNumberAnimation::QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent)
1173: QDeclarativePropertyAnimation(dd, parent)
1174{
1175 init();
1176}
1177
1178QDeclarativeNumberAnimation::~QDeclarativeNumberAnimation()
1179{
1180}
1181
1182void QDeclarativeNumberAnimation::init()
1183{
1184 Q_D(QDeclarativePropertyAnimation);
1185 d->interpolatorType = QMetaType::QReal;
1186 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
1187}
1188
1189/*!
1190 \qmlproperty real NumberAnimation::from
1191 This property holds the starting value for the animation.
1192
1193 For example, the following animation is not applied until the \c x value
1194 has reached 100:
1195
1196 \qml
1197 Item {
1198 states: [ ... ]
1199
1200 transition: Transition {
1201 NumberAnimation { properties: "x"; from: 100; duration: 200 }
1202 }
1203 }
1204 \endqml
1205
1206 If the NumberAnimation is defined within a \l Transition or \l Behavior,
1207 this value defaults to the value defined in the starting state of the
1208 \l Transition, or the current value of the property at the moment the
1209 \l Behavior is triggered.
1210
1211 \sa {QML Animation}
1212*/
1213
1214qreal QDeclarativeNumberAnimation::from() const
1215{
1216 Q_D(const QDeclarativePropertyAnimation);
1217 return d->from.toReal();
1218}
1219
1220void QDeclarativeNumberAnimation::setFrom(qreal f)
1221{
1222 QDeclarativePropertyAnimation::setFrom(f);
1223}
1224
1225/*!
1226 \qmlproperty real NumberAnimation::to
1227 This property holds the end value for the animation.
1228
1229 If the NumberAnimation is defined within a \l Transition or \l Behavior,
1230 this value defaults to the value defined in the end state of the
1231 \l Transition, or the value of the property change that triggered the
1232 \l Behavior.
1233
1234 \sa {QML Animation}
1235*/
1236qreal QDeclarativeNumberAnimation::to() const
1237{
1238 Q_D(const QDeclarativePropertyAnimation);
1239 return d->to.toReal();
1240}
1241
1242void QDeclarativeNumberAnimation::setTo(qreal t)
1243{
1244 QDeclarativePropertyAnimation::setTo(t);
1245}
1246
1247
1248
1249/*!
1250 \qmlclass Vector3dAnimation QDeclarativeVector3dAnimation
1251 \ingroup qml-animation-transition
1252 \since 4.7
1253 \inherits PropertyAnimation
1254 \brief The Vector3dAnimation element animates changes in QVector3d values.
1255
1256 Vector3dAnimation is a specialized PropertyAnimation that defines an
1257 animation to be applied when a Vector3d value changes.
1258
1259 Like any other animation element, a Vector3dAnimation can be applied in a
1260 number of ways, including transitions, behaviors and property value
1261 sources. The \l {QML Animation} documentation shows a variety of methods
1262 for creating animations.
1263
1264 \sa {QML Animation}, {declarative/animation/basics}{Animation basics example}
1265*/
1266QDeclarativeVector3dAnimation::QDeclarativeVector3dAnimation(QObject *parent)
1267: QDeclarativePropertyAnimation(parent)
1268{
1269 Q_D(QDeclarativePropertyAnimation);
1270 d->interpolatorType = QMetaType::QVector3D;
1271 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
1272 d->defaultToInterpolatorType = true;
1273}
1274
1275QDeclarativeVector3dAnimation::~QDeclarativeVector3dAnimation()
1276{
1277}
1278
1279/*!
1280 \qmlproperty real Vector3dAnimation::from
1281 This property holds the starting value for the animation.
1282
1283 If the Vector3dAnimation is defined within a \l Transition or \l Behavior,
1284 this value defaults to the value defined in the starting state of the
1285 \l Transition, or the current value of the property at the moment the
1286 \l Behavior is triggered.
1287
1288 \sa {QML Animation}
1289*/
1290QVector3D QDeclarativeVector3dAnimation::from() const
1291{
1292 Q_D(const QDeclarativePropertyAnimation);
1293 return d->from.value<QVector3D>();
1294}
1295
1296void QDeclarativeVector3dAnimation::setFrom(QVector3D f)
1297{
1298 QDeclarativePropertyAnimation::setFrom(f);
1299}
1300
1301/*!
1302 \qmlproperty real Vector3dAnimation::to
1303 This property holds the end value for the animation.
1304
1305 If the Vector3dAnimation is defined within a \l Transition or \l Behavior,
1306 this value defaults to the value defined in the end state of the
1307 \l Transition, or the value of the property change that triggered the
1308 \l Behavior.
1309
1310 \sa {QML Animation}
1311*/
1312QVector3D QDeclarativeVector3dAnimation::to() const
1313{
1314 Q_D(const QDeclarativePropertyAnimation);
1315 return d->to.value<QVector3D>();
1316}
1317
1318void QDeclarativeVector3dAnimation::setTo(QVector3D t)
1319{
1320 QDeclarativePropertyAnimation::setTo(t);
1321}
1322
1323
1324
1325/*!
1326 \qmlclass RotationAnimation QDeclarativeRotationAnimation
1327 \ingroup qml-animation-transition
1328 \since 4.7
1329 \inherits PropertyAnimation
1330 \brief The RotationAnimation element animates changes in rotation values.
1331
1332 RotationAnimation is a specialized PropertyAnimation that gives control
1333 over the direction of rotation during an animation.
1334
1335 By default, it rotates in the direction
1336 of the numerical change; a rotation from 0 to 240 will rotate 240 degrees
1337 clockwise, while a rotation from 240 to 0 will rotate 240 degrees
1338 counterclockwise. The \l direction property can be set to specify the
1339 direction in which the rotation should occur.
1340
1341 In the following example we use RotationAnimation to animate the rotation
1342 between states via the shortest path:
1343
1344 \snippet doc/src/snippets/declarative/rotationanimation.qml 0
1345
1346 Notice the RotationAnimation did not need to set a \l target
1347 value. As a convenience, when used in a transition, RotationAnimation will rotate all
1348 properties named "rotation" or "angle". You can override this by providing
1349 your own properties via \l {PropertyAnimation::properties}{properties} or
1350 \l {PropertyAnimation::property}{property}.
1351
1352 Also, note the \l Rectangle will be rotated around its default
1353 \l {Item::}{transformOrigin} (which is \c Item.Center). To use a different
1354 transform origin, set the origin in the PropertyChanges object and apply
1355 the change at the start of the animation using PropertyAction. See the
1356 PropertyAction documentation for more details.
1357
1358 Like any other animation element, a RotationAnimation can be applied in a
1359 number of ways, including transitions, behaviors and property value
1360 sources. The \l {QML Animation} documentation shows a variety of methods
1361 for creating animations.
1362
1363 \sa {QML Animation}, {declarative/animation/basics}{Animation basics example}
1364*/
1365QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress)
1366{
1367 qreal newt = t;
1368 qreal diff = t-f;
1369 while(diff > 180.0){
1370 newt -= 360.0;
1371 diff -= 360.0;
1372 }
1373 while(diff < -180.0){
1374 newt += 360.0;
1375 diff += 360.0;
1376 }
1377 return QVariant(f + (newt - f) * progress);
1378}
1379
1380QVariant _q_interpolateClockwiseRotation(qreal &f, qreal &t, qreal progress)
1381{
1382 qreal newt = t;
1383 qreal diff = t-f;
1384 while(diff < 0.0){
1385 newt += 360.0;
1386 diff += 360.0;
1387 }
1388 return QVariant(f + (newt - f) * progress);
1389}
1390
1391QVariant _q_interpolateCounterclockwiseRotation(qreal &f, qreal &t, qreal progress)
1392{
1393 qreal newt = t;
1394 qreal diff = t-f;
1395 while(diff > 0.0){
1396 newt -= 360.0;
1397 diff -= 360.0;
1398 }
1399 return QVariant(f + (newt - f) * progress);
1400}
1401
1402QDeclarativeRotationAnimation::QDeclarativeRotationAnimation(QObject *parent)
1403: QDeclarativePropertyAnimation(*(new QDeclarativeRotationAnimationPrivate), parent)
1404{
1405 Q_D(QDeclarativeRotationAnimation);
1406 d->interpolatorType = QMetaType::QReal;
1407 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
1408 d->defaultProperties = QLatin1String("rotation,angle");
1409}
1410
1411QDeclarativeRotationAnimation::~QDeclarativeRotationAnimation()
1412{
1413}
1414
1415/*!
1416 \qmlproperty real RotationAnimation::from
1417 This property holds the starting value for the animation.
1418
1419 For example, the following animation is not applied until the \c angle value
1420 has reached 100:
1421
1422 \qml
1423 Item {
1424 states: [ ... ]
1425
1426 transition: Transition {
1427 RotationAnimation { properties: "angle"; from: 100; duration: 2000 }
1428 }
1429 }
1430 \endqml
1431
1432 If the RotationAnimation is defined within a \l Transition or \l Behavior,
1433 this value defaults to the value defined in the starting state of the
1434 \l Transition, or the current value of the property at the moment the
1435 \l Behavior is triggered.
1436
1437 \sa {QML Animation}
1438*/
1439qreal QDeclarativeRotationAnimation::from() const
1440{
1441 Q_D(const QDeclarativeRotationAnimation);
1442 return d->from.toReal();
1443}
1444
1445void QDeclarativeRotationAnimation::setFrom(qreal f)
1446{
1447 QDeclarativePropertyAnimation::setFrom(f);
1448}
1449
1450/*!
1451 \qmlproperty real RotationAnimation::to
1452 This property holds the end value for the animation..
1453
1454 If the RotationAnimation is defined within a \l Transition or \l Behavior,
1455 this value defaults to the value defined in the end state of the
1456 \l Transition, or the value of the property change that triggered the
1457 \l Behavior.
1458
1459 \sa {QML Animation}
1460*/
1461qreal QDeclarativeRotationAnimation::to() const
1462{
1463 Q_D(const QDeclarativeRotationAnimation);
1464 return d->to.toReal();
1465}
1466
1467void QDeclarativeRotationAnimation::setTo(qreal t)
1468{
1469 QDeclarativePropertyAnimation::setTo(t);
1470}
1471
1472/*!
1473 \qmlproperty enumeration RotationAnimation::direction
1474 This property holds the direction of the rotation.
1475
1476 Possible values are:
1477
1478 \list
1479 \o RotationAnimation.Numerical (default) - Rotate by linearly interpolating between the two numbers.
1480 A rotation from 10 to 350 will rotate 340 degrees clockwise.
1481 \o RotationAnimation.Clockwise - Rotate clockwise between the two values
1482 \o RotationAnimation.Counterclockwise - Rotate counterclockwise between the two values
1483 \o RotationAnimation.Shortest - Rotate in the direction that produces the shortest animation path.
1484 A rotation from 10 to 350 will rotate 20 degrees counterclockwise.
1485 \endlist
1486*/
1487QDeclarativeRotationAnimation::RotationDirection QDeclarativeRotationAnimation::direction() const
1488{
1489 Q_D(const QDeclarativeRotationAnimation);
1490 return d->direction;
1491}
1492
1493void QDeclarativeRotationAnimation::setDirection(QDeclarativeRotationAnimation::RotationDirection direction)
1494{
1495 Q_D(QDeclarativeRotationAnimation);
1496 if (d->direction == direction)
1497 return;
1498
1499 d->direction = direction;
1500 switch(d->direction) {
1501 case Clockwise:
1502 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateClockwiseRotation);
1503 break;
1504 case Counterclockwise:
1505 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateCounterclockwiseRotation);
1506 break;
1507 case Shortest:
1508 d->interpolator = reinterpret_cast<QVariantAnimation::Interpolator>(&_q_interpolateShortestRotation);
1509 break;
1510 default:
1511 d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
1512 break;
1513 }
1514
1515 emit directionChanged();
1516}
1517
1518
1519
1520QDeclarativeAnimationGroup::QDeclarativeAnimationGroup(QObject *parent)
1521: QDeclarativeAbstractAnimation(*(new QDeclarativeAnimationGroupPrivate), parent)
1522{
1523}
1524
1525QDeclarativeAnimationGroup::QDeclarativeAnimationGroup(QDeclarativeAnimationGroupPrivate &dd, QObject *parent)
1526 : QDeclarativeAbstractAnimation(dd, parent)
1527{
1528}
1529
1530void QDeclarativeAnimationGroupPrivate::append_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, QDeclarativeAbstractAnimation *a)
1531{
1532 QDeclarativeAnimationGroup *q = qobject_cast<QDeclarativeAnimationGroup *>(list->object);
1533 if (q) {
1534 a->setGroup(q);
1535 QDeclarative_setParent_noEvent(a->qtAnimation(), q->d_func()->ag);
1536 q->d_func()->ag->addAnimation(a->qtAnimation());
1537 }
1538}
1539
1540void QDeclarativeAnimationGroupPrivate::clear_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list)
1541{
1542 QDeclarativeAnimationGroup *q = qobject_cast<QDeclarativeAnimationGroup *>(list->object);
1543 if (q) {
1544 for (int i = 0; i < q->d_func()->animations.count(); ++i)
1545 q->d_func()->animations.at(i)->setGroup(0);
1546 q->d_func()->animations.clear();
1547 }
1548}
1549
1550QDeclarativeAnimationGroup::~QDeclarativeAnimationGroup()
1551{
1552}
1553
1554QDeclarativeListProperty<QDeclarativeAbstractAnimation> QDeclarativeAnimationGroup::animations()
1555{
1556 Q_D(QDeclarativeAnimationGroup);
1557 QDeclarativeListProperty<QDeclarativeAbstractAnimation> list(this, d->animations);
1558 list.append = &QDeclarativeAnimationGroupPrivate::append_animation;
1559 list.clear = &QDeclarativeAnimationGroupPrivate::clear_animation;
1560 return list;
1561}
1562
1563/*!
1564 \qmlclass SequentialAnimation QDeclarativeSequentialAnimation
1565 \ingroup qml-animation-transition
1566 \since 4.7
1567 \inherits Animation
1568 \brief The SequentialAnimation element allows animations to be run sequentially.
1569
1570 The SequentialAnimation and ParallelAnimation elements allow multiple
1571 animations to be run together. Animations defined in a SequentialAnimation
1572 are run one after the other, while animations defined in a ParallelAnimation
1573 are run at the same time.
1574
1575 The following example runs two number animations in a sequence. The \l Rectangle
1576 animates to a \c x position of 50, then to a \c y position of 50.
1577
1578 \snippet doc/src/snippets/declarative/sequentialanimation.qml 0
1579
1580 Animations defined within a \l Transition are automatically run in parallel,
1581 so SequentialAnimation can be used to enclose the animations in a \l Transition
1582 if this is the preferred behavior.
1583
1584 Like any other animation element, a SequentialAnimation can be applied in a
1585 number of ways, including transitions, behaviors and property value
1586 sources. The \l {QML Animation} documentation shows a variety of methods
1587 for creating animations.
1588
1589 \note Once an animation has been grouped into a SequentialAnimation or
1590 ParallelAnimation, it cannot be individually started and stopped; the
1591 SequentialAnimation or ParallelAnimation must be started and stopped as a group.
1592
1593 \sa ParallelAnimation, {QML Animation}, {declarative/animation/basics}{Animation basics example}
1594*/
1595
1596QDeclarativeSequentialAnimation::QDeclarativeSequentialAnimation(QObject *parent) :
1597 QDeclarativeAnimationGroup(parent)
1598{
1599 Q_D(QDeclarativeAnimationGroup);
1600 d->ag = new QSequentialAnimationGroup;
1601 QDeclarative_setParent_noEvent(d->ag, this);
1602}
1603
1604QDeclarativeSequentialAnimation::~QDeclarativeSequentialAnimation()
1605{
1606}
1607
1608QAbstractAnimation *QDeclarativeSequentialAnimation::qtAnimation()
1609{
1610 Q_D(QDeclarativeAnimationGroup);
1611 return d->ag;
1612}
1613
1614void QDeclarativeSequentialAnimation::transition(QDeclarativeStateActions &actions,
1615 QDeclarativeProperties &modified,
1616 TransitionDirection direction)
1617{
1618 Q_D(QDeclarativeAnimationGroup);
1619
1620 int inc = 1;
1621 int from = 0;
1622 if (direction == Backward) {
1623 inc = -1;
1624 from = d->animations.count() - 1;
1625 }
1626
1627 bool valid = d->defaultProperty.isValid();
1628 for (int ii = from; ii < d->animations.count() && ii >= 0; ii += inc) {
1629 if (valid)
1630 d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
1631 d->animations.at(ii)->transition(actions, modified, direction);
1632 }
1633}
1634
1635
1636
1637/*!
1638 \qmlclass ParallelAnimation QDeclarativeParallelAnimation
1639 \ingroup qml-animation-transition
1640 \since 4.7
1641 \inherits Animation
1642 \brief The ParallelAnimation element allows animations to be run in parallel.
1643
1644 The SequentialAnimation and ParallelAnimation elements allow multiple
1645 animations to be run together. Animations defined in a SequentialAnimation
1646 are run one after the other, while animations defined in a ParallelAnimation
1647 are run at the same time.
1648
1649 The following animation runs two number animations in parallel. The \l Rectangle
1650 moves to (50,50) by animating its \c x and \c y properties at the same time.
1651
1652 \snippet doc/src/snippets/declarative/parallelanimation.qml 0
1653
1654 Like any other animation element, a ParallelAnimation can be applied in a
1655 number of ways, including transitions, behaviors and property value
1656 sources. The \l {QML Animation} documentation shows a variety of methods
1657 for creating animations.
1658
1659 \note Once an animation has been grouped into a SequentialAnimation or
1660 ParallelAnimation, it cannot be individually started and stopped; the
1661 SequentialAnimation or ParallelAnimation must be started and stopped as a group.
1662
1663 \sa SequentialAnimation, {QML Animation}, {declarative/animation/basics}{Animation basics example}
1664*/
1665QDeclarativeParallelAnimation::QDeclarativeParallelAnimation(QObject *parent) :
1666 QDeclarativeAnimationGroup(parent)
1667{
1668 Q_D(QDeclarativeAnimationGroup);
1669 d->ag = new QParallelAnimationGroup;
1670 QDeclarative_setParent_noEvent(d->ag, this);
1671}
1672
1673QDeclarativeParallelAnimation::~QDeclarativeParallelAnimation()
1674{
1675}
1676
1677QAbstractAnimation *QDeclarativeParallelAnimation::qtAnimation()
1678{
1679 Q_D(QDeclarativeAnimationGroup);
1680 return d->ag;
1681}
1682
1683void QDeclarativeParallelAnimation::transition(QDeclarativeStateActions &actions,
1684 QDeclarativeProperties &modified,
1685 TransitionDirection direction)
1686{
1687 Q_D(QDeclarativeAnimationGroup);
1688 bool valid = d->defaultProperty.isValid();
1689 for (int ii = 0; ii < d->animations.count(); ++ii) {
1690 if (valid)
1691 d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
1692 d->animations.at(ii)->transition(actions, modified, direction);
1693 }
1694}
1695
1696
1697
1698//convert a variant from string type to another animatable type
1699void QDeclarativePropertyAnimationPrivate::convertVariant(QVariant &variant, int type)
1700{
1701 if (variant.userType() != QVariant::String) {
1702 variant.convert((QVariant::Type)type);
1703 return;
1704 }
1705
1706 switch (type) {
1707 case QVariant::Rect: {
1708 variant.setValue(QDeclarativeStringConverters::rectFFromString(variant.toString()).toRect());
1709 break;
1710 }
1711 case QVariant::RectF: {
1712 variant.setValue(QDeclarativeStringConverters::rectFFromString(variant.toString()));
1713 break;
1714 }
1715 case QVariant::Point: {
1716 variant.setValue(QDeclarativeStringConverters::pointFFromString(variant.toString()).toPoint());
1717 break;
1718 }
1719 case QVariant::PointF: {
1720 variant.setValue(QDeclarativeStringConverters::pointFFromString(variant.toString()));
1721 break;
1722 }
1723 case QVariant::Size: {
1724 variant.setValue(QDeclarativeStringConverters::sizeFFromString(variant.toString()).toSize());
1725 break;
1726 }
1727 case QVariant::SizeF: {
1728 variant.setValue(QDeclarativeStringConverters::sizeFFromString(variant.toString()));
1729 break;
1730 }
1731 case QVariant::Color: {
1732 variant.setValue(QDeclarativeStringConverters::colorFromString(variant.toString()));
1733 break;
1734 }
1735 case QVariant::Vector3D: {
1736 variant.setValue(QDeclarativeStringConverters::vector3DFromString(variant.toString()));
1737 break;
1738 }
1739 default:
1740 if (QDeclarativeValueTypeFactory::isValueType((uint)type)) {
1741 variant.convert((QVariant::Type)type);
1742 } else {
1743 QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
1744 if (converter)
1745 variant = converter(variant.toString());
1746 }
1747 break;
1748 }
1749}
1750
1751/*!
1752 \qmlclass PropertyAnimation QDeclarativePropertyAnimation
1753 \ingroup qml-animation-transition
1754 \since 4.7
1755 \inherits Animation
1756 \brief The PropertyAnimation element animates changes in property values.
1757
1758 PropertyAnimation provides a way to animate changes to a property's value.
1759
1760 It can be used to define animations in a number of ways:
1761
1762 \list
1763 \o In a \l Transition
1764
1765 For example, to animate any objects that have changed their \c x or \c y properties
1766 as a result of a state change, using an \c InOutQuad easing curve:
1767
1768 \snippet doc/src/snippets/declarative/propertyanimation.qml transition
1769
1770
1771 \o In a \l Behavior
1772
1773 For example, to animate all changes to a rectangle's \c x property:
1774
1775 \snippet doc/src/snippets/declarative/propertyanimation.qml behavior
1776
1777
1778 \o As a property value source
1779
1780 For example, to repeatedly animate the rectangle's \c x property:
1781
1782 \snippet doc/src/snippets/declarative/propertyanimation.qml propertyvaluesource
1783
1784
1785 \o In a signal handler
1786
1787 For example, to fade out \c theObject when clicked:
1788 \qml
1789 MouseArea {
1790 anchors.fill: theObject
1791 onClicked: PropertyAnimation { target: theObject; property: "opacity"; to: 0 }
1792 }
1793 \endqml
1794
1795 \o Standalone
1796
1797 For example, to animate \c rect's \c width property over 500ms, from its current width to 30:
1798
1799 \snippet doc/src/snippets/declarative/propertyanimation.qml standalone
1800
1801 \endlist
1802
1803 Depending on how the animation is used, the set of properties normally used will be
1804 different. For more information see the individual property documentation, as well
1805 as the \l{QML Animation} introduction.
1806
1807 Note that PropertyAnimation inherits the abstract \l Animation element.
1808 This includes additional properties and methods for controlling the animation.
1809
1810 \sa {QML Animation}, {declarative/animation/basics}{Animation basics example}
1811*/
1812
1813QDeclarativePropertyAnimation::QDeclarativePropertyAnimation(QObject *parent)
1814: QDeclarativeAbstractAnimation(*(new QDeclarativePropertyAnimationPrivate), parent)
1815{
1816 Q_D(QDeclarativePropertyAnimation);
1817 d->init();
1818}
1819
1820QDeclarativePropertyAnimation::QDeclarativePropertyAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent)
1821: QDeclarativeAbstractAnimation(dd, parent)
1822{
1823 Q_D(QDeclarativePropertyAnimation);
1824 d->init();
1825}
1826
1827QDeclarativePropertyAnimation::~QDeclarativePropertyAnimation()
1828{
1829}
1830
1831void QDeclarativePropertyAnimationPrivate::init()
1832{
1833 Q_Q(QDeclarativePropertyAnimation);
1834 va = new QDeclarativeBulkValueAnimator;
1835 QDeclarative_setParent_noEvent(va, q);
1836}
1837
1838/*!
1839 \qmlproperty int PropertyAnimation::duration
1840 This property holds the duration of the animation, in milliseconds.
1841
1842 The default value is 250.
1843*/
1844int QDeclarativePropertyAnimation::duration() const
1845{
1846 Q_D(const QDeclarativePropertyAnimation);
1847 return d->va->duration();
1848}
1849
1850void QDeclarativePropertyAnimation::setDuration(int duration)
1851{
1852 if (duration < 0) {
1853 qmlInfo(this) << tr("Cannot set a duration of < 0");
1854 return;
1855 }
1856
1857 Q_D(QDeclarativePropertyAnimation);
1858 if (d->va->duration() == duration)
1859 return;
1860 d->va->setDuration(duration);
1861 emit durationChanged(duration);
1862}
1863
1864/*!
1865 \qmlproperty real PropertyAnimation::from
1866 This property holds the starting value for the animation.
1867
1868 If the PropertyAnimation is defined within a \l Transition or \l Behavior,
1869 this value defaults to the value defined in the starting state of the
1870 \l Transition, or the current value of the property at the moment the
1871 \l Behavior is triggered.
1872
1873 \sa {QML Animation}
1874*/
1875QVariant QDeclarativePropertyAnimation::from() const
1876{
1877 Q_D(const QDeclarativePropertyAnimation);
1878 return d->from;
1879}
1880
1881void QDeclarativePropertyAnimation::setFrom(const QVariant &f)
1882{
1883 Q_D(QDeclarativePropertyAnimation);
1884 if (d->fromIsDefined && f == d->from)
1885 return;
1886 d->from = f;
1887 d->fromIsDefined = f.isValid();
1888 emit fromChanged(f);
1889}
1890
1891/*!
1892 \qmlproperty real PropertyAnimation::to
1893 This property holds the end value for the animation.
1894
1895 If the PropertyAnimation is defined within a \l Transition or \l Behavior,
1896 this value defaults to the value defined in the end state of the
1897 \l Transition, or the value of the property change that triggered the
1898 \l Behavior.
1899
1900 \sa {QML Animation}
1901*/
1902QVariant QDeclarativePropertyAnimation::to() const
1903{
1904 Q_D(const QDeclarativePropertyAnimation);
1905 return d->to;
1906}
1907
1908void QDeclarativePropertyAnimation::setTo(const QVariant &t)
1909{
1910 Q_D(QDeclarativePropertyAnimation);
1911 if (d->toIsDefined && t == d->to)
1912 return;
1913 d->to = t;
1914 d->toIsDefined = t.isValid();
1915 emit toChanged(t);
1916}
1917
1918/*!
1919 \qmlproperty enumeration PropertyAnimation::easing.type
1920 \qmlproperty real PropertyAnimation::easing.amplitude
1921 \qmlproperty real PropertyAnimation::easing.overshoot
1922 \qmlproperty real PropertyAnimation::easing.period
1923 \brief the easing curve used for the animation.
1924
1925 To specify an easing curve you need to specify at least the type. For some curves you can also specify
1926 amplitude, period and/or overshoot (more details provided after the table). The default easing curve is
1927 \c Easing.Linear.
1928
1929 \qml
1930 PropertyAnimation { properties: "y"; easing.type: Easing.InOutElastic; easing.amplitude: 2.0; easing.period: 1.5 }
1931 \endqml
1932
1933 Available types are:
1934
1935 \table
1936 \row
1937 \o \c Easing.Linear
1938 \o Easing curve for a linear (t) function: velocity is constant.
1939 \o \inlineimage qeasingcurve-linear.png
1940 \row
1941 \o \c Easing.InQuad
1942 \o Easing curve for a quadratic (t^2) function: accelerating from zero velocity.
1943 \o \inlineimage qeasingcurve-inquad.png
1944 \row
1945 \o \c Easing.OutQuad
1946 \o Easing curve for a quadratic (t^2) function: decelerating to zero velocity.
1947 \o \inlineimage qeasingcurve-outquad.png
1948 \row
1949 \o \c Easing.InOutQuad
1950 \o Easing curve for a quadratic (t^2) function: acceleration until halfway, then deceleration.
1951 \o \inlineimage qeasingcurve-inoutquad.png
1952 \row
1953 \o \c Easing.OutInQuad
1954 \o Easing curve for a quadratic (t^2) function: deceleration until halfway, then acceleration.
1955 \o \inlineimage qeasingcurve-outinquad.png
1956 \row
1957 \o \c Easing.InCubic
1958 \o Easing curve for a cubic (t^3) function: accelerating from zero velocity.
1959 \o \inlineimage qeasingcurve-incubic.png
1960 \row
1961 \o \c Easing.OutCubic
1962 \o Easing curve for a cubic (t^3) function: decelerating from zero velocity.
1963 \o \inlineimage qeasingcurve-outcubic.png
1964 \row
1965 \o \c Easing.InOutCubic
1966 \o Easing curve for a cubic (t^3) function: acceleration until halfway, then deceleration.
1967 \o \inlineimage qeasingcurve-inoutcubic.png
1968 \row
1969 \o \c Easing.OutInCubic
1970 \o Easing curve for a cubic (t^3) function: deceleration until halfway, then acceleration.
1971 \o \inlineimage qeasingcurve-outincubic.png
1972 \row
1973 \o \c Easing.InQuart
1974 \o Easing curve for a quartic (t^4) function: accelerating from zero velocity.
1975 \o \inlineimage qeasingcurve-inquart.png
1976 \row
1977 \o \c Easing.OutQuart
1978 \o Easing curve for a quartic (t^4) function: decelerating from zero velocity.
1979 \o \inlineimage qeasingcurve-outquart.png
1980 \row
1981 \o \c Easing.InOutQuart
1982 \o Easing curve for a quartic (t^4) function: acceleration until halfway, then deceleration.
1983 \o \inlineimage qeasingcurve-inoutquart.png
1984 \row
1985 \o \c Easing.OutInQuart
1986 \o Easing curve for a quartic (t^4) function: deceleration until halfway, then acceleration.
1987 \o \inlineimage qeasingcurve-outinquart.png
1988 \row
1989 \o \c Easing.InQuint
1990 \o Easing curve for a quintic (t^5) function: accelerating from zero velocity.
1991 \o \inlineimage qeasingcurve-inquint.png
1992 \row
1993 \o \c Easing.OutQuint
1994 \o Easing curve for a quintic (t^5) function: decelerating from zero velocity.
1995 \o \inlineimage qeasingcurve-outquint.png
1996 \row
1997 \o \c Easing.InOutQuint
1998 \o Easing curve for a quintic (t^5) function: acceleration until halfway, then deceleration.
1999 \o \inlineimage qeasingcurve-inoutquint.png
2000 \row
2001 \o \c Easing.OutInQuint
2002 \o Easing curve for a quintic (t^5) function: deceleration until halfway, then acceleration.
2003 \o \inlineimage qeasingcurve-outinquint.png
2004 \row
2005 \o \c Easing.InSine
2006 \o Easing curve for a sinusoidal (sin(t)) function: accelerating from zero velocity.
2007 \o \inlineimage qeasingcurve-insine.png
2008 \row
2009 \o \c Easing.OutSine
2010 \o Easing curve for a sinusoidal (sin(t)) function: decelerating from zero velocity.
2011 \o \inlineimage qeasingcurve-outsine.png
2012 \row
2013 \o \c Easing.InOutSine
2014 \o Easing curve for a sinusoidal (sin(t)) function: acceleration until halfway, then deceleration.
2015 \o \inlineimage qeasingcurve-inoutsine.png
2016 \row
2017 \o \c Easing.OutInSine
2018 \o Easing curve for a sinusoidal (sin(t)) function: deceleration until halfway, then acceleration.
2019 \o \inlineimage qeasingcurve-outinsine.png
2020 \row
2021 \o \c Easing.InExpo
2022 \o Easing curve for an exponential (2^t) function: accelerating from zero velocity.
2023 \o \inlineimage qeasingcurve-inexpo.png
2024 \row
2025 \o \c Easing.OutExpo
2026 \o Easing curve for an exponential (2^t) function: decelerating from zero velocity.
2027 \o \inlineimage qeasingcurve-outexpo.png
2028 \row
2029 \o \c Easing.InOutExpo
2030 \o Easing curve for an exponential (2^t) function: acceleration until halfway, then deceleration.
2031 \o \inlineimage qeasingcurve-inoutexpo.png
2032 \row
2033 \o \c Easing.OutInExpo
2034 \o Easing curve for an exponential (2^t) function: deceleration until halfway, then acceleration.
2035 \o \inlineimage qeasingcurve-outinexpo.png
2036 \row
2037 \o \c Easing.InCirc
2038 \o Easing curve for a circular (sqrt(1-t^2)) function: accelerating from zero velocity.
2039 \o \inlineimage qeasingcurve-incirc.png
2040 \row
2041 \o \c Easing.OutCirc
2042 \o Easing curve for a circular (sqrt(1-t^2)) function: decelerating from zero velocity.
2043 \o \inlineimage qeasingcurve-outcirc.png
2044 \row
2045 \o \c Easing.InOutCirc
2046 \o Easing curve for a circular (sqrt(1-t^2)) function: acceleration until halfway, then deceleration.
2047 \o \inlineimage qeasingcurve-inoutcirc.png
2048 \row
2049 \o \c Easing.OutInCirc
2050 \o Easing curve for a circular (sqrt(1-t^2)) function: deceleration until halfway, then acceleration.
2051 \o \inlineimage qeasingcurve-outincirc.png
2052 \row
2053 \o \c Easing.InElastic
2054 \o Easing curve for an elastic (exponentially decaying sine wave) function: accelerating from zero velocity.
2055 \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
2056 \o \inlineimage qeasingcurve-inelastic.png
2057 \row
2058 \o \c Easing.OutElastic
2059 \o Easing curve for an elastic (exponentially decaying sine wave) function: decelerating from zero velocity.
2060 \br The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter.
2061 \o \inlineimage qeasingcurve-outelastic.png
2062 \row
2063 \o \c Easing.InOutElastic
2064 \o Easing curve for an elastic (exponentially decaying sine wave) function: acceleration until halfway, then deceleration.
2065 \o \inlineimage qeasingcurve-inoutelastic.png
2066 \row
2067 \o \c Easing.OutInElastic
2068 \o Easing curve for an elastic (exponentially decaying sine wave) function: deceleration until halfway, then acceleration.
2069 \o \inlineimage qeasingcurve-outinelastic.png
2070 \row
2071 \o \c Easing.InBack
2072 \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
2073 \o \inlineimage qeasingcurve-inback.png
2074 \row
2075 \o \c Easing.OutBack
2076 \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing out: decelerating to zero velocity.
2077 \o \inlineimage qeasingcurve-outback.png
2078 \row
2079 \o \c Easing.InOutBack
2080 \o Easing curve for a back (overshooting cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
2081 \o \inlineimage qeasingcurve-inoutback.png
2082 \row
2083 \o \c Easing.OutInBack
2084 \o Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
2085 \o \inlineimage qeasingcurve-outinback.png
2086 \row
2087 \o \c Easing.InBounce
2088 \o Easing curve for a bounce (exponentially decaying parabolic bounce) function: accelerating from zero velocity.
2089 \o \inlineimage qeasingcurve-inbounce.png
2090 \row
2091 \o \c Easing.OutBounce
2092 \o Easing curve for a bounce (exponentially decaying parabolic bounce) function: decelerating from zero velocity.
2093 \o \inlineimage qeasingcurve-outbounce.png
2094 \row
2095 \o \c Easing.InOutBounce
2096 \o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration.
2097 \o \inlineimage qeasingcurve-inoutbounce.png
2098 \row
2099 \o \c Easing.OutInBounce
2100 \o Easing curve for a bounce (exponentially decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration.
2101 \o \inlineimage qeasingcurve-outinbounce.png
2102 \endtable
2103
2104 \c easing.amplitude is only applicable for bounce and elastic curves (curves of type
2105 \c Easing.InBounce, \c Easing.OutBounce, \c Easing.InOutBounce, \c Easing.OutInBounce, \c Easing.InElastic,
2106 \c Easing.OutElastic, \c Easing.InOutElastic or \c Easing.OutInElastic).
2107
2108 \c easing.overshoot is only applicable if \c easing.type is: \c Easing.InBack, \c Easing.OutBack,
2109 \c Easing.InOutBack or \c Easing.OutInBack.
2110
2111 \c easing.period is only applicable if easing.type is: \c Easing.InElastic, \c Easing.OutElastic,
2112 \c Easing.InOutElastic or \c Easing.OutInElastic.
2113
2114 See the \l {declarative/animation/easing}{easing} example for a demonstration of
2115 the different easing settings.
2116*/
2117QEasingCurve QDeclarativePropertyAnimation::easing() const
2118{
2119 Q_D(const QDeclarativePropertyAnimation);
2120 return d->va->easingCurve();
2121}
2122
2123void QDeclarativePropertyAnimation::setEasing(const QEasingCurve &e)
2124{
2125 Q_D(QDeclarativePropertyAnimation);
2126 if (d->va->easingCurve() == e)
2127 return;
2128
2129 d->va->setEasingCurve(e);
2130 emit easingChanged(e);
2131}
2132
2133QObject *QDeclarativePropertyAnimation::target() const
2134{
2135 Q_D(const QDeclarativePropertyAnimation);
2136 return d->target;
2137}
2138
2139void QDeclarativePropertyAnimation::setTarget(QObject *o)
2140{
2141 Q_D(QDeclarativePropertyAnimation);
2142 if (d->target == o)
2143 return;
2144 d->target = o;
2145 emit targetChanged();
2146}
2147
2148QString QDeclarativePropertyAnimation::property() const
2149{
2150 Q_D(const QDeclarativePropertyAnimation);
2151 return d->propertyName;
2152}
2153
2154void QDeclarativePropertyAnimation::setProperty(const QString &n)
2155{
2156 Q_D(QDeclarativePropertyAnimation);
2157 if (d->propertyName == n)
2158 return;
2159 d->propertyName = n;
2160 emit propertyChanged();
2161}
2162
2163QString QDeclarativePropertyAnimation::properties() const
2164{
2165 Q_D(const QDeclarativePropertyAnimation);
2166 return d->properties;
2167}
2168
2169void QDeclarativePropertyAnimation::setProperties(const QString &prop)
2170{
2171 Q_D(QDeclarativePropertyAnimation);
2172 if (d->properties == prop)
2173 return;
2174
2175 d->properties = prop;
2176 emit propertiesChanged(prop);
2177}
2178
2179/*!
2180 \qmlproperty string PropertyAnimation::properties
2181 \qmlproperty list<Object> PropertyAnimation::targets
2182 \qmlproperty string PropertyAnimation::property
2183 \qmlproperty Object PropertyAnimation::target
2184
2185 These properties are used as a set to determine which properties should be animated.
2186 The singular and plural forms are functionally identical, e.g.
2187 \qml
2188 NumberAnimation { target: theItem; property: "x"; to: 500 }
2189 \endqml
2190 has the same meaning as
2191 \qml
2192 NumberAnimation { targets: theItem; properties: "x"; to: 500 }
2193 \endqml
2194 The singular forms are slightly optimized, so if you do have only a single target/property
2195 to animate you should try to use them.
2196
2197 The \c targets property allows multiple targets to be set. For example, this animates the
2198 \c x property of both \c itemA and \c itemB:
2199
2200 \qml
2201 NumberAnimation { targets: [itemA, itemB]; properties: "x"; to: 500 }
2202 \endqml
2203
2204 In many cases these properties do not need to be explicitly specified, as they can be
2205 inferred from the animation framework:
2206
2207 \table 80%
2208 \row
2209 \o Value Source / Behavior
2210 \o When an animation is used as a value source or in a Behavior, the default target and property
2211 name to be animated can both be inferred.
2212 \qml
2213 Rectangle {
2214 id: theRect
2215 width: 100; height: 100
2216 color: Qt.rgba(0,0,1)
2217 NumberAnimation on x { to: 500; loops: Animation.Infinite } //animate theRect's x property
2218 Behavior on y { NumberAnimation {} } //animate theRect's y property
2219 }
2220 \endqml
2221 \row
2222 \o Transition
2223 \o When used in a transition, a property animation is assumed to match \e all targets
2224 but \e no properties. In practice, that means you need to specify at least the properties
2225 in order for the animation to do anything.
2226 \qml
2227 Rectangle {
2228 id: theRect
2229 width: 100; height: 100
2230 color: Qt.rgba(0,0,1)
2231 Item { id: uselessItem }
2232 states: State {
2233 name: "state1"
2234 PropertyChanges { target: theRect; x: 200; y: 200; z: 4 }
2235 PropertyChanges { target: uselessItem; x: 10; y: 10; z: 2 }
2236 }
2237 transitions: Transition {
2238 //animate both theRect's and uselessItem's x and y to their final values
2239 NumberAnimation { properties: "x,y" }
2240
2241 //animate theRect's z to its final value
2242 NumberAnimation { target: theRect; property: "z" }
2243 }
2244 }
2245 \endqml
2246 \row
2247 \o Standalone
2248 \o When an animation is used standalone, both the target and property need to be
2249 explicitly specified.
2250 \qml
2251 Rectangle {
2252 id: theRect
2253 width: 100; height: 100
2254 color: Qt.rgba(0,0,1)
2255 //need to explicitly specify target and property
2256 NumberAnimation { id: theAnim; target: theRect; property: "x" to: 500 }
2257 MouseArea {
2258 anchors.fill: parent
2259 onClicked: theAnim.start()
2260 }
2261 }
2262 \endqml
2263 \endtable
2264
2265 As seen in the above example, properties is specified as a comma-separated string of property names to animate.
2266
2267 \sa exclude, {QML Animation}
2268*/
2269QDeclarativeListProperty<QObject> QDeclarativePropertyAnimation::targets()
2270{
2271 Q_D(QDeclarativePropertyAnimation);
2272 return QDeclarativeListProperty<QObject>(this, d->targets);
2273}
2274
2275/*!
2276 \qmlproperty list<Object> PropertyAnimation::exclude
2277 This property holds the items not to be affected by this animation.
2278 \sa PropertyAnimation::targets
2279*/
2280QDeclarativeListProperty<QObject> QDeclarativePropertyAnimation::exclude()
2281{
2282 Q_D(QDeclarativePropertyAnimation);
2283 return QDeclarativeListProperty<QObject>(this, d->exclude);
2284}
2285
2286QAbstractAnimation *QDeclarativePropertyAnimation::qtAnimation()
2287{
2288 Q_D(QDeclarativePropertyAnimation);
2289 return d->va;
2290}
2291
2292void QDeclarativeAnimationPropertyUpdater::setValue(qreal v)
2293{
2294 bool deleted = false;
2295 wasDeleted = &deleted;
2296 if (reverse) //QVariantAnimation sends us 1->0 when reversed, but we are expecting 0->1
2297 v = 1 - v;
2298 for (int ii = 0; ii < actions.count(); ++ii) {
2299 QDeclarativeAction &action = actions[ii];
2300
2301 if (v == 1.)
2302 QDeclarativePropertyPrivate::write(action.property, action.toValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
2303 else {
2304 if (!fromSourced && !fromDefined) {
2305 action.fromValue = action.property.read();
2306 if (interpolatorType)
2307 QDeclarativePropertyAnimationPrivate::convertVariant(action.fromValue, interpolatorType);
2308 }
2309 if (!interpolatorType) {
2310 int propType = action.property.propertyType();
2311 if (!prevInterpolatorType || prevInterpolatorType != propType) {
2312 prevInterpolatorType = propType;
2313 interpolator = QVariantAnimationPrivate::getInterpolator(prevInterpolatorType);
2314 }
2315 }
2316 if (interpolator)
2317 QDeclarativePropertyPrivate::write(action.property, interpolator(action.fromValue.constData(), action.toValue.constData(), v), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
2318 }
2319 if (deleted)
2320 return;
2321 }
2322 wasDeleted = 0;
2323 fromSourced = true;
2324}
2325
2326void QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions,
2327 QDeclarativeProperties &modified,
2328 TransitionDirection direction)
2329{
2330 Q_D(QDeclarativePropertyAnimation);
2331
2332 QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(','));
2333 for (int ii = 0; ii < props.count(); ++ii)
2334 props[ii] = props.at(ii).trimmed();
2335 if (!d->propertyName.isEmpty())
2336 props << d->propertyName;
2337
2338 QList<QObject*> targets = d->targets;
2339 if (d->target)
2340 targets.append(d->target);
2341
2342 bool hasSelectors = !props.isEmpty() || !targets.isEmpty() || !d->exclude.isEmpty();
2343 bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ? true : false;
2344
2345 if (d->defaultProperty.isValid() && !hasSelectors) {
2346 props << d->defaultProperty.name();
2347 targets << d->defaultProperty.object();
2348 }
2349
2350 if (props.isEmpty() && !d->defaultProperties.isEmpty()) {
2351 props << d->defaultProperties.split(QLatin1Char(','));
2352 }
2353
2354 QDeclarativeAnimationPropertyUpdater *data = new QDeclarativeAnimationPropertyUpdater;
2355 data->interpolatorType = d->interpolatorType;
2356 data->interpolator = d->interpolator;
2357 data->reverse = direction == Backward ? true : false;
2358 data->fromSourced = false;
2359 data->fromDefined = d->fromIsDefined;
2360
2361 bool hasExplicit = false;
2362 //an explicit animation has been specified
2363 if (d->toIsDefined) {
2364 for (int i = 0; i < props.count(); ++i) {
2365 for (int j = 0; j < targets.count(); ++j) {
2366 QDeclarativeAction myAction;
2367 myAction.property = d->createProperty(targets.at(j), props.at(i), this);
2368 if (myAction.property.isValid()) {
2369 if (d->fromIsDefined) {
2370 myAction.fromValue = d->from;
2371 d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
2372 }
2373 myAction.toValue = d->to;
2374 d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
2375 data->actions << myAction;
2376 hasExplicit = true;
2377 for (int ii = 0; ii < actions.count(); ++ii) {
2378 QDeclarativeAction &action = actions[ii];
2379 if (action.property.object() == myAction.property.object() &&
2380 myAction.property.name() == action.property.name()) {
2381 modified << action.property;
2382 break; //### any chance there could be multiples?
2383 }
2384 }
2385 }
2386 }
2387 }
2388 }
2389
2390 if (!hasExplicit)
2391 for (int ii = 0; ii < actions.count(); ++ii) {
2392 QDeclarativeAction &action = actions[ii];
2393
2394 QObject *obj = action.property.object();
2395 QString propertyName = action.property.name();
2396 QObject *sObj = action.specifiedObject;
2397 QString sPropertyName = action.specifiedProperty;
2398 bool same = (obj == sObj);
2399
2400 if ((targets.isEmpty() || targets.contains(obj) || (!same && targets.contains(sObj))) &&
2401 (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) &&
2402 (props.contains(propertyName) || (!same && props.contains(sPropertyName))
2403 || (useType && action.property.propertyType() == d->interpolatorType))) {
2404 QDeclarativeAction myAction = action;
2405
2406 if (d->fromIsDefined)
2407 myAction.fromValue = d->from;
2408 else
2409 myAction.fromValue = QVariant();
2410 if (d->toIsDefined)
2411 myAction.toValue = d->to;
2412
2413 d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
2414 d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType());
2415
2416 modified << action.property;
2417
2418 data->actions << myAction;
2419 action.fromValue = myAction.toValue;
2420 }
2421 }
2422
2423 if (data->actions.count()) {
2424 if (!d->rangeIsSet) {
2425 d->va->setStartValue(qreal(0));
2426 d->va->setEndValue(qreal(1));
2427 d->rangeIsSet = true;
2428 }
2429 d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
2430 d->va->setFromSourcedValue(&data->fromSourced);
2431 d->actions = &data->actions;
2432 } else {
2433 delete data;
2434 d->va->setFromSourcedValue(0); //clear previous data
2435 d->va->setAnimValue(0, QAbstractAnimation::DeleteWhenStopped); //clear previous data
2436 d->actions = 0;
2437 }
2438}
2439
2440/*!
2441 \qmlclass ParentAnimation QDeclarativeParentAnimation
2442 \ingroup qml-animation-transition
2443 \since 4.7
2444 \inherits Animation
2445 \brief The ParentAnimation element animates changes in parent values.
2446
2447 ParentAnimation is used to animate a parent change for an \l Item.
2448
2449 For example, the following ParentChange changes \c blueRect to become
2450 a child of \c redRect when it is clicked. The inclusion of the
2451 ParentAnimation, which defines a NumberAnimation to be applied during
2452 the transition, ensures the item animates smoothly as it moves to
2453 its new parent:
2454
2455 \snippet doc/src/snippets/declarative/parentanimation.qml 0
2456
2457 A ParentAnimation can contain any number of animations. These animations will
2458 be run in parallel; to run them sequentially, define them within a
2459 SequentialAnimation.
2460
2461 In some cases, such as when reparenting between items with clipping enabled, it is useful
2462 to animate the parent change via another item that does not have clipping
2463 enabled. Such an item can be set using the \l via property.
2464
2465 For convenience, when a ParentAnimation is used in a \l Transition, it will
2466 animate any ParentChange that has occurred during the state change.
2467 This can be overridden by setting a specific target item using the
2468 \l target property.
2469
2470 Like any other animation element, a ParentAnimation can be applied in a
2471 number of ways, including transitions, behaviors and property value
2472 sources. The \l {QML Animation} documentation shows a variety of methods
2473 for creating animations.
2474
2475 \sa {QML Animation}, {declarative/animation/basics}{Animation basics example}
2476*/
2477QDeclarativeParentAnimation::QDeclarativeParentAnimation(QObject *parent)
2478 : QDeclarativeAnimationGroup(*(new QDeclarativeParentAnimationPrivate), parent)
2479{
2480 Q_D(QDeclarativeParentAnimation);
2481 d->topLevelGroup = new QSequentialAnimationGroup;
2482 QDeclarative_setParent_noEvent(d->topLevelGroup, this);
2483
2484 d->startAction = new QActionAnimation;
2485 QDeclarative_setParent_noEvent(d->startAction, d->topLevelGroup);
2486 d->topLevelGroup->addAnimation(d->startAction);
2487
2488 d->ag = new QParallelAnimationGroup;
2489 QDeclarative_setParent_noEvent(d->ag, d->topLevelGroup);
2490 d->topLevelGroup->addAnimation(d->ag);
2491
2492 d->endAction = new QActionAnimation;
2493 QDeclarative_setParent_noEvent(d->endAction, d->topLevelGroup);
2494 d->topLevelGroup->addAnimation(d->endAction);
2495}
2496
2497QDeclarativeParentAnimation::~QDeclarativeParentAnimation()
2498{
2499}
2500
2501/*!
2502 \qmlproperty Item ParentAnimation::target
2503 The item to reparent.
2504
2505 When used in a transition, if no target is specified, all
2506 ParentChange occurrences are animated by the ParentAnimation.
2507*/
2508QDeclarativeItem *QDeclarativeParentAnimation::target() const
2509{
2510 Q_D(const QDeclarativeParentAnimation);
2511 return d->target;
2512}
2513
2514void QDeclarativeParentAnimation::setTarget(QDeclarativeItem *target)
2515{
2516 Q_D(QDeclarativeParentAnimation);
2517 if (target == d->target)
2518 return;
2519
2520 d->target = target;
2521 emit targetChanged();
2522}
2523
2524/*!
2525 \qmlproperty Item ParentAnimation::newParent
2526 The new parent to animate to.
2527
2528 If the ParentAnimation is defined within a \l Transition or \l Behavior,
2529 this value defaults to the value defined in the end state of the
2530 \l Transition, or the value of the property change that triggered the
2531 \l Behavior.
2532*/
2533QDeclarativeItem *QDeclarativeParentAnimation::newParent() const
2534{
2535 Q_D(const QDeclarativeParentAnimation);
2536 return d->newParent;
2537}
2538
2539void QDeclarativeParentAnimation::setNewParent(QDeclarativeItem *newParent)
2540{
2541 Q_D(QDeclarativeParentAnimation);
2542 if (newParent == d->newParent)
2543 return;
2544
2545 d->newParent = newParent;
2546 emit newParentChanged();
2547}
2548
2549/*!
2550 \qmlproperty Item ParentAnimation::via
2551 The item to reparent via. This provides a way to do an unclipped animation
2552 when both the old parent and new parent are clipped.
2553
2554 \qml
2555 ParentAnimation {
2556 target: myItem
2557 via: topLevelItem
2558 ...
2559 }
2560 \endqml
2561*/
2562QDeclarativeItem *QDeclarativeParentAnimation::via() const
2563{
2564 Q_D(const QDeclarativeParentAnimation);
2565 return d->via;
2566}
2567
2568void QDeclarativeParentAnimation::setVia(QDeclarativeItem *via)
2569{
2570 Q_D(QDeclarativeParentAnimation);
2571 if (via == d->via)
2572 return;
2573
2574 d->via = via;
2575 emit viaChanged();
2576}
2577
2578//### mirrors same-named function in QDeclarativeItem
2579QPointF QDeclarativeParentAnimationPrivate::computeTransformOrigin(QDeclarativeItem::TransformOrigin origin, qreal width, qreal height) const
2580{
2581 switch(origin) {
2582 default:
2583 case QDeclarativeItem::TopLeft:
2584 return QPointF(0, 0);
2585 case QDeclarativeItem::Top:
2586 return QPointF(width / 2., 0);
2587 case QDeclarativeItem::TopRight:
2588 return QPointF(width, 0);
2589 case QDeclarativeItem::Left:
2590 return QPointF(0, height / 2.);
2591 case QDeclarativeItem::Center:
2592 return QPointF(width / 2., height / 2.);
2593 case QDeclarativeItem::Right:
2594 return QPointF(width, height / 2.);
2595 case QDeclarativeItem::BottomLeft:
2596 return QPointF(0, height);
2597 case QDeclarativeItem::Bottom:
2598 return QPointF(width / 2., height);
2599 case QDeclarativeItem::BottomRight:
2600 return QPointF(width, height);
2601 }
2602}
2603
2604void QDeclarativeParentAnimation::transition(QDeclarativeStateActions &actions,
2605 QDeclarativeProperties &modified,
2606 TransitionDirection direction)
2607{
2608 Q_D(QDeclarativeParentAnimation);
2609
2610 struct QDeclarativeParentAnimationData : public QAbstractAnimationAction
2611 {
2612 QDeclarativeParentAnimationData() {}
2613 ~QDeclarativeParentAnimationData() { qDeleteAll(pc); }
2614
2615 QDeclarativeStateActions actions;
2616 //### reverse should probably apply on a per-action basis
2617 bool reverse;
2618 QList<QDeclarativeParentChange *> pc;
2619 virtual void doAction()
2620 {
2621 for (int ii = 0; ii < actions.count(); ++ii) {
2622 const QDeclarativeAction &action = actions.at(ii);
2623 if (reverse)
2624 action.event->reverse();
2625 else
2626 action.event->execute();
2627 }
2628 }
2629 };
2630
2631 QDeclarativeParentAnimationData *data = new QDeclarativeParentAnimationData;
2632 QDeclarativeParentAnimationData *viaData = new QDeclarativeParentAnimationData;
2633
2634 bool hasExplicit = false;
2635 if (d->target && d->newParent) {
2636 data->reverse = false;
2637 QDeclarativeAction myAction;
2638 QDeclarativeParentChange *pc = new QDeclarativeParentChange;
2639 pc->setObject(d->target);
2640 pc->setParent(d->newParent);
2641 myAction.event = pc;
2642 data->pc << pc;
2643 data->actions << myAction;
2644 hasExplicit = true;
2645 if (d->via) {
2646 viaData->reverse = false;
2647 QDeclarativeAction myVAction;
2648 QDeclarativeParentChange *vpc = new QDeclarativeParentChange;
2649 vpc->setObject(d->target);
2650 vpc->setParent(d->via);
2651 myVAction.event = vpc;
2652 viaData->pc << vpc;
2653 viaData->actions << myVAction;
2654 }
2655 //### once actions have concept of modified,
2656 // loop to match appropriate ParentChanges and mark as modified
2657 }
2658
2659 if (!hasExplicit)
2660 for (int i = 0; i < actions.size(); ++i) {
2661 QDeclarativeAction &action = actions[i];
2662 if (action.event && action.event->typeName() == QLatin1String("ParentChange")
2663 && (!d->target || static_cast<QDeclarativeParentChange*>(action.event)->object() == d->target)) {
2664
2665 QDeclarativeParentChange *pc = static_cast<QDeclarativeParentChange*>(action.event);
2666 QDeclarativeAction myAction = action;
2667 data->reverse = action.reverseEvent;
2668
2669 //### this logic differs from PropertyAnimation
2670 // (probably a result of modified vs. done)
2671 if (d->newParent) {
2672 QDeclarativeParentChange *epc = new QDeclarativeParentChange;
2673 epc->setObject(static_cast<QDeclarativeParentChange*>(action.event)->object());
2674 epc->setParent(d->newParent);
2675 myAction.event = epc;
2676 data->pc << epc;
2677 data->actions << myAction;
2678 pc = epc;
2679 } else {
2680 action.actionDone = true;
2681 data->actions << myAction;
2682 }
2683
2684 if (d->via) {
2685 viaData->reverse = false;
2686 QDeclarativeAction myAction;
2687 QDeclarativeParentChange *vpc = new QDeclarativeParentChange;
2688 vpc->setObject(pc->object());
2689 vpc->setParent(d->via);
2690 myAction.event = vpc;
2691 viaData->pc << vpc;
2692 viaData->actions << myAction;
2693 QDeclarativeAction dummyAction;
2694 QDeclarativeAction &xAction = pc->xIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
2695 QDeclarativeAction &yAction = pc->yIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
2696 QDeclarativeAction &sAction = pc->scaleIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
2697 QDeclarativeAction &rAction = pc->rotationIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction;
2698 QDeclarativeItem *target = pc->object();
2699 QDeclarativeItem *targetParent = action.reverseEvent ? pc->originalParent() : pc->parent();
2700
2701 //### this mirrors the logic in QDeclarativeParentChange.
2702 bool ok;
2703 const QTransform &transform = targetParent->itemTransform(d->via, &ok);
2704 if (transform.type() >= QTransform::TxShear || !ok) {
2705 qmlInfo(this) << QDeclarativeParentAnimation::tr("Unable to preserve appearance under complex transform");
2706 ok = false;
2707 }
2708
2709 qreal scale = 1;
2710 qreal rotation = 0;
2711 bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0);
2712 if (ok && !isRotate) {
2713 if (transform.m11() == transform.m22())
2714 scale = transform.m11();
2715 else {
2716 qmlInfo(this) << QDeclarativeParentAnimation::tr("Unable to preserve appearance under non-uniform scale");
2717 ok = false;
2718 }
2719 } else if (ok && isRotate) {
2720 if (transform.m11() == transform.m22())
2721 scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12());
2722 else {
2723 qmlInfo(this) << QDeclarativeParentAnimation::tr("Unable to preserve appearance under non-uniform scale");
2724 ok = false;
2725 }
2726
2727 if (scale != 0)
2728 rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI;
2729 else {
2730 qmlInfo(this) << QDeclarativeParentAnimation::tr("Unable to preserve appearance under scale of 0");
2731 ok = false;
2732 }
2733 }
2734
2735 const QPointF &point = transform.map(QPointF(xAction.toValue.toReal(),yAction.toValue.toReal()));
2736 qreal x = point.x();
2737 qreal y = point.y();
2738 if (ok && target->transformOrigin() != QDeclarativeItem::TopLeft) {
2739 qreal w = target->width();
2740 qreal h = target->height();
2741 if (pc->widthIsSet() && i < actions.size() - 1)
2742 w = actions[++i].toValue.toReal();
2743 if (pc->heightIsSet() && i < actions.size() - 1)
2744 h = actions[++i].toValue.toReal();
2745 const QPointF &transformOrigin
2746 = d->computeTransformOrigin(target->transformOrigin(), w,h);
2747 qreal tempxt = transformOrigin.x();
2748 qreal tempyt = transformOrigin.y();
2749 QTransform t;
2750 t.translate(-tempxt, -tempyt);
2751 t.rotate(rotation);
2752 t.scale(scale, scale);
2753 t.translate(tempxt, tempyt);
2754 const QPointF &offset = t.map(QPointF(0,0));
2755 x += offset.x();
2756 y += offset.y();
2757 }
2758
2759 if (ok) {
2760 //qDebug() << x << y << rotation << scale;
2761 xAction.toValue = x;
2762 yAction.toValue = y;
2763 sAction.toValue = sAction.toValue.toReal() * scale;
2764 rAction.toValue = rAction.toValue.toReal() + rotation;
2765 }
2766 }
2767 }
2768 }
2769
2770 if (data->actions.count()) {
2771 if (direction == QDeclarativeAbstractAnimation::Forward) {
2772 d->startAction->setAnimAction(d->via ? viaData : data, QActionAnimation::DeleteWhenStopped);
2773 d->endAction->setAnimAction(d->via ? data : 0, QActionAnimation::DeleteWhenStopped);
2774 } else {
2775 d->endAction->setAnimAction(d->via ? viaData : data, QActionAnimation::DeleteWhenStopped);
2776 d->startAction->setAnimAction(d->via ? data : 0, QActionAnimation::DeleteWhenStopped);
2777 }
2778 } else {
2779 delete data;
2780 delete viaData;
2781 }
2782
2783 //take care of any child animations
2784 bool valid = d->defaultProperty.isValid();
2785 for (int ii = 0; ii < d->animations.count(); ++ii) {
2786 if (valid)
2787 d->animations.at(ii)->setDefaultTarget(d->defaultProperty);
2788 d->animations.at(ii)->transition(actions, modified, direction);
2789 }
2790
2791}
2792
2793QAbstractAnimation *QDeclarativeParentAnimation::qtAnimation()
2794{
2795 Q_D(QDeclarativeParentAnimation);
2796 return d->topLevelGroup;
2797}
2798
2799/*!
2800 \qmlclass AnchorAnimation QDeclarativeAnchorAnimation
2801 \ingroup qml-animation-transition
2802 \since 4.7
2803 \inherits Animation
2804 \brief The AnchorAnimation element animates changes in anchor values.
2805
2806 AnchorAnimation is used to animate an anchor change.
2807
2808 In the following snippet we animate the addition of a right anchor to a \l Rectangle:
2809
2810 \snippet doc/src/snippets/declarative/anchoranimation.qml 0
2811
2812 For convenience, when an AnchorAnimation is used in a \l Transition, it will
2813 animate any AnchorChanges that have occurred during the state change.
2814 This can be overridden by setting a specific target item using the
2815 \l target property.
2816
2817 Like any other animation element, an AnchorAnimation can be applied in a
2818 number of ways, including transitions, behaviors and property value
2819 sources. The \l {QML Animation} documentation shows a variety of methods
2820 for creating animations.
2821
2822 \sa {QML Animation}, AnchorChanges
2823*/
2824
2825QDeclarativeAnchorAnimation::QDeclarativeAnchorAnimation(QObject *parent)
2826: QDeclarativeAbstractAnimation(*(new QDeclarativeAnchorAnimationPrivate), parent)
2827{
2828 Q_D(QDeclarativeAnchorAnimation);
2829 d->va = new QDeclarativeBulkValueAnimator;
2830 QDeclarative_setParent_noEvent(d->va, this);
2831}
2832
2833QDeclarativeAnchorAnimation::~QDeclarativeAnchorAnimation()
2834{
2835}
2836
2837QAbstractAnimation *QDeclarativeAnchorAnimation::qtAnimation()
2838{
2839 Q_D(QDeclarativeAnchorAnimation);
2840 return d->va;
2841}
2842
2843/*!
2844 \qmlproperty list<Item> AnchorAnimation::targets
2845 The items to reanchor.
2846
2847 If no targets are specified all AnchorChanges will be
2848 animated by the AnchorAnimation.
2849*/
2850QDeclarativeListProperty<QDeclarativeItem> QDeclarativeAnchorAnimation::targets()
2851{
2852 Q_D(QDeclarativeAnchorAnimation);
2853 return QDeclarativeListProperty<QDeclarativeItem>(this, d->targets);
2854}
2855
2856/*!
2857 \qmlproperty int AnchorAnimation::duration
2858 This property holds the duration of the animation, in milliseconds.
2859
2860 The default value is 250.
2861*/
2862int QDeclarativeAnchorAnimation::duration() const
2863{
2864 Q_D(const QDeclarativeAnchorAnimation);
2865 return d->va->duration();
2866}
2867
2868void QDeclarativeAnchorAnimation::setDuration(int duration)
2869{
2870 if (duration < 0) {
2871 qmlInfo(this) << tr("Cannot set a duration of < 0");
2872 return;
2873 }
2874
2875 Q_D(QDeclarativeAnchorAnimation);
2876 if (d->va->duration() == duration)
2877 return;
2878 d->va->setDuration(duration);
2879 emit durationChanged(duration);
2880}
2881
2882/*!
2883 \qmlproperty enumeration AnchorAnimation::easing.type
2884 \qmlproperty real AnchorAnimation::easing.amplitude
2885 \qmlproperty real AnchorAnimation::easing.overshoot
2886 \qmlproperty real AnchorAnimation::easing.period
2887 \brief the easing curve used for the animation.
2888
2889 To specify an easing curve you need to specify at least the type. For some curves you can also specify
2890 amplitude, period and/or overshoot. The default easing curve is
2891 Linear.
2892
2893 \qml
2894 AnchorAnimation { easing.type: Easing.InOutQuad }
2895 \endqml
2896
2897 See the \l{PropertyAnimation::easing.type} documentation for information
2898 about the different types of easing curves.
2899*/
2900
2901QEasingCurve QDeclarativeAnchorAnimation::easing() const
2902{
2903 Q_D(const QDeclarativeAnchorAnimation);
2904 return d->va->easingCurve();
2905}
2906
2907void QDeclarativeAnchorAnimation::setEasing(const QEasingCurve &e)
2908{
2909 Q_D(QDeclarativeAnchorAnimation);
2910 if (d->va->easingCurve() == e)
2911 return;
2912
2913 d->va->setEasingCurve(e);
2914 emit easingChanged(e);
2915}
2916
2917void QDeclarativeAnchorAnimation::transition(QDeclarativeStateActions &actions,
2918 QDeclarativeProperties &modified,
2919 TransitionDirection direction)
2920{
2921 Q_UNUSED(modified);
2922 Q_D(QDeclarativeAnchorAnimation);
2923 QDeclarativeAnimationPropertyUpdater *data = new QDeclarativeAnimationPropertyUpdater;
2924 data->interpolatorType = QMetaType::QReal;
2925 data->interpolator = d->interpolator;
2926
2927 data->reverse = direction == Backward ? true : false;
2928 data->fromSourced = false;
2929 data->fromDefined = false;
2930
2931 for (int ii = 0; ii < actions.count(); ++ii) {
2932 QDeclarativeAction &action = actions[ii];
2933 if (action.event && action.event->typeName() == QLatin1String("AnchorChanges")
2934 && (d->targets.isEmpty() || d->targets.contains(static_cast<QDeclarativeAnchorChanges*>(action.event)->object()))) {
2935 data->actions << static_cast<QDeclarativeAnchorChanges*>(action.event)->additionalActions();
2936 }
2937 }
2938
2939 if (data->actions.count()) {
2940 if (!d->rangeIsSet) {
2941 d->va->setStartValue(qreal(0));
2942 d->va->setEndValue(qreal(1));
2943 d->rangeIsSet = true;
2944 }
2945 d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
2946 d->va->setFromSourcedValue(&data->fromSourced);
2947 } else {
2948 delete data;
2949 }
2950}
2951
2952QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.