1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QABSTRACTANIMATIONJOB_P_H
5#define QABSTRACTANIMATIONJOB_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qtqmlglobal_p.h>
19#include <private/qanimationjobutil_p.h>
20#include <private/qdoubleendedlist_p.h>
21#include <QtCore/QObject>
22#include <QtCore/private/qabstractanimation_p.h>
23#include <vector>
24
25QT_REQUIRE_CONFIG(qml_animation);
26
27QT_BEGIN_NAMESPACE
28
29class QAnimationGroupJob;
30class QAnimationJobChangeListener;
31class QQmlAnimationTimer;
32
33class Q_QML_PRIVATE_EXPORT QAbstractAnimationJob : public QInheritedListNode
34{
35 Q_DISABLE_COPY(QAbstractAnimationJob)
36public:
37 enum Direction {
38 Forward,
39 Backward
40 };
41
42 enum State {
43 Stopped,
44 Paused,
45 Running
46 };
47
48 QAbstractAnimationJob();
49 virtual ~QAbstractAnimationJob();
50
51 //definition
52 inline QAnimationGroupJob *group() const {return m_group;}
53
54 inline int loopCount() const {return m_loopCount;}
55 void setLoopCount(int loopCount);
56
57 int totalDuration() const;
58 virtual int duration() const {return 0;}
59
60 inline QAbstractAnimationJob::Direction direction() const {return m_direction;}
61 void setDirection(QAbstractAnimationJob::Direction direction);
62
63 //state
64 inline int currentTime() const {return m_totalCurrentTime;}
65 inline int currentLoopTime() const {return m_currentTime;}
66 inline int currentLoop() const {return m_currentLoop;}
67 inline QAbstractAnimationJob::State state() const {return m_state;}
68 inline bool isRunning() { return m_state == Running; }
69 inline bool isStopped() { return m_state == Stopped; }
70 inline bool isPaused() { return m_state == Paused; }
71 void setDisableUserControl();
72 void setEnableUserControl();
73 bool userControlDisabled() const;
74
75 void setCurrentTime(int msecs);
76
77 void start();
78 void pause();
79 void resume();
80 void stop();
81 void complete();
82
83 enum ChangeType {
84 Completion = 0x01,
85 StateChange = 0x02,
86 CurrentLoop = 0x04,
87 CurrentTime = 0x08
88 };
89 Q_DECLARE_FLAGS(ChangeTypes, ChangeType)
90
91 void addAnimationChangeListener(QAnimationJobChangeListener *listener, QAbstractAnimationJob::ChangeTypes);
92 void removeAnimationChangeListener(QAnimationJobChangeListener *listener, QAbstractAnimationJob::ChangeTypes);
93
94 bool isGroup() const { return m_isGroup; }
95 bool isRenderThreadJob() const { return m_isRenderThreadJob; }
96 bool isRenderThreadProxy() const { return m_isRenderThreadProxy; }
97
98 SelfDeletable m_selfDeletable;
99protected:
100 virtual void updateCurrentTime(int) {}
101 virtual void updateLoopCount(int) {}
102 virtual void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
103 virtual void updateDirection(QAbstractAnimationJob::Direction direction);
104 virtual void topLevelAnimationLoopChanged() {}
105
106 virtual void debugAnimation(QDebug d) const;
107
108 void fireTopLevelAnimationLoopChanged();
109
110 void setState(QAbstractAnimationJob::State state);
111
112 void finished();
113 void stateChanged(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
114 void currentLoopChanged();
115 void directionChanged(QAbstractAnimationJob::Direction);
116 void currentTimeChanged(int currentTime);
117
118 //definition
119 int m_loopCount;
120 QAnimationGroupJob *m_group;
121 QAbstractAnimationJob::Direction m_direction;
122
123 //state
124 QAbstractAnimationJob::State m_state;
125 int m_totalCurrentTime;
126 int m_currentTime;
127 int m_currentLoop;
128 //records the finish time for an uncontrolled animation (used by animation groups)
129 int m_uncontrolledFinishTime;
130 int m_currentLoopStartTime; // used together with m_uncontrolledFinishTime
131
132 struct ChangeListener {
133 ChangeListener(QAnimationJobChangeListener *l, QAbstractAnimationJob::ChangeTypes t) : listener(l), types(t) {}
134 QAnimationJobChangeListener *listener;
135 QAbstractAnimationJob::ChangeTypes types;
136 bool operator==(const ChangeListener &other) const { return listener == other.listener && types == other.types; }
137 };
138 std::vector<ChangeListener> changeListeners;
139
140 QQmlAnimationTimer *m_timer = nullptr;
141
142 bool m_hasRegisteredTimer:1;
143 bool m_isPause:1;
144 bool m_isGroup:1;
145 bool m_disableUserControl:1;
146 bool m_hasCurrentTimeChangeListeners:1;
147 bool m_isRenderThreadJob:1;
148 bool m_isRenderThreadProxy:1;
149
150 friend class QQmlAnimationTimer;
151 friend class QAnimationGroupJob;
152 friend Q_QML_PRIVATE_EXPORT QDebug operator<<(QDebug, const QAbstractAnimationJob *job);
153};
154
155class Q_QML_PRIVATE_EXPORT QAnimationJobChangeListener
156{
157public:
158 virtual ~QAnimationJobChangeListener();
159 virtual void animationFinished(QAbstractAnimationJob *) {}
160 virtual void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) {}
161 virtual void animationCurrentLoopChanged(QAbstractAnimationJob *) {}
162 virtual void animationCurrentTimeChanged(QAbstractAnimationJob *, int) {}
163};
164
165class Q_QML_PRIVATE_EXPORT QQmlAnimationTimer : public QAbstractAnimationTimer
166{
167 Q_OBJECT
168private:
169 QQmlAnimationTimer();
170
171public:
172 ~QQmlAnimationTimer(); // must be destructible by QThreadStorage
173
174 static QQmlAnimationTimer *instance();
175 static QQmlAnimationTimer *instance(bool create);
176
177 void registerAnimation(QAbstractAnimationJob *animation, bool isTopLevel);
178 void unregisterAnimation(QAbstractAnimationJob *animation);
179
180 /*
181 this is used for updating the currentTime of all animations in case the pause
182 timer is active or, otherwise, only of the animation passed as parameter.
183 */
184 void ensureTimerUpdate();
185
186 /*
187 this will evaluate the need of restarting the pause timer in case there is still
188 some pause animations running.
189 */
190 void updateAnimationTimer();
191
192 void restartAnimationTimer() override;
193 void updateAnimationsTime(qint64 timeStep) override;
194
195 //useful for profiling/debugging
196 int runningAnimationCount() override { return animations.size(); }
197
198 bool hasStartAnimationPending() const { return startAnimationPending; }
199
200public Q_SLOTS:
201 void startAnimations();
202 void stopTimer();
203
204private:
205 qint64 lastTick;
206 int currentAnimationIdx;
207 bool insideTick;
208 bool startAnimationPending;
209 bool stopTimerPending;
210
211 QList<QAbstractAnimationJob*> animations, animationsToStart;
212
213 // this is the count of running animations that are not a group neither a pause animation
214 int runningLeafAnimations;
215 QList<QAbstractAnimationJob*> runningPauseAnimations;
216
217 void registerRunningAnimation(QAbstractAnimationJob *animation);
218 void unregisterRunningAnimation(QAbstractAnimationJob *animation);
219 void unsetJobTimer(QAbstractAnimationJob *animation);
220
221 int closestPauseAnimationTimeToFinish();
222};
223
224Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractAnimationJob::ChangeTypes)
225
226Q_QML_PRIVATE_EXPORT QDebug operator<<(QDebug, const QAbstractAnimationJob *job);
227
228QT_END_NAMESPACE
229
230#endif // QABSTRACTANIMATIONJOB_P_H
231

source code of qtdeclarative/src/qml/animations/qabstractanimationjob_p.h