Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / src / declarative / util / qdeclarativetransition.cpp
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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativestate_p.h"
43 #include "private/qdeclarativestategroup_p.h"
44 #include "private/qdeclarativestate_p_p.h"
45 #include "private/qdeclarativestateoperations_p.h"
46 #include "private/qdeclarativeanimation_p.h"
47 #include "private/qdeclarativeanimation_p_p.h"
48 #include "private/qdeclarativetransitionmanager_p_p.h"
49
50 #include <QParallelAnimationGroup>
51
52 QT_BEGIN_NAMESPACE
53
54 /*!
55     \qmlclass Transition QDeclarativeTransition
56     \ingroup qml-animation-transition
57     \since 4.7
58     \brief The Transition element defines animated transitions that occur on state changes.
59
60     A Transition defines the animations to be applied when a \l State change occurs.
61
62     For example, the following \l Rectangle has two states: the default state, and
63     an added "moved" state. In the "moved state, the rectangle's position changes
64     to (50, 50).  The added Transition specifies that when the rectangle
65     changes between the default and the "moved" state, any changes
66     to the \c x and \c y properties should be animated, using an \c Easing.InOutQuad.
67
68     \snippet doc/src/snippets/declarative/transition.qml 0
69
70     Notice the example does not require \l{PropertyAnimation::}{to} and
71     \l{PropertyAnimation::}{from} values for the NumberAnimation. As a convenience,
72     these properties are automatically set to the values of \c x and \c y before
73     and after the state change; the \c from values are provided by
74     the current values of \c x and \c y, and the \c to values are provided by
75     the PropertyChanges object. If you wish, you can provide \l{PropertyAnimation::}{to} and
76     \l{PropertyAnimation::}{from} values anyway to override the default values.
77
78     By default, a Transition's animations are applied for any state change in the
79     parent item. The  Transition \l {Transition::}{from} and \l {Transition::}{to}
80     values can be set to restrict the animations to only be applied when changing
81     from one particular state to another.
82
83     To define multiple transitions, specify \l Item::transitions as a list:
84
85     \snippet doc/src/snippets/declarative/transitions-list.qml list of transitions
86
87     If multiple Transitions are specified, only a single (best-matching) Transition will be applied for any particular
88     state change. In the example above, when changing to \c state1, the first transition will be used, rather
89     than the more generic second transition.
90
91     If a state change has a Transition that matches the same property as a
92     \l Behavior, the Transition animation overrides the \l Behavior for that
93     state change.
94
95     \sa {QML Animation and Transitions}, {declarative/animation/states}{states example}, {qmlstates}{States}, {QtDeclarative}
96 */
97
98 //ParallelAnimationWrapper allows us to do a "callback" when the animation finishes, rather than connecting
99 //and disconnecting signals and slots frequently
100 class ParallelAnimationWrapper : public QParallelAnimationGroup
101 {
102     Q_OBJECT
103 public:
104     ParallelAnimationWrapper(QObject *parent = 0) : QParallelAnimationGroup(parent) {}
105     QDeclarativeTransitionPrivate *trans;
106 protected:
107     virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
108 };
109
110 class QDeclarativeTransitionPrivate : public QObjectPrivate
111 {
112     Q_DECLARE_PUBLIC(QDeclarativeTransition)
113 public:
114     QDeclarativeTransitionPrivate()
115     : fromState(QLatin1String("*")), toState(QLatin1String("*")),
116       reversed(false), reversible(false), endState(0)
117     {
118         group.trans = this;
119     }
120
121     QString fromState;
122     QString toState;
123     bool reversed;
124     bool reversible;
125     ParallelAnimationWrapper group;
126     QDeclarativeTransitionManager *endState;
127
128     void complete()
129     {
130         endState->complete();
131     }
132     static void append_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, QDeclarativeAbstractAnimation *a);
133     QList<QDeclarativeAbstractAnimation *> animations;
134 };
135
136 void QDeclarativeTransitionPrivate::append_animation(QDeclarativeListProperty<QDeclarativeAbstractAnimation> *list, QDeclarativeAbstractAnimation *a)
137 {
138     QDeclarativeTransition *q = static_cast<QDeclarativeTransition *>(list->object);
139     q->d_func()->animations.append(a);
140     q->d_func()->group.addAnimation(a->qtAnimation());
141     a->setDisableUserControl();
142 }
143
144 void ParallelAnimationWrapper::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
145 {
146     QParallelAnimationGroup::updateState(newState, oldState);
147     if (newState == Stopped && (duration() == -1
148         || (direction() == QAbstractAnimation::Forward && currentLoopTime() == duration())
149         || (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0)))
150     {
151         trans->complete();
152     }
153 }
154
155
156
157 QDeclarativeTransition::QDeclarativeTransition(QObject *parent)
158     : QObject(*(new QDeclarativeTransitionPrivate), parent)
159 {
160 }
161
162 QDeclarativeTransition::~QDeclarativeTransition()
163 {
164 }
165
166 void QDeclarativeTransition::stop()
167 {
168     Q_D(QDeclarativeTransition);
169     d->group.stop();
170 }
171
172 void QDeclarativeTransition::setReversed(bool r)
173 {
174     Q_D(QDeclarativeTransition);
175     d->reversed = r;
176 }
177
178 void QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &actions,
179                             QList<QDeclarativeProperty> &after,
180                             QDeclarativeTransitionManager *endState)
181 {
182     Q_D(QDeclarativeTransition);
183
184     qmlExecuteDeferred(this);
185
186     if (d->reversed) {
187         for (int ii = d->animations.count() - 1; ii >= 0; --ii) {
188             d->animations.at(ii)->transition(actions, after, QDeclarativeAbstractAnimation::Backward);
189         }
190     } else {
191         for (int ii = 0; ii < d->animations.count(); ++ii) {
192             d->animations.at(ii)->transition(actions, after, QDeclarativeAbstractAnimation::Forward);
193         }
194     }
195
196     d->endState = endState;
197     d->group.setDirection(d->reversed ? QAbstractAnimation::Backward : QAbstractAnimation::Forward);
198     d->group.start();
199 }
200
201 /*!
202     \qmlproperty string Transition::from
203     \qmlproperty string Transition::to
204
205     These properties indicate the state changes that trigger the transition.
206
207     The default values for these properties is "*" (that is, any state).
208
209     For example, the following transition has not set the \c to and \c from
210     properties, so the animation is always applied when changing between
211     the two states (i.e. when the mouse is pressed and released).
212
213     \snippet doc/src/snippets/declarative/transition-from-to.qml 0
214
215     If the transition was changed to this:
216
217     \snippet doc/src/snippets/declarative/transition-from-to-modified.qml modified transition
218
219     The animation would only be applied when changing from the default state to
220     the "brighter" state (i.e. when the mouse is pressed, but not on release).
221
222     \sa reversible
223 */
224 QString QDeclarativeTransition::fromState() const
225 {
226     Q_D(const QDeclarativeTransition);
227     return d->fromState;
228 }
229
230 void QDeclarativeTransition::setFromState(const QString &f)
231 {
232     Q_D(QDeclarativeTransition);
233     if (f == d->fromState)
234         return;
235
236     d->fromState = f;
237     emit fromChanged();
238 }
239
240 /*!
241     \qmlproperty bool Transition::reversible
242     This property holds whether the transition should be automatically reversed when the conditions that triggered this transition are reversed.
243
244     The default value is false.
245
246     By default, transitions run in parallel and are applied to all state
247     changes if the \l from and \l to states have not been set. In this
248     situation, the transition is automatically applied when a state change
249     is reversed, and it is not necessary to set this property to reverse
250     the transition.
251
252     However, if a SequentialAnimation is used, or if the \l from or \l to
253     properties have been set, this property will need to be set to reverse
254     a transition when a state change is reverted. For example, the following
255     transition applies a sequential animation when the mouse is pressed,
256     and reverses the sequence of the animation when the mouse is released:
257
258     \snippet doc/src/snippets/declarative/transition-reversible.qml 0
259
260     If the transition did not set the \c to and \c reversible values, then
261     on the mouse release, the transition would play the PropertyAnimation
262     before the ColorAnimation instead of reversing the sequence.
263 */
264 bool QDeclarativeTransition::reversible() const
265 {
266     Q_D(const QDeclarativeTransition);
267     return d->reversible;
268 }
269
270 void QDeclarativeTransition::setReversible(bool r)
271 {
272     Q_D(QDeclarativeTransition);
273     if (r == d->reversible)
274         return;
275
276     d->reversible = r;
277     emit reversibleChanged();
278 }
279
280 QString QDeclarativeTransition::toState() const
281 {
282     Q_D(const QDeclarativeTransition);
283     return d->toState;
284 }
285
286 void QDeclarativeTransition::setToState(const QString &t)
287 {
288     Q_D(QDeclarativeTransition);
289     if (t == d->toState)
290         return;
291
292     d->toState = t;
293     emit toChanged();
294 }
295
296 /*!
297     \qmlproperty list<Animation> Transition::animations
298     \default
299
300     This property holds a list of the animations to be run for this transition.
301
302     \snippet examples/declarative/toys/dynamicscene/dynamicscene.qml top-level transitions
303
304     The top-level animations are run in parallel. To run them sequentially,
305     define them within a SequentialAnimation:
306
307     \snippet doc/src/snippets/declarative/transition-reversible.qml sequential animations
308 */
309 QDeclarativeListProperty<QDeclarativeAbstractAnimation> QDeclarativeTransition::animations()
310 {
311     Q_D(QDeclarativeTransition);
312     return QDeclarativeListProperty<QDeclarativeAbstractAnimation>(this, &d->animations, QDeclarativeTransitionPrivate::append_animation);
313 }
314
315 QT_END_NAMESPACE
316
317 #include <qdeclarativetransition.moc>