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