Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / quick / util / qdeclarativetransition.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 QtDeclarative 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 "qdeclarativetransition_p.h"
43
44 #include "qdeclarativestate_p.h"
45 #include "qdeclarativestate_p_p.h"
46 #include "qdeclarativestateoperations_p.h"
47 #include "qdeclarativeanimation_p.h"
48 #include "qdeclarativeanimation_p_p.h"
49 #include "qdeclarativetransitionmanager_p_p.h"
50
51 #include <QParallelAnimationGroup>
52
53 QT_BEGIN_NAMESPACE
54
55 /*!
56     \qmlclass Transition QDeclarativeTransition
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/src/snippets/declarative/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/src/snippets/declarative/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}, {QtDeclarative}
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 QParallelAnimationGroup
102 {
103     Q_OBJECT
104 public:
105     ParallelAnimationWrapper(QObject *parent = 0) : QParallelAnimationGroup(parent) {}
106     QDeclarativeTransitionPrivate *trans;
107 protected:
108     virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
109 };
110
111 class QDeclarativeTransitionPrivate : public QObjectPrivate
112 {
113     Q_DECLARE_PUBLIC(QDeclarativeTransition)
114 public:
115     QDeclarativeTransitionPrivate()
116     : fromState(QLatin1String("*")), toState(QLatin1String("*")),
117       reversed(false), reversible(false), enabled(true), manager(0)
118     {
119         group.trans = this;
120     }
121
122     QString fromState;
123     QString toState;
124     bool reversed;
125     bool reversible;
126     bool enabled;
127     ParallelAnimationWrapper group;
128     QDeclarativeTransitionManager *manager;
129
130     void complete()
131     {
132         manager->complete();
133     }
134     static void append_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, QDeclarativeAbstractAnimation *a);
135     static int animation_count(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list);
136     static QDeclarativeAbstractAnimation* animation_at(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, int pos);
137     static void clear_animations(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list);
138     QList<QDeclarativeAbstractAnimation *> animations;
139 };
140
141 void QDeclarativeTransitionPrivate::append_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, QDeclarativeAbstractAnimation *a)
142 {
143     QDeclarativeTransition *q = static_cast<QDeclarativeTransition *>(list->object);
144     q->d_func()->animations.append(a);
145     q->d_func()->group.addAnimation(a->qtAnimation());
146     a->setDisableUserControl();
147 }
148
149 int QDeclarativeTransitionPrivate::animation_count(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list)
150 {
151     QDeclarativeTransition *q = static_cast<QDeclarativeTransition *>(list->object);
152     return q->d_func()->animations.count();
153 }
154
155 QDeclarativeAbstractAnimation* QDeclarativeTransitionPrivate::animation_at(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, int pos)
156 {
157     QDeclarativeTransition *q = static_cast<QDeclarativeTransition *>(list->object);
158     return q->d_func()->animations.at(pos);
159 }
160
161 void QDeclarativeTransitionPrivate::clear_animations(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list)
162 {
163     QDeclarativeTransition *q = static_cast<QDeclarativeTransition *>(list->object);
164     while (q->d_func()->animations.count()) {
165         QDeclarativeAbstractAnimation *firstAnim = q->d_func()->animations.at(0);
166         q->d_func()->group.removeAnimation(firstAnim->qtAnimation());
167         q->d_func()->animations.removeAll(firstAnim);
168     }
169 }
170
171 void ParallelAnimationWrapper::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
172 {
173     QParallelAnimationGroup::updateState(newState, oldState);
174     if (newState == Stopped && (duration() == -1
175         || (direction() == QAbstractAnimation::Forward && currentLoopTime() == duration())
176         || (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0)))
177     {
178         trans->complete();
179     }
180 }
181
182
183
184 QDeclarativeTransition::QDeclarativeTransition(QObject *parent)
185     : QObject(*(new QDeclarativeTransitionPrivate), parent)
186 {
187 }
188
189 QDeclarativeTransition::~QDeclarativeTransition()
190 {
191 }
192
193 void QDeclarativeTransition::stop()
194 {
195     Q_D(QDeclarativeTransition);
196     d->group.stop();
197 }
198
199 void QDeclarativeTransition::setReversed(bool r)
200 {
201     Q_D(QDeclarativeTransition);
202     d->reversed = r;
203 }
204
205 void QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &actions,
206                             QList<QDeclarativeProperty> &after,
207                             QDeclarativeTransitionManager *manager)
208 {
209     Q_D(QDeclarativeTransition);
210
211     qmlExecuteDeferred(this);
212
213     if (d->reversed) {
214         for (int ii = d->animations.count() - 1; ii >= 0; --ii) {
215             d->animations.at(ii)->transition(actions, after, QDeclarativeAbstractAnimation::Backward);
216         }
217     } else {
218         for (int ii = 0; ii < d->animations.count(); ++ii) {
219             d->animations.at(ii)->transition(actions, after, QDeclarativeAbstractAnimation::Forward);
220         }
221     }
222
223     d->manager = manager;
224     d->group.setDirection(d->reversed ? QAbstractAnimation::Backward : QAbstractAnimation::Forward);
225     d->group.start();
226 }
227
228 /*!
229     \qmlproperty string QtQuick2::Transition::from
230     \qmlproperty string QtQuick2::Transition::to
231
232     These properties indicate the state changes that trigger the transition.
233
234     The default values for these properties is "*" (that is, any state).
235
236     For example, the following transition has not set the \c to and \c from
237     properties, so the animation is always applied when changing between
238     the two states (i.e. when the mouse is pressed and released).
239
240     \snippet doc/src/snippets/declarative/transition-from-to.qml 0
241
242     If the transition was changed to this:
243
244     \snippet doc/src/snippets/declarative/transition-from-to-modified.qml modified transition
245
246     The animation would only be applied when changing from the default state to
247     the "brighter" state (i.e. when the mouse is pressed, but not on release).
248
249     Multiple \c to and \from values can be set by using a comma-separated string.
250
251     \sa reversible
252 */
253 QString QDeclarativeTransition::fromState() const
254 {
255     Q_D(const QDeclarativeTransition);
256     return d->fromState;
257 }
258
259 void QDeclarativeTransition::setFromState(const QString &f)
260 {
261     Q_D(QDeclarativeTransition);
262     if (f == d->fromState)
263         return;
264
265     d->fromState = f;
266     emit fromChanged();
267 }
268
269 /*!
270     \qmlproperty bool QtQuick2::Transition::reversible
271     This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
272
273     The default value is false.
274
275     By default, transitions run in parallel and are applied to all state
276     changes if the \l from and \l to states have not been set. In this
277     situation, the transition is automatically applied when a state change
278     is reversed, and it is not necessary to set this property to reverse
279     the transition.
280
281     However, if a SequentialAnimation is used, or if the \l from or \l to
282     properties have been set, this property will need to be set to reverse
283     a transition when a state change is reverted. For example, the following
284     transition applies a sequential animation when the mouse is pressed,
285     and reverses the sequence of the animation when the mouse is released:
286
287     \snippet doc/src/snippets/declarative/transition-reversible.qml 0
288
289     If the transition did not set the \c to and \c reversible values, then
290     on the mouse release, the transition would play the PropertyAnimation
291     before the ColorAnimation instead of reversing the sequence.
292 */
293 bool QDeclarativeTransition::reversible() const
294 {
295     Q_D(const QDeclarativeTransition);
296     return d->reversible;
297 }
298
299 void QDeclarativeTransition::setReversible(bool r)
300 {
301     Q_D(QDeclarativeTransition);
302     if (r == d->reversible)
303         return;
304
305     d->reversible = r;
306     emit reversibleChanged();
307 }
308
309 QString QDeclarativeTransition::toState() const
310 {
311     Q_D(const QDeclarativeTransition);
312     return d->toState;
313 }
314
315 void QDeclarativeTransition::setToState(const QString &t)
316 {
317     Q_D(QDeclarativeTransition);
318     if (t == d->toState)
319         return;
320
321     d->toState = t;
322     emit toChanged();
323 }
324
325 /*!
326     \qmlproperty bool QtQuick2::Transition::enabled
327
328     This property holds whether the Transition will be run when moving
329     from the \c from state to the \c to state.
330
331     By default a Transition is enabled.
332
333     Note that in some circumstances disabling a Transition may cause an
334     alternative Transition to be used in its place. In the following
335     example, the generic Transition will be used to animate the change
336     from \c state1 to \c state2, as the more specific Transition has
337     been disabled.
338
339     \qml
340     Item {
341         states: [
342             State { name: "state1" ... }
343             State { name: "state2" ... }
344         ]
345         transitions: [
346             Transition { from: "state1"; to: "state2"; enabled: false ... }
347             Transition { ... }
348         ]
349     }
350     \endqml
351 */
352
353 bool QDeclarativeTransition::enabled() const
354 {
355     Q_D(const QDeclarativeTransition);
356     return d->enabled;
357 }
358
359 void QDeclarativeTransition::setEnabled(bool enabled)
360 {
361     Q_D(QDeclarativeTransition);
362     if (d->enabled == enabled)
363         return;
364     d->enabled = enabled;
365     emit enabledChanged();
366 }
367
368 /*!
369     \qmlproperty list<Animation> QtQuick2::Transition::animations
370     \default
371
372     This property holds a list of the animations to be run for this transition.
373
374     \snippet examples/declarative/toys/dynamicscene/dynamicscene.qml top-level transitions
375
376     The top-level animations are run in parallel. To run them sequentially,
377     define them within a SequentialAnimation:
378
379     \snippet doc/src/snippets/declarative/transition-reversible.qml sequential animations
380 */
381 QDeclarativeListProperty<QDeclarativeAbstractAnimation> QDeclarativeTransition::animations()
382 {
383     Q_D(QDeclarativeTransition);
384     return QDeclarativeListProperty<QDeclarativeAbstractAnimation>(this, &d->animations, QDeclarativeTransitionPrivate::append_animation,
385                                                                    QDeclarativeTransitionPrivate::animation_count,
386                                                                    QDeclarativeTransitionPrivate::animation_at,
387                                                                    QDeclarativeTransitionPrivate::clear_animations);
388 }
389
390 QT_END_NAMESPACE
391
392 #include <qdeclarativetransition.moc>