source: trunk/src/corelib/animation/qparallelanimationgroup.cpp@ 1168

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

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

  • Property svn:eol-style set to native
File size: 11.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore 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 [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*!
43 \class QParallelAnimationGroup
44 \brief The QParallelAnimationGroup class provides a parallel group of animations.
45 \since 4.6
46 \ingroup animation
47
48 QParallelAnimationGroup--a \l{QAnimationGroup}{container for
49 animations}--starts all its animations when it is
50 \l{QAbstractAnimation::start()}{started} itself, i.e., runs all
51 animations in parallel. The animation group finishes when the
52 longest lasting animation has finished.
53
54 You can treat QParallelAnimation as any other QAbstractAnimation,
55 e.g., pause, resume, or add it to other animation groups.
56
57 \code
58 QParallelAnimationGroup *group = new QParallelAnimationGroup;
59 group->addAnimation(anim1);
60 group->addAnimation(anim2);
61
62 group->start();
63 \endcode
64
65 In this example, \c anim1 and \c anim2 are two
66 \l{QPropertyAnimation}s that have already been set up.
67
68 \sa QAnimationGroup, QPropertyAnimation, {The Animation Framework}
69*/
70
71
72#include "qparallelanimationgroup.h"
73#include "qparallelanimationgroup_p.h"
74//#define QANIMATION_DEBUG
75
76#ifndef QT_NO_ANIMATION
77
78QT_BEGIN_NAMESPACE
79
80/*!
81 Constructs a QParallelAnimationGroup.
82 \a parent is passed to QObject's constructor.
83*/
84QParallelAnimationGroup::QParallelAnimationGroup(QObject *parent)
85 : QAnimationGroup(*new QParallelAnimationGroupPrivate, parent)
86{
87}
88
89/*!
90 \internal
91*/
92QParallelAnimationGroup::QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd,
93 QObject *parent)
94 : QAnimationGroup(dd, parent)
95{
96}
97
98/*!
99 Destroys the animation group. It will also destroy all its animations.
100*/
101QParallelAnimationGroup::~QParallelAnimationGroup()
102{
103}
104
105/*!
106 \reimp
107*/
108int QParallelAnimationGroup::duration() const
109{
110 Q_D(const QParallelAnimationGroup);
111 int ret = 0;
112
113 for (int i = 0; i < d->animations.size(); ++i) {
114 QAbstractAnimation *animation = d->animations.at(i);
115 const int currentDuration = animation->totalDuration();
116 if (currentDuration == -1)
117 return -1; // Undetermined length
118
119 ret = qMax(ret, currentDuration);
120 }
121
122 return ret;
123}
124
125/*!
126 \reimp
127*/
128void QParallelAnimationGroup::updateCurrentTime(int currentTime)
129{
130 Q_D(QParallelAnimationGroup);
131 if (d->animations.isEmpty())
132 return;
133
134 if (d->currentLoop > d->lastLoop) {
135 // simulate completion of the loop
136 int dura = duration();
137 if (dura > 0) {
138 for (int i = 0; i < d->animations.size(); ++i) {
139 QAbstractAnimation *animation = d->animations.at(i);
140 if (animation->state() != QAbstractAnimation::Stopped)
141 d->animations.at(i)->setCurrentTime(dura); // will stop
142 }
143 }
144 } else if (d->currentLoop < d->lastLoop) {
145 // simulate completion of the loop seeking backwards
146 for (int i = 0; i < d->animations.size(); ++i) {
147 QAbstractAnimation *animation = d->animations.at(i);
148 //we need to make sure the animation is in the right state
149 //and then rewind it
150 d->applyGroupState(animation);
151 animation->setCurrentTime(0);
152 animation->stop();
153 }
154 }
155
156#ifdef QANIMATION_DEBUG
157 qDebug("QParallellAnimationGroup %5d: setCurrentTime(%d), loop:%d, last:%d, timeFwd:%d, lastcurrent:%d, %d",
158 __LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state());
159#endif
160 // finally move into the actual time of the current loop
161 for (int i = 0; i < d->animations.size(); ++i) {
162 QAbstractAnimation *animation = d->animations.at(i);
163 const int dura = animation->totalDuration();
164 //if the loopcount is bigger we should always start all animations
165 if (d->currentLoop > d->lastLoop
166 //if we're at the end of the animation, we need to start it if it wasn't already started in this loop
167 //this happens in Backward direction where not all animations are started at the same time
168 || d->shouldAnimationStart(animation, d->lastCurrentTime > dura /*startIfAtEnd*/)) {
169 d->applyGroupState(animation);
170 }
171
172 if (animation->state() == state()) {
173 animation->setCurrentTime(currentTime);
174 if (dura > 0 && currentTime > dura)
175 animation->stop();
176 }
177 }
178 d->lastLoop = d->currentLoop;
179 d->lastCurrentTime = currentTime;
180}
181
182/*!
183 \reimp
184*/
185void QParallelAnimationGroup::updateState(QAbstractAnimation::State newState,
186 QAbstractAnimation::State oldState)
187{
188 Q_D(QParallelAnimationGroup);
189 QAnimationGroup::updateState(newState, oldState);
190
191 switch (newState) {
192 case Stopped:
193 for (int i = 0; i < d->animations.size(); ++i)
194 d->animations.at(i)->stop();
195 d->disconnectUncontrolledAnimations();
196 break;
197 case Paused:
198 for (int i = 0; i < d->animations.size(); ++i)
199 if (d->animations.at(i)->state() == Running)
200 d->animations.at(i)->pause();
201 break;
202 case Running:
203 d->connectUncontrolledAnimations();
204 for (int i = 0; i < d->animations.size(); ++i) {
205 QAbstractAnimation *animation = d->animations.at(i);
206 if (oldState == Stopped)
207 animation->stop();
208 animation->setDirection(d->direction);
209 if (d->shouldAnimationStart(animation, oldState == Stopped))
210 animation->start();
211 }
212 break;
213 }
214}
215
216void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
217{
218 Q_Q(QParallelAnimationGroup);
219
220 QAbstractAnimation *animation = qobject_cast<QAbstractAnimation *>(q->sender());
221 Q_ASSERT(animation);
222
223 int uncontrolledRunningCount = 0;
224 if (animation->duration() == -1 || animation->loopCount() < 0) {
225 QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
226 while (it != uncontrolledFinishTime.end()) {
227 if (it.key() == animation) {
228 *it = animation->currentTime();
229 }
230 if (it.value() == -1)
231 ++uncontrolledRunningCount;
232 ++it;
233 }
234 }
235
236 if (uncontrolledRunningCount > 0)
237 return;
238
239 int maxDuration = 0;
240 for (int i = 0; i < animations.size(); ++i)
241 maxDuration = qMax(maxDuration, animations.at(i)->totalDuration());
242
243 if (currentTime >= maxDuration)
244 q->stop();
245}
246
247void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations()
248{
249 QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
250 while (it != uncontrolledFinishTime.end()) {
251 disconnectUncontrolledAnimation(it.key());
252 ++it;
253 }
254
255 uncontrolledFinishTime.clear();
256}
257
258void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
259{
260 for (int i = 0; i < animations.size(); ++i) {
261 QAbstractAnimation *animation = animations.at(i);
262 if (animation->duration() == -1 || animation->loopCount() < 0) {
263 uncontrolledFinishTime[animation] = -1;
264 connectUncontrolledAnimation(animation);
265 }
266 }
267}
268
269bool QParallelAnimationGroupPrivate::shouldAnimationStart(QAbstractAnimation *animation, bool startIfAtEnd) const
270{
271 const int dura = animation->totalDuration();
272 if (dura == -1)
273 return !isUncontrolledAnimationFinished(animation);
274 if (startIfAtEnd)
275 return currentTime <= dura;
276 if (direction == QAbstractAnimation::Forward)
277 return currentTime < dura;
278 else //direction == QAbstractAnimation::Backward
279 return currentTime && currentTime <= dura;
280}
281
282void QParallelAnimationGroupPrivate::applyGroupState(QAbstractAnimation *animation)
283{
284 switch (state)
285 {
286 case QAbstractAnimation::Running:
287 animation->start();
288 break;
289 case QAbstractAnimation::Paused:
290 animation->pause();
291 break;
292 case QAbstractAnimation::Stopped:
293 default:
294 break;
295 }
296}
297
298
299bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAnimation *anim) const
300{
301 return uncontrolledFinishTime.value(anim, -1) >= 0;
302}
303
304void QParallelAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
305{
306 QAnimationGroupPrivate::animationRemoved(index, anim);
307 disconnectUncontrolledAnimation(anim);
308 uncontrolledFinishTime.remove(anim);
309}
310
311/*!
312 \reimp
313*/
314void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
315{
316 Q_D(QParallelAnimationGroup);
317 //we need to update the direction of the current animation
318 if (state() != Stopped) {
319 for (int i = 0; i < d->animations.size(); ++i) {
320 QAbstractAnimation *animation = d->animations.at(i);
321 animation->setDirection(direction);
322 }
323 } else {
324 if (direction == Forward) {
325 d->lastLoop = 0;
326 d->lastCurrentTime = 0;
327 } else {
328 // Looping backwards with loopCount == -1 does not really work well...
329 d->lastLoop = (d->loopCount == -1 ? 0 : d->loopCount - 1);
330 d->lastCurrentTime = duration();
331 }
332 }
333}
334
335/*!
336 \reimp
337*/
338bool QParallelAnimationGroup::event(QEvent *event)
339{
340 return QAnimationGroup::event(event);
341}
342
343QT_END_NAMESPACE
344
345#include "moc_qparallelanimationgroup.cpp"
346
347#endif //QT_NO_ANIMATION
Note: See TracBrowser for help on using the repository browser.