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 | #include "qvariantanimation.h"
|
---|
43 | #include "qvariantanimation_p.h"
|
---|
44 |
|
---|
45 | #include <QtCore/qrect.h>
|
---|
46 | #include <QtCore/qline.h>
|
---|
47 | #include <QtCore/qmutex.h>
|
---|
48 | #include <private/qmutexpool_p.h>
|
---|
49 |
|
---|
50 | #ifndef QT_NO_ANIMATION
|
---|
51 |
|
---|
52 | QT_BEGIN_NAMESPACE
|
---|
53 |
|
---|
54 | /*!
|
---|
55 | \class QVariantAnimation
|
---|
56 | \ingroup animation
|
---|
57 | \brief The QVariantAnimation class provides an abstract base class for animations.
|
---|
58 | \since 4.6
|
---|
59 |
|
---|
60 | This class is part of \l{The Animation Framework}. It serves as a
|
---|
61 | base class for property and item animations, with functions for
|
---|
62 | shared functionality.
|
---|
63 |
|
---|
64 | QVariantAnimation cannot be used directly as it is an abstract
|
---|
65 | class; it has a pure virtual method called updateCurrentValue().
|
---|
66 | The class performs interpolation over
|
---|
67 | \l{QVariant}s, but leaves using the interpolated values to its
|
---|
68 | subclasses. Currently, Qt provides QPropertyAnimation, which
|
---|
69 | animates Qt \l{Qt's Property System}{properties}. See the
|
---|
70 | QPropertyAnimation class description if you wish to animate such
|
---|
71 | properties.
|
---|
72 |
|
---|
73 | You can then set start and end values for the property by calling
|
---|
74 | setStartValue() and setEndValue(), and finally call start() to
|
---|
75 | start the animation. QVariantAnimation will interpolate the
|
---|
76 | property of the target object and emit valueChanged(). To react to
|
---|
77 | a change in the current value you have to reimplement the
|
---|
78 | updateCurrentValue() virtual function.
|
---|
79 |
|
---|
80 | It is also possible to set values at specified steps situated
|
---|
81 | between the start and end value. The interpolation will then
|
---|
82 | touch these points at the specified steps. Note that the start and
|
---|
83 | end values are defined as the key values at 0.0 and 1.0.
|
---|
84 |
|
---|
85 | There are two ways to affect how QVariantAnimation interpolates
|
---|
86 | the values. You can set an easing curve by calling
|
---|
87 | setEasingCurve(), and configure the duration by calling
|
---|
88 | setDuration(). You can change how the QVariants are interpolated
|
---|
89 | by creating a subclass of QVariantAnimation, and reimplementing
|
---|
90 | the virtual interpolated() function.
|
---|
91 |
|
---|
92 | Subclassing QVariantAnimation can be an alternative if you have
|
---|
93 | \l{QVariant}s that you do not wish to declare as Qt properties.
|
---|
94 | Note, however, that you in most cases will be better off declaring
|
---|
95 | your QVariant as a property.
|
---|
96 |
|
---|
97 | Not all QVariant types are supported. Below is a list of currently
|
---|
98 | supported QVariant types:
|
---|
99 |
|
---|
100 | \list
|
---|
101 | \o \l{QMetaType::}{Int}
|
---|
102 | \o \l{QMetaType::}{Double}
|
---|
103 | \o \l{QMetaType::}{Float}
|
---|
104 | \o \l{QMetaType::}{QLine}
|
---|
105 | \o \l{QMetaType::}{QLineF}
|
---|
106 | \o \l{QMetaType::}{QPoint}
|
---|
107 | \o \l{QMetaType::}{QPointF}
|
---|
108 | \o \l{QMetaType::}{QSize}
|
---|
109 | \o \l{QMetaType::}{QSizeF}
|
---|
110 | \o \l{QMetaType::}{QRect}
|
---|
111 | \o \l{QMetaType::}{QRectF}
|
---|
112 | \o \l{QMetaType::}{QColor}
|
---|
113 | \endlist
|
---|
114 |
|
---|
115 | If you need to interpolate other variant types, including custom
|
---|
116 | types, you have to implement interpolation for these yourself.
|
---|
117 | To do this, you can register an interpolator function for a given
|
---|
118 | type. This function takes 3 parameters: the start value, the end value
|
---|
119 | and the current progress.
|
---|
120 |
|
---|
121 | Example:
|
---|
122 | \code
|
---|
123 | QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
|
---|
124 | {
|
---|
125 | ...
|
---|
126 | return QColor(...);
|
---|
127 | }
|
---|
128 | ...
|
---|
129 | qRegisterAnimationInterpolator<QColor>(myColorInterpolator);
|
---|
130 | \endcode
|
---|
131 |
|
---|
132 | Another option is to reimplement interpolated(), which returns
|
---|
133 | interpolation values for the value being interpolated.
|
---|
134 |
|
---|
135 | \omit We need some snippets around here. \endomit
|
---|
136 |
|
---|
137 | \sa QPropertyAnimation, QAbstractAnimation, {The Animation Framework}
|
---|
138 | */
|
---|
139 |
|
---|
140 | /*!
|
---|
141 | \fn void QVariantAnimation::valueChanged(const QVariant &value)
|
---|
142 |
|
---|
143 | QVariantAnimation emits this signal whenever the current \a value changes.
|
---|
144 |
|
---|
145 | \sa currentValue, startValue, endValue
|
---|
146 | */
|
---|
147 |
|
---|
148 | /*!
|
---|
149 | \fn void QVariantAnimation::updateCurrentValue(const QVariant &value) = 0;
|
---|
150 |
|
---|
151 | This pure virtual function is called every time the animation's current
|
---|
152 | value changes. The \a value argument is the new current value.
|
---|
153 |
|
---|
154 | \sa currentValue
|
---|
155 | */
|
---|
156 |
|
---|
157 | static bool animationValueLessThan(const QVariantAnimation::KeyValue &p1, const QVariantAnimation::KeyValue &p2)
|
---|
158 | {
|
---|
159 | return p1.first < p2.first;
|
---|
160 | }
|
---|
161 |
|
---|
162 | static QVariant defaultInterpolator(const void *, const void *, qreal)
|
---|
163 | {
|
---|
164 | return QVariant();
|
---|
165 | }
|
---|
166 |
|
---|
167 | template<> Q_INLINE_TEMPLATE QRect _q_interpolate(const QRect &f, const QRect &t, qreal progress)
|
---|
168 | {
|
---|
169 | QRect ret;
|
---|
170 | ret.setCoords(_q_interpolate(f.left(), t.left(), progress),
|
---|
171 | _q_interpolate(f.top(), t.top(), progress),
|
---|
172 | _q_interpolate(f.right(), t.right(), progress),
|
---|
173 | _q_interpolate(f.bottom(), t.bottom(), progress));
|
---|
174 | return ret;
|
---|
175 | }
|
---|
176 |
|
---|
177 | template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF &t, qreal progress)
|
---|
178 | {
|
---|
179 | qreal x1, y1, w1, h1;
|
---|
180 | f.getRect(&x1, &y1, &w1, &h1);
|
---|
181 | qreal x2, y2, w2, h2;
|
---|
182 | t.getRect(&x2, &y2, &w2, &h2);
|
---|
183 | return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress),
|
---|
184 | _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress));
|
---|
185 | }
|
---|
186 |
|
---|
187 | template<> Q_INLINE_TEMPLATE QLine _q_interpolate(const QLine &f, const QLine &t, qreal progress)
|
---|
188 | {
|
---|
189 | return QLine( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
|
---|
190 | }
|
---|
191 |
|
---|
192 | template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF &t, qreal progress)
|
---|
193 | {
|
---|
194 | return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
|
---|
195 | }
|
---|
196 |
|
---|
197 | QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), interpolator(&defaultInterpolator)
|
---|
198 | { }
|
---|
199 |
|
---|
200 | void QVariantAnimationPrivate::convertValues(int t)
|
---|
201 | {
|
---|
202 | //this ensures that all the keyValues are of type t
|
---|
203 | for (int i = 0; i < keyValues.count(); ++i) {
|
---|
204 | QVariantAnimation::KeyValue &pair = keyValues[i];
|
---|
205 | pair.second.convert(static_cast<QVariant::Type>(t));
|
---|
206 | }
|
---|
207 | //we also need update to the current interval if needed
|
---|
208 | currentInterval.start.second.convert(static_cast<QVariant::Type>(t));
|
---|
209 | currentInterval.end.second.convert(static_cast<QVariant::Type>(t));
|
---|
210 |
|
---|
211 | //... and the interpolator
|
---|
212 | updateInterpolator();
|
---|
213 | }
|
---|
214 |
|
---|
215 | void QVariantAnimationPrivate::updateInterpolator()
|
---|
216 | {
|
---|
217 | int type = currentInterval.start.second.userType();
|
---|
218 | if (type == currentInterval.end.second.userType())
|
---|
219 | interpolator = getInterpolator(type);
|
---|
220 | else
|
---|
221 | interpolator = 0;
|
---|
222 |
|
---|
223 | //we make sure that the interpolator is always set to something
|
---|
224 | if (!interpolator)
|
---|
225 | interpolator = &defaultInterpolator;
|
---|
226 | }
|
---|
227 |
|
---|
228 | /*!
|
---|
229 | \internal
|
---|
230 | The goal of this function is to update the currentInterval member. As a consequence, we also
|
---|
231 | need to update the currentValue.
|
---|
232 | Set \a force to true to always recalculate the interval.
|
---|
233 | */
|
---|
234 | void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/)
|
---|
235 | {
|
---|
236 | // can't interpolate if we don't have at least 2 values
|
---|
237 | if ((keyValues.count() + (defaultStartEndValue.isValid() ? 1 : 0)) < 2)
|
---|
238 | return;
|
---|
239 |
|
---|
240 | const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration)));
|
---|
241 |
|
---|
242 | //0 and 1 are still the boundaries
|
---|
243 | if (force || (currentInterval.start.first > 0 && progress < currentInterval.start.first)
|
---|
244 | || (currentInterval.end.first < 1 && progress > currentInterval.end.first)) {
|
---|
245 | //let's update currentInterval
|
---|
246 | QVariantAnimation::KeyValues::const_iterator it = qLowerBound(keyValues.constBegin(),
|
---|
247 | keyValues.constEnd(),
|
---|
248 | qMakePair(progress, QVariant()),
|
---|
249 | animationValueLessThan);
|
---|
250 | if (it == keyValues.constBegin()) {
|
---|
251 | //the item pointed to by it is the start element in the range
|
---|
252 | if (it->first == 0 && keyValues.count() > 1) {
|
---|
253 | currentInterval.start = *it;
|
---|
254 | currentInterval.end = *(it+1);
|
---|
255 | } else {
|
---|
256 | currentInterval.start = qMakePair(qreal(0), defaultStartEndValue);
|
---|
257 | currentInterval.end = *it;
|
---|
258 | }
|
---|
259 | } else if (it == keyValues.constEnd()) {
|
---|
260 | --it; //position the iterator on the last item
|
---|
261 | if (it->first == 1 && keyValues.count() > 1) {
|
---|
262 | //we have an end value (item with progress = 1)
|
---|
263 | currentInterval.start = *(it-1);
|
---|
264 | currentInterval.end = *it;
|
---|
265 | } else {
|
---|
266 | //we use the default end value here
|
---|
267 | currentInterval.start = *it;
|
---|
268 | currentInterval.end = qMakePair(qreal(1), defaultStartEndValue);
|
---|
269 | }
|
---|
270 | } else {
|
---|
271 | currentInterval.start = *(it-1);
|
---|
272 | currentInterval.end = *it;
|
---|
273 | }
|
---|
274 |
|
---|
275 | // update all the values of the currentInterval
|
---|
276 | updateInterpolator();
|
---|
277 | }
|
---|
278 | setCurrentValueForProgress(progress);
|
---|
279 | }
|
---|
280 |
|
---|
281 | void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
|
---|
282 | {
|
---|
283 | Q_Q(QVariantAnimation);
|
---|
284 |
|
---|
285 | const qreal startProgress = currentInterval.start.first;
|
---|
286 | const qreal endProgress = currentInterval.end.first;
|
---|
287 | const qreal localProgress = (progress - startProgress) / (endProgress - startProgress);
|
---|
288 |
|
---|
289 | QVariant ret = q->interpolated(currentInterval.start.second,
|
---|
290 | currentInterval.end.second,
|
---|
291 | localProgress);
|
---|
292 | qSwap(currentValue, ret);
|
---|
293 | q->updateCurrentValue(currentValue);
|
---|
294 | static QBasicAtomicInt changedSignalIndex = Q_BASIC_ATOMIC_INITIALIZER(0);
|
---|
295 | if (!changedSignalIndex) {
|
---|
296 | //we keep the mask so that we emit valueChanged only when needed (for performance reasons)
|
---|
297 | changedSignalIndex.testAndSetRelaxed(0, signalIndex("valueChanged(QVariant)"));
|
---|
298 | }
|
---|
299 | if (isSignalConnected(changedSignalIndex) && currentValue != ret) {
|
---|
300 | //the value has changed
|
---|
301 | emit q->valueChanged(currentValue);
|
---|
302 | }
|
---|
303 | }
|
---|
304 |
|
---|
305 | QVariant QVariantAnimationPrivate::valueAt(qreal step) const
|
---|
306 | {
|
---|
307 | QVariantAnimation::KeyValues::const_iterator result =
|
---|
308 | qBinaryFind(keyValues.begin(), keyValues.end(), qMakePair(step, QVariant()), animationValueLessThan);
|
---|
309 | if (result != keyValues.constEnd())
|
---|
310 | return result->second;
|
---|
311 |
|
---|
312 | return QVariant();
|
---|
313 | }
|
---|
314 |
|
---|
315 | void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value)
|
---|
316 | {
|
---|
317 | if (step < qreal(0.0) || step > qreal(1.0)) {
|
---|
318 | qWarning("QVariantAnimation::setValueAt: invalid step = %f", step);
|
---|
319 | return;
|
---|
320 | }
|
---|
321 |
|
---|
322 | QVariantAnimation::KeyValue pair(step, value);
|
---|
323 |
|
---|
324 | QVariantAnimation::KeyValues::iterator result = qLowerBound(keyValues.begin(), keyValues.end(), pair, animationValueLessThan);
|
---|
325 | if (result == keyValues.end() || result->first != step) {
|
---|
326 | keyValues.insert(result, pair);
|
---|
327 | } else {
|
---|
328 | if (value.isValid())
|
---|
329 | result->second = value; // replaces the previous value
|
---|
330 | else
|
---|
331 | keyValues.erase(result); // removes the previous value
|
---|
332 | }
|
---|
333 |
|
---|
334 | recalculateCurrentInterval(/*force=*/true);
|
---|
335 | }
|
---|
336 |
|
---|
337 | void QVariantAnimationPrivate::setDefaultStartEndValue(const QVariant &value)
|
---|
338 | {
|
---|
339 | defaultStartEndValue = value;
|
---|
340 | recalculateCurrentInterval(/*force=*/true);
|
---|
341 | }
|
---|
342 |
|
---|
343 | /*!
|
---|
344 | Construct a QVariantAnimation object. \a parent is passed to QAbstractAnimation's
|
---|
345 | constructor.
|
---|
346 | */
|
---|
347 | QVariantAnimation::QVariantAnimation(QObject *parent) : QAbstractAnimation(*new QVariantAnimationPrivate, parent)
|
---|
348 | {
|
---|
349 | }
|
---|
350 |
|
---|
351 | /*!
|
---|
352 | \internal
|
---|
353 | */
|
---|
354 | QVariantAnimation::QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent) : QAbstractAnimation(dd, parent)
|
---|
355 | {
|
---|
356 | }
|
---|
357 |
|
---|
358 | /*!
|
---|
359 | Destroys the animation.
|
---|
360 | */
|
---|
361 | QVariantAnimation::~QVariantAnimation()
|
---|
362 | {
|
---|
363 | }
|
---|
364 |
|
---|
365 | /*!
|
---|
366 | \property QVariantAnimation::easingCurve
|
---|
367 | \brief the easing curve of the animation
|
---|
368 |
|
---|
369 | This property defines the easing curve of the animation. By
|
---|
370 | default, a linear easing curve is used, resulting in linear
|
---|
371 | interpolation. Other curves are provided, for instance,
|
---|
372 | QEasingCurve::InCirc, which provides a circular entry curve.
|
---|
373 | Another example is QEasingCurve::InOutElastic, which provides an
|
---|
374 | elastic effect on the values of the interpolated variant.
|
---|
375 |
|
---|
376 | QVariantAnimation will use the QEasingCurve::valueForProgress() to
|
---|
377 | transform the "normalized progress" (currentTime / totalDuration)
|
---|
378 | of the animation into the effective progress actually
|
---|
379 | used by the animation. It is this effective progress that will be
|
---|
380 | the progress when interpolated() is called. Also, the steps in the
|
---|
381 | keyValues are referring to this effective progress.
|
---|
382 |
|
---|
383 | The easing curve is used with the interpolator, the interpolated()
|
---|
384 | virtual function, the animation's duration, and iterationCount, to
|
---|
385 | control how the current value changes as the animation progresses.
|
---|
386 | */
|
---|
387 | QEasingCurve QVariantAnimation::easingCurve() const
|
---|
388 | {
|
---|
389 | Q_D(const QVariantAnimation);
|
---|
390 | return d->easing;
|
---|
391 | }
|
---|
392 |
|
---|
393 | void QVariantAnimation::setEasingCurve(const QEasingCurve &easing)
|
---|
394 | {
|
---|
395 | Q_D(QVariantAnimation);
|
---|
396 | d->easing = easing;
|
---|
397 | d->recalculateCurrentInterval();
|
---|
398 | }
|
---|
399 |
|
---|
400 | typedef QVector<QVariantAnimation::Interpolator> QInterpolatorVector;
|
---|
401 | Q_GLOBAL_STATIC(QInterpolatorVector, registeredInterpolators)
|
---|
402 |
|
---|
403 | /*!
|
---|
404 | \fn void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
|
---|
405 | \relates QVariantAnimation
|
---|
406 | \threadsafe
|
---|
407 |
|
---|
408 | Registers a custom interpolator \a func for the template type \c{T}.
|
---|
409 | The interpolator has to be registered before the animation is constructed.
|
---|
410 | To unregister (and use the default interpolator) set \a func to 0.
|
---|
411 | */
|
---|
412 |
|
---|
413 | /*!
|
---|
414 | \internal
|
---|
415 | \typedef QVariantAnimation::Interpolator
|
---|
416 |
|
---|
417 | This is a typedef for a pointer to a function with the following
|
---|
418 | signature:
|
---|
419 | \code
|
---|
420 | QVariant myInterpolator(const QVariant &from, const QVariant &to, qreal progress);
|
---|
421 | \endcode
|
---|
422 |
|
---|
423 | */
|
---|
424 |
|
---|
425 | /*! \internal
|
---|
426 | * Registers a custom interpolator \a func for the specific \a interpolationType.
|
---|
427 | * The interpolator has to be registered before the animation is constructed.
|
---|
428 | * To unregister (and use the default interpolator) set \a func to 0.
|
---|
429 | */
|
---|
430 | void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator func, int interpolationType)
|
---|
431 | {
|
---|
432 | // will override any existing interpolators
|
---|
433 | QInterpolatorVector *interpolators = registeredInterpolators();
|
---|
434 | // we may be called from the static destruction code at program termination
|
---|
435 | // when registeredInterpolators() has already gone
|
---|
436 | if (!interpolators)
|
---|
437 | return;
|
---|
438 | #ifndef QT_NO_THREAD
|
---|
439 | QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
|
---|
440 | #endif
|
---|
441 | if (int(interpolationType) >= interpolators->count())
|
---|
442 | interpolators->resize(int(interpolationType) + 1);
|
---|
443 | interpolators->replace(interpolationType, func);
|
---|
444 | }
|
---|
445 |
|
---|
446 |
|
---|
447 | template<typename T> static inline QVariantAnimation::Interpolator castToInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
|
---|
448 | {
|
---|
449 | return reinterpret_cast<QVariantAnimation::Interpolator>(func);
|
---|
450 | }
|
---|
451 |
|
---|
452 | QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType)
|
---|
453 | {
|
---|
454 | QInterpolatorVector *interpolators = registeredInterpolators();
|
---|
455 | #ifndef QT_NO_THREAD
|
---|
456 | QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
|
---|
457 | #endif
|
---|
458 | QVariantAnimation::Interpolator ret = 0;
|
---|
459 | if (interpolationType < interpolators->count()) {
|
---|
460 | ret = interpolators->at(interpolationType);
|
---|
461 | if (ret) return ret;
|
---|
462 | }
|
---|
463 |
|
---|
464 | switch(interpolationType)
|
---|
465 | {
|
---|
466 | case QMetaType::Int:
|
---|
467 | return castToInterpolator(_q_interpolateVariant<int>);
|
---|
468 | case QMetaType::Double:
|
---|
469 | return castToInterpolator(_q_interpolateVariant<double>);
|
---|
470 | case QMetaType::Float:
|
---|
471 | return castToInterpolator(_q_interpolateVariant<float>);
|
---|
472 | case QMetaType::QLine:
|
---|
473 | return castToInterpolator(_q_interpolateVariant<QLine>);
|
---|
474 | case QMetaType::QLineF:
|
---|
475 | return castToInterpolator(_q_interpolateVariant<QLineF>);
|
---|
476 | case QMetaType::QPoint:
|
---|
477 | return castToInterpolator(_q_interpolateVariant<QPoint>);
|
---|
478 | case QMetaType::QPointF:
|
---|
479 | return castToInterpolator(_q_interpolateVariant<QPointF>);
|
---|
480 | case QMetaType::QSize:
|
---|
481 | return castToInterpolator(_q_interpolateVariant<QSize>);
|
---|
482 | case QMetaType::QSizeF:
|
---|
483 | return castToInterpolator(_q_interpolateVariant<QSizeF>);
|
---|
484 | case QMetaType::QRect:
|
---|
485 | return castToInterpolator(_q_interpolateVariant<QRect>);
|
---|
486 | case QMetaType::QRectF:
|
---|
487 | return castToInterpolator(_q_interpolateVariant<QRectF>);
|
---|
488 | default:
|
---|
489 | return 0; //this type is not handled
|
---|
490 | }
|
---|
491 | }
|
---|
492 |
|
---|
493 | /*!
|
---|
494 | \property QVariantAnimation::duration
|
---|
495 | \brief the duration of the animation
|
---|
496 |
|
---|
497 | This property describes the duration in milliseconds of the
|
---|
498 | animation. The default duration is 250 milliseconds.
|
---|
499 |
|
---|
500 | \sa QAbstractAnimation::duration()
|
---|
501 | */
|
---|
502 | int QVariantAnimation::duration() const
|
---|
503 | {
|
---|
504 | Q_D(const QVariantAnimation);
|
---|
505 | return d->duration;
|
---|
506 | }
|
---|
507 |
|
---|
508 | void QVariantAnimation::setDuration(int msecs)
|
---|
509 | {
|
---|
510 | Q_D(QVariantAnimation);
|
---|
511 | if (msecs < 0) {
|
---|
512 | qWarning("QVariantAnimation::setDuration: cannot set a negative duration");
|
---|
513 | return;
|
---|
514 | }
|
---|
515 | if (d->duration == msecs)
|
---|
516 | return;
|
---|
517 | d->duration = msecs;
|
---|
518 | d->recalculateCurrentInterval();
|
---|
519 | }
|
---|
520 |
|
---|
521 | /*!
|
---|
522 | \property QVariantAnimation::startValue
|
---|
523 | \brief the optional start value of the animation
|
---|
524 |
|
---|
525 | This property describes the optional start value of the animation. If
|
---|
526 | omitted, or if a null QVariant is assigned as the start value, the
|
---|
527 | animation will use the current position of the end when the animation
|
---|
528 | is started.
|
---|
529 |
|
---|
530 | \sa endValue
|
---|
531 | */
|
---|
532 | QVariant QVariantAnimation::startValue() const
|
---|
533 | {
|
---|
534 | return keyValueAt(0);
|
---|
535 | }
|
---|
536 |
|
---|
537 | void QVariantAnimation::setStartValue(const QVariant &value)
|
---|
538 | {
|
---|
539 | setKeyValueAt(0, value);
|
---|
540 | }
|
---|
541 |
|
---|
542 | /*!
|
---|
543 | \property QVariantAnimation::endValue
|
---|
544 | \brief the end value of the animation
|
---|
545 |
|
---|
546 | This property describes the end value of the animation.
|
---|
547 |
|
---|
548 | \sa startValue
|
---|
549 | */
|
---|
550 | QVariant QVariantAnimation::endValue() const
|
---|
551 | {
|
---|
552 | return keyValueAt(1);
|
---|
553 | }
|
---|
554 |
|
---|
555 | void QVariantAnimation::setEndValue(const QVariant &value)
|
---|
556 | {
|
---|
557 | setKeyValueAt(1, value);
|
---|
558 | }
|
---|
559 |
|
---|
560 |
|
---|
561 | /*!
|
---|
562 | Returns the key frame value for the given \a step. The given \a step
|
---|
563 | must be in the range 0 to 1. If there is no KeyValue for \a step,
|
---|
564 | it returns an invalid QVariant.
|
---|
565 |
|
---|
566 | \sa keyValues(), setKeyValueAt()
|
---|
567 | */
|
---|
568 | QVariant QVariantAnimation::keyValueAt(qreal step) const
|
---|
569 | {
|
---|
570 | return d_func()->valueAt(step);
|
---|
571 | }
|
---|
572 |
|
---|
573 | /*!
|
---|
574 | \typedef QVariantAnimation::KeyValue
|
---|
575 |
|
---|
576 | This is a typedef for QPair<qreal, QVariant>.
|
---|
577 | */
|
---|
578 | /*!
|
---|
579 | \typedef QVariantAnimation::KeyValues
|
---|
580 |
|
---|
581 | This is a typedef for QVector<KeyValue>
|
---|
582 | */
|
---|
583 |
|
---|
584 | /*!
|
---|
585 | Creates a key frame at the given \a step with the given \a value.
|
---|
586 | The given \a step must be in the range 0 to 1.
|
---|
587 |
|
---|
588 | \sa setKeyValues(), keyValueAt()
|
---|
589 | */
|
---|
590 | void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value)
|
---|
591 | {
|
---|
592 | d_func()->setValueAt(step, value);
|
---|
593 | }
|
---|
594 |
|
---|
595 | /*!
|
---|
596 | Returns the key frames of this animation.
|
---|
597 |
|
---|
598 | \sa keyValueAt(), setKeyValues()
|
---|
599 | */
|
---|
600 | QVariantAnimation::KeyValues QVariantAnimation::keyValues() const
|
---|
601 | {
|
---|
602 | return d_func()->keyValues;
|
---|
603 | }
|
---|
604 |
|
---|
605 | /*!
|
---|
606 | Replaces the current set of key frames with the given \a keyValues.
|
---|
607 | the step of the key frames must be in the range 0 to 1.
|
---|
608 |
|
---|
609 | \sa keyValues(), keyValueAt()
|
---|
610 | */
|
---|
611 | void QVariantAnimation::setKeyValues(const KeyValues &keyValues)
|
---|
612 | {
|
---|
613 | Q_D(QVariantAnimation);
|
---|
614 | d->keyValues = keyValues;
|
---|
615 | qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
|
---|
616 | d->recalculateCurrentInterval(/*force=*/true);
|
---|
617 | }
|
---|
618 |
|
---|
619 | /*!
|
---|
620 | \property QVariantAnimation::currentValue
|
---|
621 | \brief the current value of the animation.
|
---|
622 |
|
---|
623 | This property describes the current value; an interpolated value
|
---|
624 | between the \l{startValue}{start value} and the \l{endValue}{end
|
---|
625 | value}, using the current time for progress. The value itself is
|
---|
626 | obtained from interpolated(), which is called repeatedly as the
|
---|
627 | animation is running.
|
---|
628 |
|
---|
629 | QVariantAnimation calls the virtual updateCurrentValue() function
|
---|
630 | when the current value changes. This is particularly useful for
|
---|
631 | subclasses that need to track updates. For example,
|
---|
632 | QPropertyAnimation uses this function to animate Qt \l{Qt's
|
---|
633 | Property System}{properties}.
|
---|
634 |
|
---|
635 | \sa startValue, endValue
|
---|
636 | */
|
---|
637 | QVariant QVariantAnimation::currentValue() const
|
---|
638 | {
|
---|
639 | Q_D(const QVariantAnimation);
|
---|
640 | if (!d->currentValue.isValid())
|
---|
641 | const_cast<QVariantAnimationPrivate*>(d)->recalculateCurrentInterval();
|
---|
642 | return d->currentValue;
|
---|
643 | }
|
---|
644 |
|
---|
645 | /*!
|
---|
646 | \reimp
|
---|
647 | */
|
---|
648 | bool QVariantAnimation::event(QEvent *event)
|
---|
649 | {
|
---|
650 | return QAbstractAnimation::event(event);
|
---|
651 | }
|
---|
652 |
|
---|
653 | /*!
|
---|
654 | \reimp
|
---|
655 | */
|
---|
656 | void QVariantAnimation::updateState(QAbstractAnimation::State newState,
|
---|
657 | QAbstractAnimation::State oldState)
|
---|
658 | {
|
---|
659 | Q_UNUSED(oldState);
|
---|
660 | Q_UNUSED(newState);
|
---|
661 | }
|
---|
662 |
|
---|
663 | /*!
|
---|
664 |
|
---|
665 | This virtual function returns the linear interpolation between
|
---|
666 | variants \a from and \a to, at \a progress, usually a value
|
---|
667 | between 0 and 1. You can reimplement this function in a subclass
|
---|
668 | of QVariantAnimation to provide your own interpolation algorithm.
|
---|
669 |
|
---|
670 | Note that in order for the interpolation to work with a
|
---|
671 | QEasingCurve that return a value smaller than 0 or larger than 1
|
---|
672 | (such as QEasingCurve::InBack) you should make sure that it can
|
---|
673 | extrapolate. If the semantic of the datatype does not allow
|
---|
674 | extrapolation this function should handle that gracefully.
|
---|
675 |
|
---|
676 | You should call the QVariantAnimation implementation of this
|
---|
677 | function if you want your class to handle the types already
|
---|
678 | supported by Qt (see class QVariantAnimation description for a
|
---|
679 | list of supported types).
|
---|
680 |
|
---|
681 | \sa QEasingCurve
|
---|
682 | */
|
---|
683 | QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
|
---|
684 | {
|
---|
685 | return d_func()->interpolator(from.constData(), to.constData(), progress);
|
---|
686 | }
|
---|
687 |
|
---|
688 | /*!
|
---|
689 | \reimp
|
---|
690 | */
|
---|
691 | void QVariantAnimation::updateCurrentTime(int)
|
---|
692 | {
|
---|
693 | d_func()->recalculateCurrentInterval();
|
---|
694 | }
|
---|
695 |
|
---|
696 | QT_END_NAMESPACE
|
---|
697 |
|
---|
698 | #include "moc_qvariantanimation.cpp"
|
---|
699 |
|
---|
700 | #endif //QT_NO_ANIMATION
|
---|