Update ooo320-m1
[ooovba.git] / vcl / source / app / timer.cxx
blob25e1725acf6f012cb31327268b9560d62fc861bb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: timer.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #ifndef _SV_SVSYS_HXX
35 #include <svsys.h>
36 #endif
37 #include <vcl/saltimer.hxx>
38 #include <tools/time.hxx>
39 #include <vcl/svdata.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/salinst.hxx>
42 #include <tools/debug.hxx>
43 #include <vcl/timer.hxx>
47 // =======================================================================
49 #define MAX_TIMER_PERIOD ((ULONG)0xFFFFFFFF)
51 // ---------------------
52 // - TimeManager-Types -
53 // ---------------------
55 struct ImplTimerData
57 ImplTimerData* mpNext; // Pointer to the next Instance
58 Timer* mpSVTimer; // Pointer to SV Timer instance
59 ULONG mnUpdateTime; // Last Update Time
60 ULONG mnTimerUpdate; // TimerCallbackProcs on stack
61 BOOL mbDelete; // Wurde Timer waehren Update() geloescht
62 BOOL mbInTimeout; // Befinden wir uns im Timeout-Handler
65 // =======================================================================
67 void Timer::ImplDeInitTimer()
69 ImplSVData* pSVData = ImplGetSVData();
70 ImplTimerData* pTimerData = pSVData->mpFirstTimerData;
72 if ( pTimerData )
76 ImplTimerData* pTempTimerData = pTimerData;
77 if ( pTimerData->mpSVTimer )
79 pTimerData->mpSVTimer->mbActive = FALSE;
80 pTimerData->mpSVTimer->mpTimerData = NULL;
82 pTimerData = pTimerData->mpNext;
83 delete pTempTimerData;
85 while ( pTimerData );
87 pSVData->mpFirstTimerData = NULL;
88 pSVData->mnTimerPeriod = 0;
89 delete pSVData->mpSalTimer;
90 pSVData->mpSalTimer = NULL;
94 // -----------------------------------------------------------------------
96 static void ImplStartTimer( ImplSVData* pSVData, ULONG nMS )
98 if ( !nMS )
99 nMS = 1;
101 if ( nMS != pSVData->mnTimerPeriod )
103 pSVData->mnTimerPeriod = nMS;
104 pSVData->mpSalTimer->Start( nMS );
108 // -----------------------------------------------------------------------
110 void Timer::ImplTimerCallbackProc()
112 ImplSVData* pSVData = ImplGetSVData();
113 ImplTimerData* pTimerData;
114 ImplTimerData* pPrevTimerData;
115 ULONG nMinPeriod = MAX_TIMER_PERIOD;
116 ULONG nDeltaTime;
117 ULONG nTime = Time::GetSystemTicks();
119 if ( pSVData->mbNoCallTimer )
120 return;
122 pSVData->mnTimerUpdate++;
123 pSVData->mbNotAllTimerCalled = TRUE;
125 // Suche Timer raus, wo der Timeout-Handler gerufen werden muss
126 pTimerData = pSVData->mpFirstTimerData;
127 while ( pTimerData )
129 // Wenn Timer noch nicht neu ist und noch nicht geloescht wurde
130 // und er sich nicht im Timeout-Handler befindet,
131 // dann den Handler rufen, wenn die Zeit abgelaufen ist
132 if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
133 !pTimerData->mbDelete && !pTimerData->mbInTimeout )
135 // Zeit abgelaufen
136 if ( (pTimerData->mnUpdateTime+pTimerData->mpSVTimer->mnTimeout) <= nTime )
138 // Neue Updatezeit setzen
139 pTimerData->mnUpdateTime = nTime;
141 // kein AutoTimer, dann anhalten
142 if ( !pTimerData->mpSVTimer->mbAuto )
144 pTimerData->mpSVTimer->mbActive = FALSE;
145 pTimerData->mbDelete = TRUE;
148 // call Timeout
149 pTimerData->mbInTimeout = TRUE;
150 pTimerData->mpSVTimer->Timeout();
151 pTimerData->mbInTimeout = FALSE;
155 pTimerData = pTimerData->mpNext;
158 // Neue Zeit ermitteln
159 ULONG nNewTime = Time::GetSystemTicks();
160 pPrevTimerData = NULL;
161 pTimerData = pSVData->mpFirstTimerData;
162 while ( pTimerData )
164 // Befindet sich Timer noch im Timeout-Handler, dann ignorieren
165 if ( pTimerData->mbInTimeout )
167 pPrevTimerData = pTimerData;
168 pTimerData = pTimerData->mpNext;
170 // Wurde Timer zwischenzeitlich zerstoert ?
171 else if ( pTimerData->mbDelete )
173 if ( pPrevTimerData )
174 pPrevTimerData->mpNext = pTimerData->mpNext;
175 else
176 pSVData->mpFirstTimerData = pTimerData->mpNext;
177 if ( pTimerData->mpSVTimer )
178 pTimerData->mpSVTimer->mpTimerData = NULL;
179 ImplTimerData* pTempTimerData = pTimerData;
180 pTimerData = pTimerData->mpNext;
181 delete pTempTimerData;
183 else
185 pTimerData->mnTimerUpdate = 0;
186 // kleinste Zeitspanne ermitteln
187 if ( pTimerData->mnUpdateTime == nTime )
189 nDeltaTime = pTimerData->mpSVTimer->mnTimeout;
190 if ( nDeltaTime < nMinPeriod )
191 nMinPeriod = nDeltaTime;
193 else
195 nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpSVTimer->mnTimeout;
196 if ( nDeltaTime < nNewTime )
197 nMinPeriod = 1;
198 else
200 nDeltaTime -= nNewTime;
201 if ( nDeltaTime < nMinPeriod )
202 nMinPeriod = nDeltaTime;
205 pPrevTimerData = pTimerData;
206 pTimerData = pTimerData->mpNext;
210 // Wenn keine Timer mehr existieren, dann Clock loeschen
211 if ( !pSVData->mpFirstTimerData )
213 pSVData->mpSalTimer->Stop();
214 pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
216 else
217 ImplStartTimer( pSVData, nMinPeriod );
219 pSVData->mnTimerUpdate--;
220 pSVData->mbNotAllTimerCalled = FALSE;
223 // =======================================================================
225 Timer::Timer()
227 mpTimerData = NULL;
228 mnTimeout = 1;
229 mbAuto = FALSE;
230 mbActive = FALSE;
233 // -----------------------------------------------------------------------
235 Timer::Timer( const Timer& rTimer )
237 mpTimerData = NULL;
238 mnTimeout = rTimer.mnTimeout;
239 mbAuto = FALSE;
240 mbActive = FALSE;
241 maTimeoutHdl = rTimer.maTimeoutHdl;
243 if ( rTimer.IsActive() )
244 Start();
247 // -----------------------------------------------------------------------
249 Timer::~Timer()
251 if ( mpTimerData )
253 mpTimerData->mbDelete = TRUE;
254 mpTimerData->mpSVTimer = NULL;
258 // -----------------------------------------------------------------------
260 void Timer::Timeout()
262 maTimeoutHdl.Call( this );
265 // -----------------------------------------------------------------------
267 void Timer::SetTimeout( ULONG nNewTimeout )
269 mnTimeout = nNewTimeout;
271 // Wenn Timer aktiv, dann Clock erneuern
272 if ( mbActive )
274 ImplSVData* pSVData = ImplGetSVData();
275 if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
276 ImplStartTimer( pSVData, mnTimeout );
280 // -----------------------------------------------------------------------
282 void Timer::Start()
284 mbActive = TRUE;
286 ImplSVData* pSVData = ImplGetSVData();
287 if ( !mpTimerData )
289 if ( !pSVData->mpFirstTimerData )
291 pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
292 if( ! pSVData->mpSalTimer )
294 pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
295 pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
299 // insert timer and start
300 mpTimerData = new ImplTimerData;
301 mpTimerData->mpSVTimer = this;
302 mpTimerData->mnUpdateTime = Time::GetSystemTicks();
303 mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
304 mpTimerData->mbDelete = FALSE;
305 mpTimerData->mbInTimeout = FALSE;
307 // !!!!! Wegen SFX hinten einordnen !!!!!
308 ImplTimerData* pPrev = NULL;
309 ImplTimerData* pData = pSVData->mpFirstTimerData;
310 while ( pData )
312 pPrev = pData;
313 pData = pData->mpNext;
315 mpTimerData->mpNext = NULL;
316 if ( pPrev )
317 pPrev->mpNext = mpTimerData;
318 else
319 pSVData->mpFirstTimerData = mpTimerData;
321 if ( mnTimeout < pSVData->mnTimerPeriod )
322 ImplStartTimer( pSVData, mnTimeout );
324 else if( !mpTimerData->mpSVTimer ) // TODO: remove when guilty found
326 DBG_ERROR( "Timer::Start() on a destroyed Timer!" );
328 else
330 mpTimerData->mnUpdateTime = Time::GetSystemTicks();
331 mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate;
332 mpTimerData->mbDelete = FALSE;
336 // -----------------------------------------------------------------------
338 void Timer::Stop()
340 mbActive = FALSE;
342 if ( mpTimerData )
343 mpTimerData->mbDelete = TRUE;
346 // -----------------------------------------------------------------------
348 Timer& Timer::operator=( const Timer& rTimer )
350 if ( IsActive() )
351 Stop();
353 mbActive = FALSE;
354 mnTimeout = rTimer.mnTimeout;
355 maTimeoutHdl = rTimer.maTimeoutHdl;
357 if ( rTimer.IsActive() )
358 Start();
360 return *this;
363 // =======================================================================
365 AutoTimer::AutoTimer()
367 mbAuto = TRUE;
370 // -----------------------------------------------------------------------
372 AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
374 mbAuto = TRUE;
377 // -----------------------------------------------------------------------
379 AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
381 Timer::operator=( rTimer );
382 return *this;