summaryrefslogtreecommitdiffstats
path: root/src/declarative/timeline
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2009-04-22 04:47:24 (GMT)
commit2366667fc97eb6a56203b2dd7dac776ff4164abd (patch)
treeb2acb6cc6bfe475d7e619e4788973b61fff775e0 /src/declarative/timeline
parent2c762f3b8b284a7c6dc0c499b7052013bad5b707 (diff)
downloadQt-2366667fc97eb6a56203b2dd7dac776ff4164abd.zip
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.gz
Qt-2366667fc97eb6a56203b2dd7dac776ff4164abd.tar.bz2
Initial import of kinetic-dui branch from the old kinetic
Diffstat (limited to 'src/declarative/timeline')
-rw-r--r--src/declarative/timeline/gfxeasing.cpp846
-rw-r--r--src/declarative/timeline/gfxeasing.h107
-rw-r--r--src/declarative/timeline/gfxtimeline.cpp946
-rw-r--r--src/declarative/timeline/gfxtimeline.h190
-rw-r--r--src/declarative/timeline/gfxvalueproxy.h83
-rw-r--r--src/declarative/timeline/timeline.pri9
6 files changed, 2181 insertions, 0 deletions
diff --git a/src/declarative/timeline/gfxeasing.cpp b/src/declarative/timeline/gfxeasing.cpp
new file mode 100644
index 0000000..c89ba88
--- /dev/null
+++ b/src/declarative/timeline/gfxeasing.cpp
@@ -0,0 +1,846 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gfxeasing.h"
+#include <math.h>
+#include <QHash>
+#include <QPainter>
+#include <QVariant>
+#include <QDebug>
+#include <QStringList>
+#include <QMouseEvent>
+#include "gfxtimeline.h"
+
+
+QT_BEGIN_NAMESPACE
+typedef QHash<QString, qreal> GfxEasingProperties;
+class GfxEasingFunction
+{
+public:
+ virtual ~GfxEasingFunction() {}
+ virtual float value(float t, float b, float c, float d) = 0;
+ virtual GfxEasingFunction *copy() const = 0;
+};
+
+#include "../3rdparty/easing.cpp"
+
+struct ElasticEase : public GfxEasingFunction
+{
+ enum Type { In, Out };
+ ElasticEase(Type t) : _t(t), _p(0.0f), _a(0.0f) {}
+
+ Type _t;
+ qreal _p;
+ qreal _a;
+
+ GfxEasingFunction *copy() const
+ {
+ ElasticEase *rv = new ElasticEase(_t);
+ rv->_p = _p;
+ rv->_a = _a;
+ return rv;
+ }
+
+ float value(float t, float b, float c, float d)
+ {
+ if (t==0) return b;
+ float t_adj = (float)t / (float)d;
+ if (t_adj==1) return b+c;
+
+ qreal p = _p?_p:(d * 0.3f);
+
+ qreal a;
+ qreal s;
+
+ if(!_a || _a < ::fabs(c)) {
+ a = c;
+ s = p / 4.0f;
+ } else {
+ a = _a;
+ s = p / (2 * M_PI) * ::asin(c / a);
+ }
+
+ if(_t == In)
+ t_adj -= 1.0f;
+
+ return (a*::pow(2,-10*t_adj) * ::sin( (t_adj*d-s)*(2*M_PI)/p ) + c + b);
+ }
+};
+
+struct BounceEase : public GfxEasingFunction
+{
+ enum Type { In, Out };
+ BounceEase(Type t) : _t(t), _a(-1.0) {}
+
+ Type _t;
+ qreal _a;
+
+ GfxEasingFunction *copy() const
+ {
+ BounceEase *rv = new BounceEase(_t);
+ rv->_t = _t;
+ rv->_a = _a;
+ return rv;
+ }
+
+ float value(float t, float b, float c, float d)
+ {
+ if(In == _t)
+ return c - bounce(d - t, 0, c, d) + b;
+ else
+ return bounce(t, b, c, d);
+ }
+
+ float bounce(float t, float b, float c, float d)
+ {
+ float t_adj = (float)t / (float)d;
+ float amp = (_a == -1.0)?c:_a;
+ if ((t_adj) < (1/2.75)) {
+ if(c == 0. && _a != -1.0) {
+ t_adj -= (0.5f/2.75f);
+ return -amp * (1. - (30.25*t_adj*t_adj)) + b;
+ } else {
+ return c*(7.5625*t_adj*t_adj) + b;
+ }
+ } else if (t_adj < (2/2.75)) {
+ t_adj -= (1.5f/2.75f);
+ return -amp * (1. - (7.5625*t_adj*t_adj + .75)) + (b + c);
+ } else if (t_adj < (2.5/2.75)) {
+ t_adj -= (2.25f/2.75f);
+ return -amp * (1. - (7.5625*t_adj*t_adj + .9375)) + (b + c);
+ } else {
+ t_adj -= (2.65f/2.75f);
+ return -amp * (1. - (7.5625*t_adj*t_adj + .984375)) + (b + c);
+ }
+ }
+};
+
+static GfxEasingFunction *easeInElasticC(const GfxEasingProperties &p)
+{
+ ElasticEase *rv = new ElasticEase(ElasticEase::In);
+ rv->_p = p[QLatin1String("period")];
+ rv->_a = p[QLatin1String("amplitude")];
+ return rv;
+}
+
+
+static GfxEasingFunction *easeOutElasticC(const GfxEasingProperties &p)
+{
+ ElasticEase *rv = new ElasticEase(ElasticEase::Out);
+ rv->_p = p[QLatin1String("period")];
+ rv->_a = p[QLatin1String("amplitude")];
+ return rv;
+}
+
+static GfxEasingFunction *easeOutBounceC(const GfxEasingProperties &p)
+{
+ BounceEase *rv = new BounceEase(BounceEase::Out);
+ rv->_a = p[QLatin1String("amplitude")];
+ return rv;
+}
+
+static GfxEasingFunction *easeInBounceC(const GfxEasingProperties &p)
+{
+ BounceEase *rv = new BounceEase(BounceEase::Out);
+ rv->_a = p[QLatin1String("amplitude")];
+ return rv;
+}
+
+
+struct SimpleConfig : public GfxEasingFunction
+{
+ GfxEasing::Function func;
+
+ float value(float t, float b, float c, float d)
+ {
+ return func(t, b, c, d);
+ }
+
+ GfxEasingFunction *copy() const
+ {
+ SimpleConfig *rv = new SimpleConfig;
+ rv->func = func;
+ return rv;
+ }
+};
+
+GfxEasing::Function curveToFunc(GfxEasing::Curve curve)
+{
+ switch(curve)
+ {
+ case GfxEasing::None:
+ return &easeNone;
+ case GfxEasing::InQuad:
+ return &easeInQuad;
+ case GfxEasing::OutQuad:
+ return &easeOutQuad;
+ case GfxEasing::InOutQuad:
+ return &easeInOutQuad;
+ case GfxEasing::OutInQuad:
+ return &easeOutInQuad;
+ case GfxEasing::InCubic:
+ return &easeInCubic;
+ case GfxEasing::OutCubic:
+ return &easeOutCubic;
+ case GfxEasing::InOutCubic:
+ return &easeInOutCubic;
+ case GfxEasing::OutInCubic:
+ return &easeOutInCubic;
+ case GfxEasing::InQuart:
+ return &easeInQuart;
+ case GfxEasing::OutQuart:
+ return &easeOutQuart;
+ case GfxEasing::InOutQuart:
+ return &easeInOutQuart;
+ case GfxEasing::OutInQuart:
+ return &easeOutInQuart;
+ case GfxEasing::InQuint:
+ return &easeInQuint;
+ case GfxEasing::OutQuint:
+ return &easeOutQuint;
+ case GfxEasing::InOutQuint:
+ return &easeInOutQuint;
+ case GfxEasing::OutInQuint:
+ return &easeOutInQuint;
+ case GfxEasing::InSine:
+ return &easeInSine;
+ case GfxEasing::OutSine:
+ return &easeOutSine;
+ case GfxEasing::InOutSine:
+ return &easeInOutSine;
+ case GfxEasing::OutInSine:
+ return &easeOutInSine;
+ case GfxEasing::InExpo:
+ return &easeInExpo;
+ case GfxEasing::OutExpo:
+ return &easeOutExpo;
+ case GfxEasing::InOutExpo:
+ return &easeInOutExpo;
+ case GfxEasing::OutInExpo:
+ return &easeOutInExpo;
+ case GfxEasing::InCirc:
+ return &easeInCirc;
+ case GfxEasing::OutCirc:
+ return &easeOutCirc;
+ case GfxEasing::InOutCirc:
+ return &easeInOutCirc;
+ case GfxEasing::OutInCirc:
+ return &easeOutInCirc;
+ case GfxEasing::InElastic:
+ return &easeInElastic;
+ case GfxEasing::OutElastic:
+ return &easeOutElastic;
+ case GfxEasing::InOutElastic:
+ return &easeInOutElastic;
+ case GfxEasing::OutInElastic:
+ return &easeOutInElastic;
+ case GfxEasing::InBack:
+ return &easeInBack;
+ case GfxEasing::OutBack:
+ return &easeOutBack;
+ case GfxEasing::InOutBack:
+ return &easeInOutBack;
+ case GfxEasing::OutInBack:
+ return &easeOutInBack;
+ case GfxEasing::InBounce:
+ return &easeInBounce;
+ case GfxEasing::OutBounce:
+ return &easeOutBounce;
+ case GfxEasing::InOutBounce:
+ return &easeInOutBounce;
+ case GfxEasing::OutInBounce:
+ return &easeOutInBounce;
+ default:
+ return 0;
+ };
+}
+
+struct NameFunctionMap : public QHash<QString, GfxEasing::Function>
+{
+ NameFunctionMap()
+ {
+ insert(QLatin1String("easeNone"), easeNone);
+ insert(QLatin1String("easeInQuad"), easeInQuad);
+ insert(QLatin1String("easeOutQuad"), easeOutQuad);
+ insert(QLatin1String("easeInOutQuad"), easeInOutQuad);
+ insert(QLatin1String("easeOutInQuad"), easeOutInQuad);
+ insert(QLatin1String("easeInCubic"), easeInCubic);
+ insert(QLatin1String("easeOutCubic"), easeOutCubic);
+ insert(QLatin1String("easeInOutCubic"), easeInOutCubic);
+ insert(QLatin1String("easeOutInCubic"), easeOutInCubic);
+ insert(QLatin1String("easeInQuart"), easeInQuart);
+ insert(QLatin1String("easeOutQuart"), easeOutQuart);
+ insert(QLatin1String("easeInOutQuart"), easeInOutQuart);
+ insert(QLatin1String("easeOutInQuart"), easeOutInQuart);
+ insert(QLatin1String("easeInQuint"), easeInQuint);
+ insert(QLatin1String("easeOutQuint"), easeOutQuint);
+ insert(QLatin1String("easeInOutQuint"), easeInOutQuint);
+ insert(QLatin1String("easeOutInQuint"), easeOutInQuint);
+ insert(QLatin1String("easeInSine"), easeInSine);
+ insert(QLatin1String("easeOutSine"), easeOutSine);
+ insert(QLatin1String("easeInOutSine"), easeInOutSine);
+ insert(QLatin1String("easeOutInSine"), easeOutInSine);
+ insert(QLatin1String("easeInExpo"), easeInExpo);
+ insert(QLatin1String("easeOutExpo"), easeOutExpo);
+ insert(QLatin1String("easeInOutExpo"), easeInOutExpo);
+ insert(QLatin1String("easeOutInExpo"), easeOutInExpo);
+ insert(QLatin1String("easeInCirc"), easeInCirc);
+ insert(QLatin1String("easeOutCirc"), easeOutCirc);
+ insert(QLatin1String("easeInOutCirc"), easeInOutCirc);
+ insert(QLatin1String("easeOutInCirc"), easeOutInCirc);
+ insert(QLatin1String("easeInElastic"), easeInElastic);
+ insert(QLatin1String("easeOutElastic"), easeOutElastic);
+ insert(QLatin1String("easeInOutElastic"), easeInOutElastic);
+ insert(QLatin1String("easeOutInElastic"), easeOutInElastic);
+ insert(QLatin1String("easeInBack"), easeInBack);
+ insert(QLatin1String("easeOutBack"), easeOutBack);
+ insert(QLatin1String("easeInOutBack"), easeInOutBack);
+ insert(QLatin1String("easeOutInBack"), easeOutInBack);
+ insert(QLatin1String("easeInBounce"), easeInBounce);
+ insert(QLatin1String("easeOutBounce"), easeOutBounce);
+ insert(QLatin1String("easeInOutBounce"), easeInOutBounce);
+ insert(QLatin1String("easeOutInBounce"), easeOutInBounce);
+ }
+};
+Q_GLOBAL_STATIC(NameFunctionMap, nameFunctionMap);
+
+typedef GfxEasingFunction *(*ConfigurableFunction)(const GfxEasingProperties &);
+struct ConfigFunctionMap : public QHash<QString, ConfigurableFunction>
+{
+ ConfigFunctionMap()
+ {
+ insert(QLatin1String("easeInElastic"), easeInElasticC);
+ insert(QLatin1String("easeOutElastic"), easeOutElasticC);
+ insert(QLatin1String("easeInBounce"), easeInBounceC);
+ insert(QLatin1String("easeOutBounce"), easeOutBounceC);
+ }
+};
+Q_GLOBAL_STATIC(ConfigFunctionMap, configFunctionMap);
+
+/*!
+ \class GfxEasing
+ \ingroup animation
+ \brief The GfxEasing class provides easing curves for controlling animation.
+
+ Easing curves describe a function that controls how a value changes over
+ time. Easing curves allow transitions from one value to another to appear
+ more natural than a simple linear motion would allow. The GfxEasing class
+ is usually used in conjunction with the GfxTimeLine class, but can be used
+ on its own.
+
+ To calculate the value at a given time, the easing curve function requires
+ the starting value, the final value and the total time to change from the
+ starting to the final value. When using the GfxEasing class with
+ GfxTimeLine, these values are supplied by the GfxTimeLine. When using
+ the GfxEasing class on its own, the programmer must specify them using
+ the GfxEasing::setFrom(), GfxEasing::setTo() and GfxEasing::setLength()
+ methods, or by passing them explicitly to the GfxEasing::valueAt() method.
+
+ For example,
+ \code
+ GfxEasing easing(GfxEasing::InOutQuad);
+ easing.setFrom(0);
+ easing.setTo(1000);
+ easing.setLength(1000);
+
+ for(int milliseconds = 0; milliseconds < 1000; ++milliseconds)
+ qWarning() << "Value at" << milliseconds << "milliseconds is
+ << easing.valueAt(milliseconds);
+ \endcode
+ will print the value at each millisecond for an InOutQuad transition from
+ 0 to 1000 over 1 second.
+
+ When using a GfxTimeLine, the values are communicated implicitly.
+ \code
+ GfxTimeLine timeline;
+ GfxValue value(0);
+
+ timeline.move(value, 1000, GfxEasing(GfxEasing::InOutQuad), 1000);
+ \endcode
+ In this case, any values set using the previous setter methods would be
+ ignored.
+ */
+
+/*!
+ \qmlproperty string NumericAnimation::easing
+ \brief the easing curve used for the transition.
+
+ Available values are:
+
+ \list
+ \i \e easeNone - Easing equation function for a simple linear tweening, with no easing.
+ \i \e easeInQuad - Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
+ \i \e easeOutQuad - Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity.
+ \i \e easeInOutQuad - Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuad - Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInCubic - Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity.
+ \i \e easeOutCubic - Easing equation function for a cubic (t^3) easing out: decelerating from zero velocity.
+ \i \e easeInOutCubic - Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInCubic - Easing equation function for a cubic (t^3) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInQuart - Easing equation function for a quartic (t^4) easing in: accelerating from zero velocity.
+ \i \e easeOutQuart - Easing equation function for a quartic (t^4) easing out: decelerating from zero velocity.
+ \i \e easeInOutQuart - Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuart - Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInQuint - Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity.
+ \i \e easeOutQuint - Easing equation function for a quintic (t^5) easing out: decelerating from zero velocity.
+ \i \e easeInOutQuint - Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInQuint - Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInSine - Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity.
+ \i \e easeOutSine - Easing equation function for a sinusoidal (sin(t)) easing out: decelerating from zero velocity.
+ \i \e easeInOutSine - Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInSine - Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInExpo - Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity.
+ \i \e easeOutExpo - Easing equation function for an exponential (2^t) easing out: decelerating from zero velocity.
+ \i \e easeInOutExpo - Easing equation function for an exponential (2^t) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInExpo - Easing equation function for an exponential (2^t) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInCirc - Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity.
+ \i \e easeOutCirc - Easing equation function for a circular (sqrt(1-t^2)) easing out: decelerating from zero velocity.
+ \i \e easeInOutCirc - Easing equation function for a circular (sqrt(1-t^2)) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInCirc - Easing equation function for a circular (sqrt(1-t^2)) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing in: accelerating from zero velocity. The peak amplitude can be set with the \i amplitude parameter, and the period of decay by the \i period parameter.
+ \i \e easeOutElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing out: decelerating from zero velocity. The peak amplitude can be set with the \i amplitude parameter, and the period of decay by the \i period parameter.
+ \i \e easeInOutElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInElastic - Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeInBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+ \i \e easeOutBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: decelerating from zero velocity.
+ \i \e easeInOutBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInBack - Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+ \i \e easeOutBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity.
+ \i \e easeInBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity.
+ \i \e easeInOutBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration.
+ \i \e easeOutInBounce - Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration.
+ \endlist
+*/
+
+/*!
+ \enum GfxEasing::Curve
+
+ The type of easing curve.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::None
+ Easing equation function for a simple linear tweening, with no easing.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InQuad
+ Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutQuad
+ Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutQuad
+ Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInQuad
+ Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InCubic
+ Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutCubic
+ Easing equation function for a cubic (t^3) easing out: decelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutCubic
+ Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInCubic
+ Easing equation function for a cubic (t^3) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InQuart
+ Easing equation function for a quartic (t^4) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutQuart
+ Easing equation function for a quartic (t^4) easing out: decelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutQuart
+ Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInQuart
+ Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InQuint
+ Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutQuint
+ Easing equation function for a quintic (t^5) easing out: decelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutQuint
+ Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInQuint
+ Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InSine
+ Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutSine
+ Easing equation function for a sinusoidal (sin(t)) easing out: decelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutSine
+ Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInSine
+ Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InExpo
+ Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutExpo
+ Easing equation function for an exponential (2^t) easing out: decelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutExpo
+ Easing equation function for an exponential (2^t) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInExpo
+ Easing equation function for an exponential (2^t) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InCirc
+ Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutCirc
+ Easing equation function for a circular (sqrt(1-t^2)) easing out: decelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutCirc
+ Easing equation function for a circular (sqrt(1-t^2)) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInCirc
+ Easing equation function for a circular (sqrt(1-t^2)) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InElastic
+ Easing equation function for an elastic (exponentially decaying sine wave) easing in: accelerating from zero velocity. The peak amplitude can be set with the \i amplitude parameter, and the period of decay by the \i period parameter.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutElastic
+ Easing equation function for an elastic (exponentially decaying sine wave) easing out: decelerating from zero velocity. The peak amplitude can be set with the \i amplitude parameter, and the period of decay by the \i period parameter.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutElastic
+ Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInElastic
+ Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InBack
+ Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutBack
+ Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: decelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutBack
+ Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInBack
+ Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutBounce
+ Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InBounce
+ Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::InOutBounce
+ Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration.
+*/
+/*!
+ \var GfxEasing::Curve GfxEasing::OutInBounce
+ Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration.
+*/
+
+/*!
+ Construct a linear easing object. This is equivalent to \c {GfxEasing(GfxEasing::None)}.
+ */
+GfxEasing::GfxEasing()
+: _config(0), _func(&easeNone), _b(0.), _c(1.), _d(1.)
+{
+}
+
+/*!
+ Construct an easing object with the given \a curve.
+ */
+GfxEasing::GfxEasing(Curve curve)
+: _config(0), _func(0), _b(0.), _c(1.), _d(1.)
+{
+ _func = curveToFunc(curve);
+ if(!_func) {
+ qWarning("GfxEasing: Invalid curve type %d", curve);
+ _func = &easeNone;
+ }
+}
+
+/*!
+ Construct an easing object with the given \a curve. If \a curve does not
+ describe a legal curve, a linear easing object is constructed.
+
+ Curve names have the form
+ \c {ease<CurveName>[(<arg>: <arg value>[, <arg2>: <arg value>])]}. The
+ \i CurveName is equivalent to the GfxEasing::Curve enum name. Some more
+ advanced curves can take arguments to further refine their behaviour. Where
+ applicable, these parameters are described in the corresponding
+ GfxEasing::Curve value documentation.
+
+ For example,
+ \code
+ GfxEasing easing("easeInOutQuad");
+ GfxEasing easing2("easeInElastic(period: 5, amplitude: 100)");
+ \endcode
+ */
+GfxEasing::GfxEasing(const QString &curve)
+: _config(0), _func(&easeNone), _b(0.), _c(1.), _d(1.)
+{
+ if(curve.contains(QLatin1Char('('))) {
+ QString easeName = curve.trimmed();
+ GfxEasingProperties prop;
+ if(!easeName.endsWith(QLatin1Char(')'))) {
+ qWarning("GfxEasing: Unmatched perenthesis in easing function '%s'",
+ curve.toLatin1().constData());
+ return;
+ }
+
+ int idx = easeName.indexOf(QLatin1Char('('));
+ QString prop_str =
+ easeName.mid(idx + 1, easeName.length() - 1 - idx - 1);
+ easeName = easeName.left(idx);
+
+ QStringList props = prop_str.split(QLatin1Char(','));
+ foreach(QString str, props) {
+ int sep = str.indexOf(QLatin1Char(':'));
+
+ if(sep == -1) {
+ qWarning("GfxEasing: Improperly specified property in easing function '%s'",
+ curve.toLatin1().constData());
+ return;
+ }
+
+ QString propName = str.left(sep).trimmed();
+ bool isOk;
+ qreal propValue = str.mid(sep + 1).trimmed().toDouble(&isOk);
+
+ if(propName.isEmpty() || !isOk) {
+ qWarning("GfxEasing: Improperly specified property in easing function '%s'",
+ curve.toLatin1().constData());
+ return;
+ }
+
+ prop.insert(propName, propValue);
+ }
+
+ QHash<QString, ConfigurableFunction>::Iterator iter =
+ configFunctionMap()->find(easeName);
+
+ if(iter != configFunctionMap()->end())
+ _config = (*iter)(prop);
+ } else {
+ if(nameFunctionMap()->contains(curve))
+ _func = *(nameFunctionMap()->find(curve));
+ }
+
+ if(!_func && !_config) {
+ qWarning("GfxEasing: Unknown easing curve '%s'",
+ curve.toLatin1().constData());
+ _func = &easeNone;
+ }
+}
+
+/*!
+ Construct a copy of \a other.
+ */
+GfxEasing::GfxEasing(const GfxEasing &other)
+: _config(0), _func(other._func), _b(other._b), _c(other._c), _d(other._d)
+{
+ if(other._config) _config = other._config->copy();
+}
+
+/*!
+ Copy \a other.
+ */
+GfxEasing &GfxEasing::operator=(const GfxEasing &other)
+{
+ if(_config) { delete _config; _config = 0; }
+ if(other._config) _config = other._config->copy();
+
+ _func = other._func;
+ _b = other._b;
+ _c = other._c;
+ _d = other._d;
+
+ return *this;
+}
+
+/*!
+ Returns true if this is a linear easing object.
+ */
+bool GfxEasing::isLinear() const
+{
+ return !_config && _func == &easeNone;
+}
+
+/*!
+ Return the starting value for the easing curve. By default this is 0.
+ */
+qreal GfxEasing::from() const
+{
+ return _b;
+}
+
+/*!
+ Set the starting value for the easing curve to \a from.
+ */
+void GfxEasing::setFrom(qreal from)
+{
+ _b = from;
+}
+
+/*!
+ Return the final value for the easing curve. By default this is 0.
+ */
+qreal GfxEasing::to() const
+{
+ return _c;
+}
+
+/*!
+ Set the final value for the easing curve to \a to.
+ */
+void GfxEasing::setTo(qreal to)
+{
+ _c = to;
+}
+
+/*!
+ Return the length of the easing curve, in milliseconds. By default this
+ is 1.
+ */
+qreal GfxEasing::length() const
+{
+ return _d;
+}
+
+/*!
+ Set the \a length of the easing curve, in milliseconds.
+ */
+void GfxEasing::setLength(qreal length)
+{
+ Q_ASSERT(length > 0);
+ _d = length;
+}
+
+/*!
+ Return the value for the easing curve at time \a t milliseconds, based on
+ the parameters returned by GfxEasing::from(), GfxEasing::to() and
+ GfxEasing::length().
+
+ \a t is clamped to (0, GfxEasing::length()).
+ */
+qreal GfxEasing::valueAt(qreal t) const
+{
+ if(t < 0) t = 0;
+ else if(t > length()) t = length();
+
+ if(_config)
+ return _config->value(t, _b, _c - _b, _d);
+ else
+ return _func(t, _b, _c - _b, _d);
+}
+
+/*
+ Return the value for the easing curve at time \a t milliseconds, based on
+ the provided parameters \a from, \a to and \a length. The values returned
+ from the object's GfxEasing::from(), GfxEasing::to() and GfxEasing::length()
+ methods are ignored.
+
+ \a t is clamped to (0, \a length).
+ */
+qreal GfxEasing::valueAt(qreal t, qreal from, qreal to, qreal length) const
+{
+ if(t < 0) t = 0;
+ else if(t > length) t = length;
+
+ if(_config)
+ return _config->value(t, from, to - from, length);
+ else
+ return _func(t, from, to - from, length);
+}
+
+/*!
+ \internal
+ */
+QStringList GfxEasing::curves()
+{
+ return nameFunctionMap()->keys();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/timeline/gfxeasing.h b/src/declarative/timeline/gfxeasing.h
new file mode 100644
index 0000000..c15aadc
--- /dev/null
+++ b/src/declarative/timeline/gfxeasing.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GFXEASING_H
+#define GFXEASING_H
+
+#include <qfxglobal.h>
+#include <QList>
+#include <QPair>
+#include <QWidget>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class GfxEasingFunction;
+class Q_DECLARATIVE_EXPORT GfxEasing
+{
+public:
+ enum Curve {
+ None,
+ InQuad, OutQuad, InOutQuad, OutInQuad,
+ InCubic, OutCubic, InOutCubic, OutInCubic,
+ InQuart, OutQuart, InOutQuart, OutInQuart,
+ InQuint, OutQuint, InOutQuint, OutInQuint,
+ InSine, OutSine, InOutSine, OutInSine,
+ InExpo, OutExpo, InOutExpo, OutInExpo,
+ InCirc, OutCirc, InOutCirc, OutInCirc,
+ InElastic, OutElastic, InOutElastic, OutInElastic,
+ InBack, OutBack, InOutBack, OutInBack,
+ InBounce, OutBounce, InOutBounce, OutInBounce
+ };
+
+ GfxEasing();
+ GfxEasing(Curve);
+ GfxEasing(const QString &);
+ GfxEasing(const GfxEasing &);
+ GfxEasing &operator=(const GfxEasing &);
+
+ bool isLinear() const;
+
+ qreal from() const;
+ void setFrom(qreal);
+ qreal to() const;
+ void setTo(qreal);
+ qreal length() const;
+ void setLength(qreal);
+
+ qreal valueAt(qreal t) const;
+ qreal valueAt(qreal t, qreal from, qreal to, qreal length) const;
+
+ static QStringList curves();
+
+ typedef float (*Function)(float t, float b, float c, float d);
+private:
+ GfxEasingFunction *_config;
+ Function _func;
+
+ qreal _b, _c, _d;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif
diff --git a/src/declarative/timeline/gfxtimeline.cpp b/src/declarative/timeline/gfxtimeline.cpp
new file mode 100644
index 0000000..36b18d0
--- /dev/null
+++ b/src/declarative/timeline/gfxtimeline.cpp
@@ -0,0 +1,946 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gfxtimeline.h"
+#include <QDebug>
+#include <QMutex>
+#include <QThread>
+#include <QWaitCondition>
+#include <QEvent>
+#include <QCoreApplication>
+#include "gfxeasing.h"
+#include <QTime>
+
+QT_BEGIN_NAMESPACE
+
+#define TIMETICK 5
+
+//
+// Timeline stuff
+//
+
+struct Update {
+ Update(GfxValue *_g, qreal _v)
+ : g(_g), v(_v) {}
+ Update(const GfxEvent &_e)
+ : g(0), v(0), e(_e) {}
+
+ GfxValue *g;
+ qreal v;
+ GfxEvent e;
+};
+
+struct QmlTimeLinePrivate
+{
+ QmlTimeLinePrivate(QmlTimeLine *);
+
+ struct Op {
+ enum Type {
+ Pause,
+ Set,
+ Move,
+ MoveBy,
+ Accel,
+ AccelDistance,
+ Execute
+ };
+ Op() {}
+ Op(Type t, int l, qreal v, qreal v2, int o,
+ const GfxEvent &ev = GfxEvent(), const GfxEasing &es = GfxEasing())
+ : type(t), length(l), value(v), value2(v2), order(o), event(ev),
+ easing(es) {}
+ Op(const Op &o)
+ : type(o.type), length(o.length), value(o.value), value2(o.value2),
+ order(o.order), event(o.event), easing(o.easing) {}
+ Op &operator=(const Op &o) {
+ type = o.type; length = o.length; value = o.value;
+ value2 = o.value2; order = o.order; event = o.event;
+ easing = o.easing;
+ return *this;
+ }
+
+ Type type;
+ int length;
+ qreal value;
+ qreal value2;
+
+ int order;
+ GfxEvent event;
+ GfxEasing easing;
+ };
+ struct TimeLine
+ {
+ TimeLine() : length(0), consumedOpLength(0), base(0.) {}
+ QList<Op> ops;
+ int length;
+ int consumedOpLength;
+ qreal base;
+ };
+
+ int length;
+ int syncPoint;
+ typedef QHash<QmlTimeLineObject *, TimeLine> Ops;
+ Ops ops;
+ QmlTimeLine *q;
+
+ void add(QmlTimeLineObject &, const Op &);
+ qreal value(const Op &op, int time, qreal base, bool *) const;
+
+ int advance(int);
+
+ bool clockRunning;
+ int prevTime;
+
+ int order;
+
+ QmlTimeLine::SyncMode syncMode;
+ int syncAdj;
+ QList<QPair<int, Update> > *updateQueue;
+};
+
+QmlTimeLinePrivate::QmlTimeLinePrivate(QmlTimeLine *parent)
+: length(0), syncPoint(0), q(parent), clockRunning(false), prevTime(0), order(0), syncMode(QmlTimeLine::LocalSync), syncAdj(0), updateQueue(0)
+{
+}
+
+void QmlTimeLinePrivate::add(QmlTimeLineObject &g, const Op &o)
+{
+ if(g._t && g._t != q) {
+ qWarning() << "QmlTimeLine: Cannot modify a GfxValue owned by"
+ << "another timeline.";
+ return;
+ }
+ g._t = q;
+
+ Ops::Iterator iter = ops.find(&g);
+ if(iter == ops.end()) {
+ iter = ops.insert(&g, TimeLine());
+ if(syncPoint > 0)
+ q->pause(g, syncPoint);
+ }
+ if(!iter->ops.isEmpty() &&
+ o.type == Op::Pause &&
+ iter->ops.last().type == Op::Pause) {
+ iter->ops.last().length += o.length;
+ iter->length += o.length;
+ } else {
+ iter->ops.append(o);
+ iter->length += o.length;
+ }
+
+ if(iter->length > length)
+ length = iter->length;
+
+ if(!clockRunning) {
+ q->stop();
+ prevTime = 0;
+ clockRunning = true;
+
+ if(syncMode == QmlTimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ q->start();
+/* q->tick(0);
+ if(syncMode == QmlTimeLine::LocalSync) {
+ syncAdj = -1;
+ } else {
+ syncAdj = 0;
+ }
+ */
+ }
+}
+
+qreal QmlTimeLinePrivate::value(const Op &op, int time, qreal base, bool *changed) const
+{
+ Q_ASSERT(time >= 0);
+ Q_ASSERT(time <= op.length);
+ *changed = true;
+
+ switch(op.type) {
+ case Op::Pause:
+ *changed = false;
+ return base;
+ case Op::Set:
+ return op.value;
+ case Op::Move:
+ if(time == 0) {
+ return base;
+ } else if(time == (op.length)) {
+ return op.value;
+ } else {
+ if(op.easing.isLinear()) {
+ qreal delta = op.value - base;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ return base + delta * pTime;
+ } else {
+ return op.easing.valueAt(time, base, op.value, op.length);
+ }
+ }
+ case Op::MoveBy:
+ if(time == 0) {
+ return base;
+ } else if(time == (op.length)) {
+ return base + op.value;
+ } else {
+ if(op.easing.isLinear()) {
+ qreal delta = op.value;
+ qreal pTime = (qreal)(time) / (qreal)op.length;
+ return base + delta * pTime;
+ } else {
+ return op.easing.valueAt(time, base, base + op.value, op.length);
+ }
+ }
+ case Op::Accel:
+ if(time == 0) {
+ return base;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal delta = op.value * t + 0.5f * op.value2 * t * t;
+ return base + delta;
+ }
+ case Op::AccelDistance:
+ if(time == 0) {
+ return base;
+ } else if(time == (op.length)) {
+ return base + op.value2;
+ } else {
+ qreal t = (qreal)(time) / 1000.0f;
+ qreal accel = -1.0f * 1000.0f * op.value / (qreal)op.length;
+ qreal delta = op.value * t + 0.5f * accel * t * t;
+ return base + delta;
+
+ }
+ case Op::Execute:
+ op.event.execute();
+ *changed = false;
+ return -1;
+ }
+
+ return base;
+}
+
+/*!
+ \class QmlTimeLine
+ \ingroup animation
+ \brief The QmlTimeLine class provides a timeline for controlling animations.
+
+ QmlTimeLine is similar to QTimeLine except:
+ \list
+ \i It updates GfxValue instances directly, rather than maintaining a single
+ current value.
+
+ For example, the following animates a simple value over 200 milliseconds:
+ \code
+ GfxValue v(<starting value>);
+ QmlTimeLine tl;
+ tl.move(v, 100., 200);
+ tl.start()
+ \endcode
+
+ If your program needs to know when values are changed, it can either
+ connect to the QmlTimeLine's updated() signal, or inherit from GfxValue
+ and reimplement the GfxValue::setValue() method.
+
+ \i Supports multiple GfxValue, arbitrary start and end values and allows
+ animations to be strung together for more complex effects.
+
+ For example, the following animation moves the x and y coordinates of
+ an object from wherever they are to the position (100, 100) in 50
+ milliseconds and then further animates them to (100, 200) in 50
+ milliseconds:
+
+ \code
+ GfxValue x(<starting value>);
+ GfxValue y(<starting value>);
+
+ QmlTimeLine tl;
+ tl.start();
+
+ tl.move(x, 100., 50);
+ tl.move(y, 100., 50);
+ tl.move(y, 200., 50);
+ \endcode
+
+ \i All QmlTimeLine instances share a single, synchronized clock.
+
+ Actions scheduled within the same event loop tick are scheduled
+ synchronously against each other, regardless of the wall time between the
+ scheduling. Synchronized scheduling applies both to within the same
+ QmlTimeLine and across separate QmlTimeLine's within the same process.
+
+ \endlist
+
+ Currently easing functions are not supported.
+*/
+
+
+/*!
+ Construct a new QmlTimeLine with the specified \a parent.
+*/
+QmlTimeLine::QmlTimeLine(QObject *parent)
+: QAbstractAnimation(parent)
+{
+ d = new QmlTimeLinePrivate(this);
+}
+
+/*!
+ Destroys the time line. Any inprogress animations are canceled, but not
+ completed.
+*/
+QmlTimeLine::~QmlTimeLine()
+{
+ for(QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ iter.key()->_t = 0;
+
+ delete d; d = 0;
+}
+
+/*!
+ \enum QmlTimeLine::SyncMode
+ */
+
+/*!
+ Return the timeline's synchronization mode.
+ */
+QmlTimeLine::SyncMode QmlTimeLine::syncMode() const
+{
+ return d->syncMode;
+}
+
+/*!
+ Set the timeline's synchronization mode to \a syncMode.
+ */
+void QmlTimeLine::setSyncMode(SyncMode syncMode)
+{
+ d->syncMode = syncMode;
+}
+
+/*!
+ Pause \a gfxValue for \a time milliseconds.
+*/
+void QmlTimeLine::pause(QmlTimeLineObject &obj, int time)
+{
+ if(time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Pause, time, 0., 0., d->order++);
+ d->add(obj, op);
+}
+
+/*!
+ Execute the \a event.
+ */
+void QmlTimeLine::execute(const GfxEvent &event)
+{
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Execute, 0, 0, 0., d->order++, event);
+ d->add(*event.eventObject(), op);
+}
+
+/*!
+ Set the \a value of \a gfxValue.
+*/
+void QmlTimeLine::set(GfxValue &gfxValue, qreal value)
+{
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Set, 0, value, 0., d->order++);
+ d->add(gfxValue, op);
+}
+
+/*!
+ Decelerate \a gfxValue from the starting \a velocity to zero at the
+ given \a acceleration rate. Although the \a acceleration is technically
+ a deceleration, it should always be positive. The QmlTimeLine will ensure
+ that the deceleration is in the opposite direction to the initial velocity.
+*/
+int QmlTimeLine::accel(GfxValue &gfxValue, qreal velocity, qreal acceleration)
+{
+ if((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(gfxValue, op);
+
+ return time;
+}
+
+/*!
+ \overload
+
+ Decelerate \a gfxValue from the starting \a velocity to zero at the
+ given \a acceleration rate over a maximum distance of maxDistance.
+
+ If necessary, QmlTimeLine will reduce the acceleration to ensure that the
+ entire operation does not require a move of more than \a maxDistance.
+ \a maxDistance should always be positive.
+*/
+int QmlTimeLine::accel(GfxValue &gfxValue, qreal velocity, qreal acceleration, qreal maxDistance)
+{
+ Q_ASSERT(acceleration >= 0.0f && maxDistance >= 0.0f);
+
+ qreal maxAccel = (velocity * velocity) / (2.0f * maxDistance);
+ if(maxAccel > acceleration)
+ acceleration = maxAccel;
+
+ if((velocity > 0.0f) == (acceleration > 0.0f))
+ acceleration = acceleration * -1.0f;
+
+ int time = static_cast<int>(-1000 * velocity / acceleration);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
+ d->add(gfxValue, op);
+
+ return time;
+}
+
+/*!
+ Decelerate \a gfxValue from the starting \a velocity to zero over the given
+ \a distance. This is like accel(), but the QmlTimeLine calculates the exact
+ deceleration to use.
+
+ \a distance should be positive.
+*/
+int QmlTimeLine::accelDistance(GfxValue &gfxValue, qreal velocity, qreal distance)
+{
+ if (distance == 0.0f || velocity == 0.0f)
+ return -1;
+ Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
+
+ int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
+
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
+ d->add(gfxValue, op);
+
+ return time;
+}
+
+/*!
+ Linearly change the \a gfxValue from its current value to the given
+ \a destination value over \a time milliseconds.
+*/
+void QmlTimeLine::move(GfxValue &gfxValue, qreal destination, int time)
+{
+ if(time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++);
+ d->add(gfxValue, op);
+}
+
+/*!
+ Change the \a gfxValue from its current value to the given \a destination
+ value over \a time milliseconds using the \a easing curve.
+ */
+void QmlTimeLine::move(GfxValue &gfxValue, qreal destination, const GfxEasing &easing, int time)
+{
+ if(time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++, GfxEvent(), easing);
+ d->add(gfxValue, op);
+}
+
+/*!
+ Linearly change the \a gfxValue from its current value by the \a change amount
+ over \a time milliseconds.
+*/
+void QmlTimeLine::moveBy(GfxValue &gfxValue, qreal change, int time)
+{
+ if(time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++);
+ d->add(gfxValue, op);
+}
+
+/*!
+ Change the \a gfxValue from its current value by the \a change amount over
+ \a time milliseconds using the \a easing curve.
+ */
+void QmlTimeLine::moveBy(GfxValue &gfxValue, qreal change, const GfxEasing &easing, int time)
+{
+ if(time <= 0) return;
+ QmlTimeLinePrivate::Op op(QmlTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++, GfxEvent(), easing);
+ d->add(gfxValue, op);
+}
+
+/*!
+ Cancel (but don't complete) all scheduled actions for \a gfxValue.
+*/
+void QmlTimeLine::reset(GfxValue &gfxValue)
+{
+ if(!gfxValue._t)
+ return;
+ if(gfxValue._t != this) {
+ qWarning() << "QmlTimeLine: Cannot reset a GfxValue owned by another timeline.";
+ return;
+ }
+ remove(&gfxValue);
+ gfxValue._t = 0;
+}
+
+int QmlTimeLine::duration() const
+{
+ return -1;
+}
+
+/*!
+ Synchronize the end point of \a gfxValue to the endpoint of \a syncTo
+ within this timeline.
+
+ Following operations on \a gfxValue in this timeline will be scheduled after
+ all the currently scheduled actions on \a syncTo are complete. In
+ psuedo-code this is equivalent to:
+ \code
+ QmlTimeLine::pause(gfxValue, min(0, length_of(syncTo) - length_of(gfxValue)))
+ \endcode
+*/
+void QmlTimeLine::sync(GfxValue &gfxValue, GfxValue &syncTo)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(&syncTo);
+ if(iter == d->ops.end())
+ return;
+ int length = iter->length;
+
+ iter = d->ops.find(&gfxValue);
+ if(iter == d->ops.end()) {
+ pause(gfxValue, length);
+ } else {
+ int glength = iter->length;
+ pause(gfxValue, length - glength);
+ }
+}
+
+/*!
+ Synchronize the end point of \a gfxValue to the endpoint of the longest
+ action currently scheduled in the timeline.
+
+ In psuedo-code, this is equivalent to:
+ \code
+ QmlTimeLine::pause(gfxValue, length_of(timeline) - length_of(gfxValue))
+ \endcode
+*/
+void QmlTimeLine::sync(GfxValue &gfxValue)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(&gfxValue);
+ if(iter == d->ops.end()) {
+ pause(gfxValue, d->length);
+ } else {
+ pause(gfxValue, d->length - iter->length);
+ }
+}
+
+/*!
+ Synchronize all currently and future scheduled values in this timeline to
+ the longest action currently scheduled.
+
+ For example:
+ \code
+ value1->setValue(0.);
+ value2->setValue(0.);
+ value3->setValue(0.);
+ QmlTimeLine tl;
+ ...
+ tl.move(value1, 10, 200);
+ tl.move(value2, 10, 100);
+ tl.sync();
+ tl.move(value2, 20, 100);
+ tl.move(value3, 20, 100);
+ \endcode
+
+ will result in:
+
+ \table
+ \header \o \o 0ms \o 50ms \o 100ms \o 150ms \o 200ms \o 250ms \o 300ms
+ \row \o value1 \o 0 \o 2.5 \o 5.0 \o 7.5 \o 10 \o 10 \o 10
+ \row \o value2 \o 0 \o 5.0 \o 10.0 \o 10.0 \o 10.0 \o 15.0 \o 20.0
+ \row \o value2 \o 0 \o 0 \o 0 \o 0 \o 0 \o 10.0 \o 20.0
+ \endtable
+*/
+
+/*void QmlTimeLine::sync()
+{
+ for(QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter)
+ pause(*iter.key(), d->length - iter->length);
+ d->syncPoint = d->length;
+}*/
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+void QmlTimeLine::setSyncPoint(int sp)
+{
+ d->syncPoint = sp;
+}
+
+/*!
+ \internal
+
+ Temporary hack.
+ */
+int QmlTimeLine::syncPoint() const
+{
+ return d->syncPoint;
+}
+
+/*!
+ Returns true if the timeline is active. An active timeline is one where
+ GfxValue actions are still pending.
+*/
+bool QmlTimeLine::isActive() const
+{
+ return !d->ops.isEmpty();
+}
+
+/*!
+ Completes the timeline. All queued actions are played to completion, and then discarded. For example,
+ \code
+ GfxValue v(0.);
+ QmlTimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.complete();
+ // v.value() == 100.
+ \endcode
+*/
+void QmlTimeLine::complete()
+{
+ d->advance(d->length);
+}
+
+/*!
+ Resets the timeline. All queued actions are discarded and GfxValue's retain their current value. For example,
+ \code
+ GfxValue v(0.);
+ QmlTimeLine tl;
+ tl.move(v, 100., 1000.);
+ // 500 ms passes
+ // v.value() == 50.
+ tl.clear();
+ // v.value() == 50.
+ \endcode
+*/
+void QmlTimeLine::clear()
+{
+ for(QmlTimeLinePrivate::Ops::ConstIterator iter = d->ops.begin(); iter != d->ops.end(); ++iter)
+ iter.key()->_t = 0;
+ d->ops.clear();
+ d->length = 0;
+ d->syncPoint = 0;
+ //XXX need stop here?
+}
+
+int QmlTimeLine::time() const
+{
+ return d->prevTime;
+}
+
+/*!
+ \fn void QmlTimeLine::updated()
+
+ Emitted each time the timeline modifies GfxValues. Even if multiple
+ GfxValues are changed, this signal is only emitted once for each clock tick.
+*/
+
+void QmlTimeLine::updateCurrentTime(int v)
+{
+ if(d->syncAdj == -1)
+ d->syncAdj = v;
+ v -= d->syncAdj;
+
+ int timeChanged = v - d->prevTime;
+#if 0
+ if(!timeChanged)
+ return;
+#endif
+ d->prevTime = v;
+ d->advance(timeChanged);
+ emit updated();
+
+ // Do we need to stop the clock?
+ if(d->ops.isEmpty()) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = false;
+ emit completed();
+ } /*else if(pauseTime > 0) {
+ GfxClock::cancelClock();
+ d->prevTime = 0;
+ GfxClock::pauseFor(pauseTime);
+ d->syncAdj = 0;
+ d->clockRunning = false;
+ }*/ else if(/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+ d->syncAdj = 0;
+ start();
+ }
+}
+
+bool operator<(const QPair<int, Update> &lhs,
+ const QPair<int, Update> &rhs)
+{
+ return lhs.first < rhs.first;
+}
+
+int QmlTimeLinePrivate::advance(int t)
+{
+ int pauseTime = -1;
+
+ // XXX - surely there is a more efficient way?
+ do {
+ pauseTime = -1;
+ // Minimal advance time
+ int advanceTime = t;
+ for(Ops::Iterator iter = ops.begin(); iter != ops.end(); ++iter) {
+ TimeLine &tl = *iter;
+ Op &op = tl.ops.first();
+ int length = op.length - tl.consumedOpLength;
+
+ if(length < advanceTime) {
+ advanceTime = length;
+ if(advanceTime == 0)
+ break;
+ }
+ }
+ t -= advanceTime;
+
+ // Process until then. A zero length advance time will only process
+ // sets.
+ QList<QPair<int, Update> > updates;
+
+ for(Ops::Iterator iter = ops.begin(); iter != ops.end(); ) {
+ GfxValue *v = static_cast<GfxValue *>(iter.key());
+ TimeLine &tl = *iter;
+ Q_ASSERT(!tl.ops.isEmpty());
+
+ do {
+ Op &op = tl.ops.first();
+ if(advanceTime == 0 && op.length != 0)
+ continue;
+
+ if(tl.consumedOpLength == 0 &&
+ op.type != Op::Pause &&
+ op.type != Op::Execute)
+ tl.base = v->value();
+
+ if((tl.consumedOpLength + advanceTime) == op.length) {
+ if(op.type == Op::Execute) {
+ updates << qMakePair(op.order, Update(op.event));
+ } else {
+ bool changed = false;
+ qreal val = value(op, op.length, tl.base, &changed);
+ if(changed)
+ updates << qMakePair(op.order, Update(v, val));
+ }
+ tl.length -= qMin(advanceTime, tl.length);
+ tl.consumedOpLength = 0;
+ tl.ops.removeFirst();
+ } else {
+ tl.consumedOpLength += advanceTime;
+ bool changed = false;
+ qreal val = value(op, tl.consumedOpLength, tl.base, &changed);
+ if(changed)
+ updates << qMakePair(op.order, Update(v, val));
+ tl.length -= qMin(advanceTime, tl.length);
+ break;
+ }
+
+ } while(!tl.ops.isEmpty() && advanceTime == 0 && tl.ops.first().length == 0);
+
+
+ if(tl.ops.isEmpty()) {
+ iter = ops.erase(iter);
+ v->_t = 0;
+ } else {
+ if(tl.ops.first().type == Op::Pause && pauseTime != 0) {
+ int opPauseTime = tl.ops.first().length - tl.consumedOpLength;
+ if(pauseTime == -1 || opPauseTime < pauseTime)
+ pauseTime = opPauseTime;
+ } else {
+ pauseTime = 0;
+ }
+ ++iter;
+ }
+ }
+
+ length -= qMin(length, advanceTime);
+ syncPoint -= advanceTime;
+
+ qSort(updates.begin(), updates.end());
+ updateQueue = &updates;
+ for(int ii = 0; ii < updates.count(); ++ii) {
+ const Update &v = updates.at(ii).second;
+ if(v.g)
+ v.g->setValue(v.v);
+ else
+ v.e.execute();
+ }
+ updateQueue = 0;
+ } while(t);
+
+ return pauseTime;
+}
+
+void QmlTimeLine::remove(QmlTimeLineObject *v)
+{
+ QmlTimeLinePrivate::Ops::Iterator iter = d->ops.find(v);
+ Q_ASSERT(iter != d->ops.end());
+
+ int len = iter->length;
+ d->ops.erase(iter);
+ if(len == d->length) {
+ // We need to recalculate the length
+ d->length = 0;
+ for(QmlTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
+ iter != d->ops.end();
+ ++iter) {
+
+ if(iter->length > d->length)
+ d->length = iter->length;
+
+ }
+ }
+ if(d->ops.isEmpty()) {
+ stop();
+ d->clockRunning = false;
+ } else if(/*!GfxClock::isActive()*/ state() != Running) {
+ stop();
+ d->prevTime = 0;
+ d->clockRunning = true;
+
+ if(d->syncMode == QmlTimeLine::LocalSync) {
+ d->syncAdj = -1;
+ } else {
+ d->syncAdj = 0;
+ }
+ start();
+ }
+
+ if(d->updateQueue) {
+ for(int ii = 0; ii < d->updateQueue->count(); ++ii) {
+ if(d->updateQueue->at(ii).second.g == v ||
+ d->updateQueue->at(ii).second.e.eventObject() == v) {
+ d->updateQueue->removeAt(ii);
+ --ii;
+ }
+ }
+ }
+
+
+}
+
+/*!
+ \class GfxValue
+ \ingroup animation
+ \brief The GfxValue class is modified by QmlTimeLine.
+*/
+
+/*!
+ \fn GfxValue::GfxValue(qreal value = 0)
+
+ Construct a new GfxValue with an initial \a value.
+*/
+
+/*!
+ \fn qreal GfxValue::value() const
+
+ Return the current value.
+*/
+
+/*!
+ \fn void GfxValue::setValue(qreal value)
+
+ Set the current \a value.
+*/
+
+/*!
+ \fn QmlTimeLine *GfxValue::timeLine() const
+
+ If a QmlTimeLine is operating on this value, return a pointer to it,
+ otherwise return null.
+*/
+
+
+QmlTimeLineObject::QmlTimeLineObject()
+: _t(0)
+{
+}
+
+QmlTimeLineObject::~QmlTimeLineObject()
+{
+ if(_t) {
+ _t->remove(this);
+ _t = 0;
+ }
+}
+
+GfxEvent::GfxEvent()
+: d0(0), d1(0), d2(0)
+{
+}
+
+GfxEvent::GfxEvent(const GfxEvent &o)
+: d0(o.d0), d1(o.d1), d2(o.d2)
+{
+}
+
+GfxEvent &GfxEvent::operator=(const GfxEvent &o)
+{
+ d0 = o.d0;
+ d1 = o.d1;
+ d2 = o.d2;
+ return *this;
+}
+
+void GfxEvent::execute() const
+{
+ d0(d1);
+}
+
+QmlTimeLineObject *GfxEvent::eventObject() const
+{
+ return d2;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/timeline/gfxtimeline.h b/src/declarative/timeline/gfxtimeline.h
new file mode 100644
index 0000000..0bdddaf
--- /dev/null
+++ b/src/declarative/timeline/gfxtimeline.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GFXTIMELINE_H
+#define GFXTIMELINE_H
+
+#include <QObject>
+#include <qfxglobal.h>
+#include <QAbstractAnimation>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class GfxEasing;
+class GfxValue;
+class GfxEvent;
+struct QmlTimeLinePrivate;
+class QmlTimeLineObject;
+class Q_DECLARATIVE_EXPORT QmlTimeLine : public QAbstractAnimation
+{
+Q_OBJECT
+public:
+ QmlTimeLine(QObject *parent = 0);
+ ~QmlTimeLine();
+
+ enum SyncMode { LocalSync, GlobalSync };
+ SyncMode syncMode() const;
+ void setSyncMode(SyncMode);
+
+ void pause(QmlTimeLineObject &, int);
+ void execute(const GfxEvent &);
+ void set(GfxValue &, qreal);
+
+ int accel(GfxValue &, qreal velocity, qreal accel);
+ int accel(GfxValue &, qreal velocity, qreal accel, qreal maxDistance);
+ int accelDistance(GfxValue &, qreal velocity, qreal distance);
+
+ void move(GfxValue &, qreal destination, int time = 500);
+ void move(GfxValue &, qreal destination, const GfxEasing &, int time = 500);
+ void moveBy(GfxValue &, qreal change, int time = 500);
+ void moveBy(GfxValue &, qreal change, const GfxEasing &, int time = 500);
+
+ void sync();
+ void setSyncPoint(int);
+ int syncPoint() const;
+
+ void sync(GfxValue &);
+ void sync(GfxValue &, GfxValue &);
+
+ void reset(GfxValue &);
+
+ void complete();
+ void clear();
+ bool isActive() const;
+
+ int time() const;
+
+ virtual int duration() const;
+Q_SIGNALS:
+ void updated();
+ void completed();
+
+protected:
+ virtual void updateCurrentTime(int);
+
+private:
+ void remove(QmlTimeLineObject *);
+ friend class QmlTimeLineObject;
+ friend struct QmlTimeLinePrivate;
+ QmlTimeLinePrivate *d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlTimeLineObject
+{
+public:
+ QmlTimeLineObject();
+ virtual ~QmlTimeLineObject();
+
+protected:
+ friend class QmlTimeLine;
+ friend struct QmlTimeLinePrivate;
+ QmlTimeLine *_t;
+};
+
+class Q_DECLARATIVE_EXPORT GfxValue : public QmlTimeLineObject
+{
+public:
+ GfxValue(qreal v = 0.) : _v(v) {}
+
+ qreal value() const { return _v; }
+ virtual void setValue(qreal v) { _v = v; }
+
+ QmlTimeLine *timeLine() const { return _t; }
+
+ operator qreal() const { return _v; }
+ GfxValue &operator=(qreal v) { setValue(v); return *this; }
+private:
+ friend class QmlTimeLine;
+ friend struct QmlTimeLinePrivate;
+ qreal _v;
+};
+
+class Q_DECLARATIVE_EXPORT GfxEvent
+{
+public:
+ GfxEvent();
+ GfxEvent(const GfxEvent &o);
+
+ template<class T, void (T::*method)()>
+ GfxEvent(QmlTimeLineObject *b, T *c)
+ {
+ d0 = &callFunc<T, method>;
+ d1 = (void *)c;
+ d2 = b;
+ }
+
+ template<class T, void (T::*method)()>
+ static GfxEvent gfxEvent(QmlTimeLineObject *b, T *c)
+ {
+ GfxEvent rv;
+ rv.d0 = &callFunc<T, method>;
+ rv.d1 = (void *)c;
+ rv.d2 = b;
+ return rv;
+ }
+
+ GfxEvent &operator=(const GfxEvent &o);
+ void execute() const;
+ QmlTimeLineObject *eventObject() const;
+
+private:
+ typedef void (*CallFunc)(void *c);
+
+ template <class T, void (T::*method)()>
+ static void callFunc(void *c)
+ {
+ T *cls = (T *)c;
+ (cls->*method)();
+ }
+ CallFunc d0;
+ void *d1;
+ QmlTimeLineObject *d2;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/timeline/gfxvalueproxy.h b/src/declarative/timeline/gfxvalueproxy.h
new file mode 100644
index 0000000..1eaf44e
--- /dev/null
+++ b/src/declarative/timeline/gfxvalueproxy.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GFXVALUEPROXY_H
+#define GFXVALUEPROXY_H
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+template<class T>
+class GfxValueProxy : public GfxValue
+{
+public:
+ GfxValueProxy(T *cls, void (T::*func)(qreal), qreal v = 0.)
+ : GfxValue(v), _class(cls), _setFunctionReal(func), _setFunctionInt(0)
+ {
+ Q_ASSERT(_class);
+ }
+
+ GfxValueProxy(T *cls, void (T::*func)(int), qreal v = 0.)
+ : GfxValue(v), _class(cls), _setFunctionReal(0), _setFunctionInt(func)
+ {
+ Q_ASSERT(_class);
+ }
+
+ virtual void setValue(qreal v)
+ {
+ GfxValue::setValue(v);
+ if(_setFunctionReal) (_class->*_setFunctionReal)(v);
+ else if(_setFunctionInt) (_class->*_setFunctionInt)((int)v);
+ }
+
+private:
+ T *_class;
+ void (T::*_setFunctionReal)(qreal);
+ void (T::*_setFunctionInt)(int);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif//GFXVALUEPROXY
diff --git a/src/declarative/timeline/timeline.pri b/src/declarative/timeline/timeline.pri
new file mode 100644
index 0000000..8994c78
--- /dev/null
+++ b/src/declarative/timeline/timeline.pri
@@ -0,0 +1,9 @@
+SOURCES += \
+ timeline/gfxeasing.cpp \
+ timeline/gfxtimeline.cpp \
+
+HEADERS += \
+ timeline/gfxeasing.h \
+ timeline/gfxtimeline.h \
+ timeline/gfxvalueproxy.h \
+