Doc: Moving Qt Quick docs for new doc structure
[profile/ivi/qtdeclarative.git] / src / quick / util / qquicktransition.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquicktransition_p.h"
43
44 #include "qquickstate_p.h"
45 #include "qquickstate_p_p.h"
46 #include "qquickstatechangescript_p.h"
47 #include "qquickanimation_p.h"
48 #include "qquickanimation_p_p.h"
49 #include "qquicktransitionmanager_p_p.h"
50
51 #include "private/qparallelanimationgroupjob_p.h"
52
53 QT_BEGIN_NAMESPACE
54
55 /*!
56     \qmlclass Transition QQuickTransition
57     \inqmlmodule QtQuick 2
58     \ingroup qml-animation-transition
59     \brief The Transition element defines animated transitions that occur on state changes.
60
61     A Transition defines the animations to be applied when a \l State change occurs.
62
63     For example, the following \l Rectangle has two states: the default state, and
64     an added "moved" state. In the "moved state, the rectangle's position changes
65     to (50, 50).  The added Transition specifies that when the rectangle
66     changes between the default and the "moved" state, any changes
67     to the \c x and \c y properties should be animated, using an \c Easing.InOutQuad.
68
69     \snippet doc/snippets/qml/transition.qml 0
70
71     Notice the example does not require \l{PropertyAnimation::}{to} and
72     \l{PropertyAnimation::}{from} values for the NumberAnimation. As a convenience,
73     these properties are automatically set to the values of \c x and \c y before
74     and after the state change; the \c from values are provided by
75     the current values of \c x and \c y, and the \c to values are provided by
76     the PropertyChanges object. If you wish, you can provide \l{PropertyAnimation::}{to} and
77     \l{PropertyAnimation::}{from} values anyway to override the default values.
78
79     By default, a Transition's animations are applied for any state change in the
80     parent item. The  Transition \l {Transition::}{from} and \l {Transition::}{to}
81     values can be set to restrict the animations to only be applied when changing
82     from one particular state to another.
83
84     To define multiple transitions, specify \l Item::transitions as a list:
85
86     \snippet doc/snippets/qml/transitions-list.qml list of transitions
87
88     If multiple Transitions are specified, only a single (best-matching) Transition will be applied for any particular
89     state change. In the example above, when changing to \c state1, the first transition will be used, rather
90     than the more generic second transition.
91
92     If a state change has a Transition that matches the same property as a
93     \l Behavior, the Transition animation overrides the \l Behavior for that
94     state change.
95
96     \sa {QML Animation and Transitions}, {declarative/animation/states}{states example}, {qmlstates}{States}, {QtQml}
97 */
98
99 //ParallelAnimationWrapper allows us to do a "callback" when the animation finishes, rather than connecting
100 //and disconnecting signals and slots frequently
101 class ParallelAnimationWrapper : public QParallelAnimationGroupJob
102 {
103 public:
104     ParallelAnimationWrapper() : QParallelAnimationGroupJob() {}
105     QQuickTransitionManager *manager;
106
107 protected:
108     virtual void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
109 };
110
111 class QQuickTransitionPrivate : public QObjectPrivate, QAnimationJobChangeListener
112 {
113     Q_DECLARE_PUBLIC(QQuickTransition)
114 public:
115     QQuickTransitionPrivate()
116     : fromState(QLatin1String("*")), toState(QLatin1String("*"))
117     , runningInstanceCount(0), state(QAbstractAnimationJob::Stopped)
118     , reversed(false), reversible(false), enabled(true)
119     {
120     }
121
122     void removeStateChangeListener(QAbstractAnimationJob *anim)
123     {
124         if (anim)
125             anim->removeAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
126     }
127
128     QString fromState;
129     QString toState;
130     quint32 runningInstanceCount;
131     QAbstractAnimationJob::State state;
132     bool reversed;
133     bool reversible;
134     bool enabled;
135 protected:
136     virtual void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State);
137
138     static void append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a);
139     static int animation_count(QQmlListProperty<QQuickAbstractAnimation> *list);
140     static QQuickAbstractAnimation* animation_at(QQmlListProperty<QQuickAbstractAnimation> *list, int pos);
141     static void clear_animations(QQmlListProperty<QQuickAbstractAnimation> *list);
142     QList<QQuickAbstractAnimation *> animations;
143 };
144
145 void QQuickTransitionPrivate::append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a)
146 {
147     QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
148     q->d_func()->animations.append(a);
149     a->setDisableUserControl();
150 }
151
152 int QQuickTransitionPrivate::animation_count(QQmlListProperty<QQuickAbstractAnimation> *list)
153 {
154     QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
155     return q->d_func()->animations.count();
156 }
157
158 QQuickAbstractAnimation* QQuickTransitionPrivate::animation_at(QQmlListProperty<QQuickAbstractAnimation> *list, int pos)
159 {
160     QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
161     return q->d_func()->animations.at(pos);
162 }
163
164 void QQuickTransitionPrivate::clear_animations(QQmlListProperty<QQuickAbstractAnimation> *list)
165 {
166     QQuickTransition *q = static_cast<QQuickTransition *>(list->object);
167     while (q->d_func()->animations.count()) {
168         QQuickAbstractAnimation *firstAnim = q->d_func()->animations.at(0);
169         q->d_func()->animations.removeAll(firstAnim);
170     }
171 }
172
173 void QQuickTransitionPrivate::animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
174 {
175     Q_Q(QQuickTransition);
176
177     if (newState == QAbstractAnimationJob::Running) {
178         if (!runningInstanceCount)
179             emit q->runningChanged();
180         runningInstanceCount++;
181     } else if (newState == QAbstractAnimationJob::Stopped) {
182         runningInstanceCount--;
183         if (!runningInstanceCount)
184             emit q->runningChanged();
185     }
186 }
187
188 void ParallelAnimationWrapper::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState)
189 {
190     QParallelAnimationGroupJob::updateState(newState, oldState);
191     if (newState == Stopped && (duration() == -1
192         || (direction() == QAbstractAnimationJob::Forward && currentLoopTime() == duration())
193         || (direction() == QAbstractAnimationJob::Backward && currentLoopTime() == 0)))
194     {
195          manager->complete();
196     }
197 }
198
199 QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim)
200     : m_transition(transition)
201     , m_anim(anim)
202 {
203 }
204
205 QQuickTransitionInstance::~QQuickTransitionInstance()
206 {
207     m_transition->removeStateChangeListener(m_anim);
208     delete m_anim;
209 }
210
211 void QQuickTransitionInstance::start()
212 {
213     if (m_anim)
214         m_anim->start();
215 }
216
217 void QQuickTransitionInstance::stop()
218 {
219     if (m_anim)
220         m_anim->stop();
221 }
222
223 bool QQuickTransitionInstance::isRunning() const
224 {
225     return m_anim && m_anim->state() == QAbstractAnimationJob::Running;
226 }
227
228 QQuickTransition::QQuickTransition(QObject *parent)
229     : QObject(*(new QQuickTransitionPrivate), parent)
230 {
231 }
232
233 QQuickTransition::~QQuickTransition()
234 {
235 }
236
237 void QQuickTransition::setReversed(bool r)
238 {
239     Q_D(QQuickTransition);
240     d->reversed = r;
241 }
242
243 QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::ActionList &actions,
244                             QList<QQmlProperty> &after,
245                             QQuickTransitionManager *manager,
246                             QObject *defaultTarget)
247 {
248     Q_D(QQuickTransition);
249
250     qmlExecuteDeferred(this);
251
252     ParallelAnimationWrapper *group = new ParallelAnimationWrapper();
253     group->manager = manager;
254
255     QQuickAbstractAnimation::TransitionDirection direction = d->reversed ? QQuickAbstractAnimation::Backward : QQuickAbstractAnimation::Forward;
256     int start = d->reversed ? d->animations.count() - 1 : 0;
257     int end = d->reversed ? -1 : d->animations.count();
258
259     QAbstractAnimationJob *anim = 0;
260     for (int i = start; i != end;) {
261         anim = d->animations.at(i)->transition(actions, after, direction, defaultTarget);
262         if (anim)
263             d->reversed ? group->prependAnimation(anim) : group->appendAnimation(anim);
264         d->reversed ? --i : ++i;
265     }
266
267     group->setDirection(d->reversed ? QAbstractAnimationJob::Backward : QAbstractAnimationJob::Forward);
268
269     group->addAnimationChangeListener(d, QAbstractAnimationJob::StateChange);
270     QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(d, group);
271     return wrapper;
272 }
273
274 /*!
275     \qmlproperty string QtQuick2::Transition::from
276     \qmlproperty string QtQuick2::Transition::to
277
278     These properties indicate the state changes that trigger the transition.
279
280     The default values for these properties is "*" (that is, any state).
281
282     For example, the following transition has not set the \c to and \c from
283     properties, so the animation is always applied when changing between
284     the two states (i.e. when the mouse is pressed and released).
285
286     \snippet doc/snippets/qml/transition-from-to.qml 0
287
288     If the transition was changed to this:
289
290     \snippet doc/snippets/qml/transition-from-to-modified.qml modified transition
291
292     The animation would only be applied when changing from the default state to
293     the "brighter" state (i.e. when the mouse is pressed, but not on release).
294
295     Multiple \c to and \from values can be set by using a comma-separated string.
296
297     \sa reversible
298 */
299 QString QQuickTransition::fromState() const
300 {
301     Q_D(const QQuickTransition);
302     return d->fromState;
303 }
304
305 void QQuickTransition::setFromState(const QString &f)
306 {
307     Q_D(QQuickTransition);
308     if (f == d->fromState)
309         return;
310
311     d->fromState = f;
312     emit fromChanged();
313 }
314
315 /*!
316     \qmlproperty bool QtQuick2::Transition::reversible
317     This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
318
319     The default value is false.
320
321     By default, transitions run in parallel and are applied to all state
322     changes if the \l from and \l to states have not been set. In this
323     situation, the transition is automatically applied when a state change
324     is reversed, and it is not necessary to set this property to reverse
325     the transition.
326
327     However, if a SequentialAnimation is used, or if the \l from or \l to
328     properties have been set, this property will need to be set to reverse
329     a transition when a state change is reverted. For example, the following
330     transition applies a sequential animation when the mouse is pressed,
331     and reverses the sequence of the animation when the mouse is released:
332
333     \snippet doc/snippets/qml/transition-reversible.qml 0
334
335     If the transition did not set the \c to and \c reversible values, then
336     on the mouse release, the transition would play the PropertyAnimation
337     before the ColorAnimation instead of reversing the sequence.
338 */
339 bool QQuickTransition::reversible() const
340 {
341     Q_D(const QQuickTransition);
342     return d->reversible;
343 }
344
345 void QQuickTransition::setReversible(bool r)
346 {
347     Q_D(QQuickTransition);
348     if (r == d->reversible)
349         return;
350
351     d->reversible = r;
352     emit reversibleChanged();
353 }
354
355 QString QQuickTransition::toState() const
356 {
357     Q_D(const QQuickTransition);
358     return d->toState;
359 }
360
361 void QQuickTransition::setToState(const QString &t)
362 {
363     Q_D(QQuickTransition);
364     if (t == d->toState)
365         return;
366
367     d->toState = t;
368     emit toChanged();
369 }
370
371 /*!
372     \qmlproperty bool QtQuick2::Transition::enabled
373
374     This property holds whether the Transition will be run when moving
375     from the \c from state to the \c to state.
376
377     By default a Transition is enabled.
378
379     Note that in some circumstances disabling a Transition may cause an
380     alternative Transition to be used in its place. In the following
381     example, the generic Transition will be used to animate the change
382     from \c state1 to \c state2, as the more specific Transition has
383     been disabled.
384
385     \qml
386     Item {
387         states: [
388             State { name: "state1" ... }
389             State { name: "state2" ... }
390         ]
391         transitions: [
392             Transition { from: "state1"; to: "state2"; enabled: false ... }
393             Transition { ... }
394         ]
395     }
396     \endqml
397 */
398
399 bool QQuickTransition::enabled() const
400 {
401     Q_D(const QQuickTransition);
402     return d->enabled;
403 }
404
405 void QQuickTransition::setEnabled(bool enabled)
406 {
407     Q_D(QQuickTransition);
408     if (d->enabled == enabled)
409         return;
410     d->enabled = enabled;
411     emit enabledChanged();
412 }
413
414 /*!
415     \qmlproperty bool QtQuick2::Transition::running
416
417     This property holds whether the transition is currently running.
418
419     This property is read only.
420 */
421 bool QQuickTransition::running() const
422 {
423     Q_D(const QQuickTransition);
424     return d->runningInstanceCount;
425 }
426
427
428 /*!
429     \qmlproperty list<Animation> QtQuick2::Transition::animations
430     \default
431
432     This property holds a list of the animations to be run for this transition.
433
434     \snippet examples/declarative/toys/dynamicscene/dynamicscene.qml top-level transitions
435
436     The top-level animations are run in parallel. To run them sequentially,
437     define them within a SequentialAnimation:
438
439     \snippet doc/snippets/qml/transition-reversible.qml sequential animations
440 */
441 QQmlListProperty<QQuickAbstractAnimation> QQuickTransition::animations()
442 {
443     Q_D(QQuickTransition);
444     return QQmlListProperty<QQuickAbstractAnimation>(this, &d->animations, QQuickTransitionPrivate::append_animation,
445                                                                    QQuickTransitionPrivate::animation_count,
446                                                                    QQuickTransitionPrivate::animation_at,
447                                                                    QQuickTransitionPrivate::clear_animations);
448 }
449
450 QT_END_NAMESPACE
451
452 //#include <qquicktransition.moc>