1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include <svx/sdr/animation/scheduler.hxx>
27 
28 #include <vector>
29 
30 //////////////////////////////////////////////////////////////////////////////
31 // event class
32 
33 namespace sdr
34 {
35 	namespace animation
36 	{
Event(sal_uInt32 nTime)37 		Event::Event(sal_uInt32 nTime)
38 		:	mnTime(nTime),
39 			mpNext(0L)
40 		{
41 		}
42 
~Event()43 		Event::~Event()
44 		{
45 		}
46 
GetNext() const47 		Event* Event::GetNext() const
48 		{
49 			return mpNext;
50 		}
51 
SetNext(Event * pNew)52 		void Event::SetNext(Event* pNew)
53 		{
54 			if(pNew != mpNext)
55 			{
56 				mpNext = pNew;
57 			}
58 		}
59 
GetTime() const60 		sal_uInt32 Event::GetTime() const
61 		{
62 			return mnTime;
63 		}
64 
SetTime(sal_uInt32 nNew)65 		void Event::SetTime(sal_uInt32 nNew)
66 		{
67 			if(mnTime != nNew)
68 			{
69 				mnTime = nNew;
70 			}
71 		}
72 	} // end of namespace animation
73 } // end of namespace sdr
74 
75 //////////////////////////////////////////////////////////////////////////////
76 // eventlist class
77 
78 namespace sdr
79 {
80 	namespace animation
81 	{
EventList()82 		EventList::EventList()
83 		:	mpHead(0L)
84 		{
85 		}
86 
~EventList()87 		EventList::~EventList()
88 		{
89 			Clear();
90 		}
91 
Insert(Event * pNew)92 		void EventList::Insert(Event* pNew)
93 		{
94 			if(pNew)
95 			{
96 				Event* pCurrent = mpHead;
97 				Event* pPrev = 0L;
98 
99 				while(pCurrent && pCurrent->GetTime() < pNew->GetTime())
100 				{
101 					pPrev = pCurrent;
102 					pCurrent = pCurrent->GetNext();
103 				}
104 
105 				if(pPrev)
106 				{
107 					pNew->SetNext(pPrev->GetNext());
108 					pPrev->SetNext(pNew);
109 				}
110 				else
111 				{
112 					pNew->SetNext(mpHead);
113 					mpHead = pNew;
114 				}
115 			}
116 		}
117 
Remove(Event * pOld)118 		void EventList::Remove(Event* pOld)
119 		{
120 			if(pOld && mpHead)
121 			{
122 				Event* pCurrent = mpHead;
123 				Event* pPrev = 0L;
124 
125 				while(pCurrent && pCurrent != pOld)
126 				{
127 					pPrev = pCurrent;
128 					pCurrent = pCurrent->GetNext();
129 				}
130 
131 				if(pPrev)
132 				{
133 					pPrev->SetNext(pOld->GetNext());
134 				}
135 				else
136 				{
137 					mpHead = pOld->GetNext();
138 				}
139 
140 				pOld->SetNext(0L);
141 			}
142 		}
143 
Clear()144 		void EventList::Clear()
145 		{
146 			while(mpHead)
147 			{
148 				Event* pNext = mpHead->GetNext();
149 				mpHead->SetNext(0L);
150 				mpHead = pNext;
151 			}
152 		}
153 
GetFirst()154 		Event* EventList::GetFirst()
155 		{
156 			return mpHead;
157 		}
158 	} // end of namespace animation
159 } // end of namespace sdr
160 
161 //////////////////////////////////////////////////////////////////////////////
162 // scheduler class
163 
164 namespace sdr
165 {
166 	namespace animation
167 	{
Scheduler()168 		Scheduler::Scheduler()
169 		:	mnTime(0L),
170 			mnDeltaTime(0L),
171 			mbIsPaused(false)
172 		{
173 		}
174 
~Scheduler()175 		Scheduler::~Scheduler()
176 		{
177 			Stop();
178 		}
179 
Timeout()180 		void Scheduler::Timeout()
181 		{
182 			// stop timer and add time
183 			Stop();
184 			mnTime += mnDeltaTime;
185 
186 			// execute events
187 			triggerEvents();
188 
189 			// re-start or stop timer according to event list
190 			checkTimeout();
191 		}
192 
triggerEvents()193 		void Scheduler::triggerEvents()
194 		{
195 			Event* pNextEvent = maList.GetFirst();
196 
197 			if(pNextEvent)
198 			{
199 				// copy events which need to be executed to a vector. Remove them from
200 				// the scheduler
201 				::std::vector< Event* > EventPointerVector;
202 
203 				while(pNextEvent && pNextEvent->GetTime() <= mnTime)
204 				{
205 					maList.Remove(pNextEvent);
206 					EventPointerVector.push_back(pNextEvent);
207 					pNextEvent = maList.GetFirst();
208 				}
209 
210 				// execute events from the vector
211 				for(::std::vector< Event* >::iterator aCandidate = EventPointerVector.begin();
212 					aCandidate != EventPointerVector.end(); aCandidate++)
213 				{
214 					// trigger event. This may re-insert the event to the scheduler again
215 					(*aCandidate)->Trigger(mnTime);
216 				}
217 			}
218 		}
219 
checkTimeout()220 		void Scheduler::checkTimeout()
221 		{
222 			// re-start or stop timer according to event list
223 			if(!IsPaused() && maList.GetFirst())
224 			{
225 				mnDeltaTime = maList.GetFirst()->GetTime() - mnTime;
226 
227 				if(0L != mnDeltaTime)
228 				{
229 					SetTimeout(mnDeltaTime);
230 					Start();
231 				}
232 			}
233 			else
234 			{
235 				Stop();
236 			}
237 		}
238 
GetTime()239 		sal_uInt32 Scheduler::GetTime()
240 		{
241 			return mnTime;
242 		}
243 
244 		// #i38135#
SetTime(sal_uInt32 nTime)245 		void Scheduler::SetTime(sal_uInt32 nTime)
246 		{
247 			// reset time
248 			Stop();
249 			mnTime = nTime;
250 
251 			// get event pointer
252 			Event* pEvent = maList.GetFirst();
253 
254 			if(pEvent)
255 			{
256 				// retet event time points
257 				while(pEvent)
258 				{
259 					pEvent->SetTime(nTime);
260 					pEvent = pEvent->GetNext();
261 				}
262 
263 				if(!IsPaused())
264 				{
265 					// without delta time, init events by triggering them. This will invalidate
266 					// painted objects and add them to the scheduler again
267 					mnDeltaTime = 0L;
268 					triggerEvents();
269 					checkTimeout();
270 				}
271 			}
272 		}
273 
Reset(sal_uInt32 nTime)274 		void Scheduler::Reset(sal_uInt32 nTime)
275 		{
276 			mnTime = nTime;
277 			mnDeltaTime = 0L;
278 			maList.Clear();
279 		}
280 
InsertEvent(Event * pNew)281 		void Scheduler::InsertEvent(Event* pNew)
282 		{
283 			if(pNew)
284 			{
285 				maList.Insert(pNew);
286 				checkTimeout();
287 			}
288 		}
289 
RemoveEvent(Event * pOld)290 		void Scheduler::RemoveEvent(Event* pOld)
291 		{
292 			if(pOld && maList.GetFirst())
293 			{
294 				maList.Remove(pOld);
295 				checkTimeout();
296 			}
297 		}
298 
SetPaused(bool bNew)299 		void Scheduler::SetPaused(bool bNew)
300 		{
301 			if(bNew != mbIsPaused)
302 			{
303 				mbIsPaused = bNew;
304 				checkTimeout();
305 			}
306 		}
307 	} // end of namespace animation
308 } // end of namespace sdr
309 
310 //////////////////////////////////////////////////////////////////////////////
311 // eof
312