Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "PresenterTimer.hxx"
30 : : #include <osl/doublecheckedlocking.h>
31 : : #include <osl/thread.hxx>
32 : : #include <boost/bind.hpp>
33 : : #include <boost/function.hpp>
34 : : #include <boost/enable_shared_from_this.hpp>
35 : : #include <set>
36 : :
37 : : using namespace ::com::sun::star;
38 : : using namespace ::com::sun::star::uno;
39 : :
40 : : #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
41 : :
42 : : namespace sdext { namespace presenter {
43 : :
44 : : namespace {
45 : : class TimerTask
46 : : {
47 : : public:
48 : : TimerTask (
49 : : const PresenterTimer::Task& rTask,
50 : : const TimeValue& rDueTime,
51 : : const sal_Int64 nRepeatIntervall,
52 : : const sal_Int32 nTaskId);
53 : 0 : ~TimerTask (void) {}
54 : :
55 : : PresenterTimer::Task maTask;
56 : : TimeValue maDueTime;
57 : : const sal_Int64 mnRepeatIntervall;
58 : : const sal_Int32 mnTaskId;
59 : : bool mbIsCanceled;
60 : : };
61 : :
62 : : typedef ::boost::shared_ptr<TimerTask> SharedTimerTask;
63 : :
64 : : class TimerTaskComparator
65 : : {
66 : : public:
67 : 0 : bool operator() (const SharedTimerTask& rpTask1, const SharedTimerTask& rpTask2) const
68 : : {
69 : 0 : return rpTask1->maDueTime.Seconds < rpTask2->maDueTime.Seconds
70 : 0 : || (rpTask1->maDueTime.Seconds == rpTask2->maDueTime.Seconds
71 [ # # ]: 0 : && rpTask1->maDueTime.Nanosec < rpTask2->maDueTime.Nanosec);
[ # # # # ]
72 : : }
73 : : };
74 : :
75 : : /** Queue all scheduled tasks and process them when their time has come.
76 : : */
77 : : class TimerScheduler
78 : : : public ::boost::enable_shared_from_this<TimerScheduler>,
79 : : public ::osl::Thread
80 : : {
81 : : public:
82 : : static ::boost::shared_ptr<TimerScheduler> Instance (void);
83 : : static SharedTimerTask CreateTimerTask (
84 : : const PresenterTimer::Task& rTask,
85 : : const TimeValue& rDueTime,
86 : : const sal_Int64 nRepeatIntervall);
87 : :
88 : : void ScheduleTask (const SharedTimerTask& rpTask);
89 : : void CancelTask (const sal_Int32 nTaskId);
90 : :
91 : : static bool GetCurrentTime (TimeValue& rCurrentTime);
92 : : static sal_Int64 GetTimeDifference (
93 : : const TimeValue& rTargetTime,
94 : : const TimeValue& rCurrentTime);
95 : : static void ConvertToTimeValue (
96 : : TimeValue& rTimeValue,
97 : : const sal_Int64 nTimeDifference);
98 : : static sal_Int64 ConvertFromTimeValue (
99 : : const TimeValue& rTimeValue);
100 : :
101 : : private:
102 : : static ::boost::shared_ptr<TimerScheduler> mpInstance;
103 : : static ::osl::Mutex maInstanceMutex;
104 : : ::boost::shared_ptr<TimerScheduler> mpLateDestroy; // for clean exit
105 : : static sal_Int32 mnTaskId;
106 : :
107 : : ::osl::Mutex maTaskContainerMutex;
108 : : typedef ::std::set<SharedTimerTask,TimerTaskComparator> TaskContainer;
109 : : TaskContainer maScheduledTasks;
110 : : ::osl::Mutex maCurrentTaskMutex;
111 : : SharedTimerTask mpCurrentTask;
112 : :
113 : : static void Release (void);
114 : :
115 : : TimerScheduler (void);
116 : : virtual ~TimerScheduler (void);
117 [ # # ]: 0 : class Deleter {public: void operator () (TimerScheduler* pScheduler) { delete pScheduler; } };
118 : : friend class Deleter;
119 : :
120 : : virtual void SAL_CALL run (void);
121 : 0 : virtual void SAL_CALL onTerminated (void) { mpLateDestroy.reset(); }
122 : : };
123 : :
124 : : } // end of anonymous namespace
125 : :
126 : : //===== PresenterTimer ========================================================
127 : :
128 : 0 : sal_Int32 PresenterTimer::ScheduleRepeatedTask (
129 : : const Task& rTask,
130 : : const sal_Int64 nDelay,
131 : : const sal_Int64 nIntervall)
132 : : {
133 : : TimeValue aCurrentTime;
134 [ # # ][ # # ]: 0 : if (TimerScheduler::GetCurrentTime(aCurrentTime))
135 : : {
136 : : TimeValue aDueTime;
137 : : TimerScheduler::ConvertToTimeValue(
138 : : aDueTime,
139 [ # # ]: 0 : TimerScheduler::ConvertFromTimeValue (aCurrentTime) + nDelay);
140 [ # # ]: 0 : SharedTimerTask pTask (TimerScheduler::CreateTimerTask(rTask, aDueTime, nIntervall));
141 [ # # ][ # # ]: 0 : TimerScheduler::Instance()->ScheduleTask(pTask);
[ # # ]
142 [ # # ]: 0 : return pTask->mnTaskId;
143 : : }
144 : :
145 : 0 : return NotAValidTaskId;
146 : : }
147 : :
148 : 0 : void PresenterTimer::CancelTask (const sal_Int32 nTaskId)
149 : : {
150 [ # # ]: 0 : return TimerScheduler::Instance()->CancelTask(nTaskId);
151 : : }
152 : :
153 : : //===== TimerScheduler ========================================================
154 : :
155 : 8 : ::boost::shared_ptr<TimerScheduler> TimerScheduler::mpInstance;
156 : 8 : ::osl::Mutex TimerScheduler::maInstanceMutex;
157 : : sal_Int32 TimerScheduler::mnTaskId = PresenterTimer::NotAValidTaskId;
158 : :
159 : 0 : ::boost::shared_ptr<TimerScheduler> TimerScheduler::Instance (void)
160 : : {
161 [ # # ]: 0 : ::osl::MutexGuard aGuard (maInstanceMutex);
162 [ # # ]: 0 : if (mpInstance.get() == NULL)
163 : : {
164 [ # # ][ # # ]: 0 : mpInstance.reset(new TimerScheduler(), TimerScheduler::Deleter());
165 [ # # ]: 0 : mpInstance->create();
166 : : }
167 [ # # ][ # # ]: 0 : return mpInstance;
168 : : }
169 : :
170 : 0 : TimerScheduler::TimerScheduler (void)
171 : : : maTaskContainerMutex(),
172 : : maScheduledTasks(),
173 : : maCurrentTaskMutex(),
174 [ # # ][ # # ]: 0 : mpCurrentTask()
[ # # ][ # # ]
[ # # ]
175 : : {
176 : 0 : }
177 : :
178 [ # # ][ # # ]: 0 : TimerScheduler::~TimerScheduler (void)
[ # # ][ # # ]
[ # # ]
179 : : {
180 [ # # ]: 0 : }
181 : :
182 : 0 : SharedTimerTask TimerScheduler::CreateTimerTask (
183 : : const PresenterTimer::Task& rTask,
184 : : const TimeValue& rDueTime,
185 : : const sal_Int64 nRepeatIntervall)
186 : : {
187 [ # # ]: 0 : return SharedTimerTask(new TimerTask(rTask, rDueTime, nRepeatIntervall, ++mnTaskId));
188 : : }
189 : :
190 : 0 : void TimerScheduler::ScheduleTask (const SharedTimerTask& rpTask)
191 : : {
192 [ # # ]: 0 : if (rpTask.get() == NULL)
193 : 0 : return;
194 [ # # ]: 0 : if (rpTask->mbIsCanceled)
195 : 0 : return;
196 : :
197 : : {
198 [ # # ]: 0 : osl::MutexGuard aTaskGuard (maTaskContainerMutex);
199 [ # # ][ # # ]: 0 : maScheduledTasks.insert(rpTask);
200 : : }
201 : : }
202 : :
203 : 0 : void TimerScheduler::CancelTask (const sal_Int32 nTaskId)
204 : : {
205 : : // Set of scheduled tasks is sorted after their due times, not their
206 : : // task ids. Therefore we have to do a linear search for the task to
207 : : // cancel.
208 : : {
209 [ # # ]: 0 : ::osl::MutexGuard aGuard (maTaskContainerMutex);
210 : 0 : TaskContainer::iterator iTask (maScheduledTasks.begin());
211 : 0 : TaskContainer::const_iterator iEnd (maScheduledTasks.end());
212 [ # # ]: 0 : for ( ; iTask!=iEnd; ++iTask)
213 : : {
214 [ # # ]: 0 : if ((*iTask)->mnTaskId == nTaskId)
215 : : {
216 [ # # ]: 0 : maScheduledTasks.erase(iTask);
217 : 0 : break;
218 : : }
219 [ # # ]: 0 : }
220 : : }
221 : :
222 : : // The task that is to be canceled may be currently about to be
223 : : // processed. Mark it with a flag that a) prevents a repeating task
224 : : // from being scheduled again and b) tries to prevent its execution.
225 : : {
226 [ # # ]: 0 : ::osl::MutexGuard aGuard (maCurrentTaskMutex);
227 [ # # # # ]: 0 : if (mpCurrentTask.get() != NULL
[ # # ]
228 : 0 : && mpCurrentTask->mnTaskId == nTaskId)
229 [ # # ]: 0 : mpCurrentTask->mbIsCanceled = true;
230 : : }
231 : :
232 : : // Let the main-loop cleanup in it's own time
233 : 0 : }
234 : :
235 : 0 : void SAL_CALL TimerScheduler::run (void)
236 : : {
237 : 0 : while (1)
238 : : {
239 : : // Get the current time.
240 : : TimeValue aCurrentTime;
241 [ # # ][ # # ]: 0 : if ( ! GetCurrentTime(aCurrentTime))
242 : : {
243 : : // We can not get the current time and thus can not schedule anything.
244 : : break;
245 : : }
246 : :
247 : : // Restrict access to the maScheduledTasks member to one, mutext
248 : : // guarded, block.
249 [ # # ]: 0 : SharedTimerTask pTask;
250 : 0 : sal_Int64 nDifference = 0;
251 : : {
252 [ # # ]: 0 : ::osl::MutexGuard aGuard (maTaskContainerMutex);
253 : :
254 : : // There are no more scheduled task. Leave this loop, function and
255 : : // live of the TimerScheduler.
256 [ # # ]: 0 : if (maScheduledTasks.empty())
257 : : break;
258 : :
259 : : nDifference = GetTimeDifference(
260 : 0 : (*maScheduledTasks.begin())->maDueTime,
261 [ # # ]: 0 : aCurrentTime);
262 [ # # ]: 0 : if (nDifference <= 0)
263 : : {
264 [ # # ]: 0 : pTask = *maScheduledTasks.begin();
265 [ # # ]: 0 : maScheduledTasks.erase(maScheduledTasks.begin());
266 [ # # ][ # # ]: 0 : }
267 : : }
268 : :
269 : : // Acquire a reference to the current task.
270 : : {
271 [ # # ]: 0 : ::osl::MutexGuard aGuard (maCurrentTaskMutex);
272 [ # # ][ # # ]: 0 : mpCurrentTask = pTask;
273 : : }
274 : :
275 [ # # ]: 0 : if (pTask.get() == NULL)
276 : : {
277 : : // Wait until the first task becomes due.
278 : : TimeValue aTimeValue;
279 [ # # ]: 0 : ConvertToTimeValue(aTimeValue, nDifference);
280 [ # # ]: 0 : wait(aTimeValue);
281 : : }
282 : : else
283 : : {
284 : : // Execute task.
285 [ # # # # ]: 0 : if ( ! pTask->maTask.empty()
[ # # ]
286 : 0 : && ! pTask->mbIsCanceled)
287 : : {
288 [ # # ]: 0 : pTask->maTask(aCurrentTime);
289 : :
290 : : // Re-schedule repeating tasks.
291 [ # # ]: 0 : if (pTask->mnRepeatIntervall > 0)
292 : : {
293 : : ConvertToTimeValue(
294 : 0 : pTask->maDueTime,
295 : 0 : ConvertFromTimeValue(pTask->maDueTime)
296 [ # # ]: 0 : + pTask->mnRepeatIntervall);
297 [ # # ]: 0 : ScheduleTask(pTask);
298 : : }
299 : : }
300 : :
301 : : }
302 : :
303 : : // Release reference to the current task.
304 : : {
305 [ # # ]: 0 : ::osl::MutexGuard aGuard (maCurrentTaskMutex);
306 [ # # ][ # # ]: 0 : mpCurrentTask.reset();
307 : : }
308 [ # # ][ # # ]: 0 : }
309 : :
310 : : // While holding maInstanceMutex
311 [ # # ]: 0 : osl::Guard< osl::Mutex > aInstance( maInstanceMutex );
312 [ # # ]: 0 : mpLateDestroy = mpInstance;
313 [ # # ][ # # ]: 0 : mpInstance.reset();
314 : 0 : }
315 : :
316 : 0 : bool TimerScheduler::GetCurrentTime (TimeValue& rCurrentTime)
317 : : {
318 : : TimeValue aSystemTime;
319 [ # # ][ # # ]: 0 : if (osl_getSystemTime(&aSystemTime))
320 [ # # ]: 0 : return osl_getLocalTimeFromSystemTime(&aSystemTime, &rCurrentTime);
321 : 0 : return false;
322 : : }
323 : :
324 : 0 : sal_Int64 TimerScheduler::GetTimeDifference (
325 : : const TimeValue& rTargetTime,
326 : : const TimeValue& rCurrentTime)
327 : : {
328 : 0 : return ConvertFromTimeValue(rTargetTime) - ConvertFromTimeValue(rCurrentTime);
329 : : }
330 : :
331 : 0 : void TimerScheduler::ConvertToTimeValue (
332 : : TimeValue& rTimeValue,
333 : : const sal_Int64 nTimeDifference)
334 : : {
335 : 0 : rTimeValue.Seconds = sal::static_int_cast<sal_Int32>(nTimeDifference / 1000000000L);
336 : 0 : rTimeValue.Nanosec = sal::static_int_cast<sal_Int32>(nTimeDifference % 1000000000L);
337 : 0 : }
338 : :
339 : 0 : sal_Int64 TimerScheduler::ConvertFromTimeValue (
340 : : const TimeValue& rTimeValue)
341 : : {
342 : 0 : return sal_Int64(rTimeValue.Seconds) * 1000000000L + rTimeValue.Nanosec;
343 : : }
344 : :
345 : : //===== TimerTask =============================================================
346 : :
347 : : namespace {
348 : :
349 : 0 : TimerTask::TimerTask (
350 : : const PresenterTimer::Task& rTask,
351 : : const TimeValue& rDueTime,
352 : : const sal_Int64 nRepeatIntervall,
353 : : const sal_Int32 nTaskId)
354 : : : maTask(rTask),
355 : : maDueTime(rDueTime),
356 : : mnRepeatIntervall(nRepeatIntervall),
357 : : mnTaskId(nTaskId),
358 : 0 : mbIsCanceled(false)
359 : : {
360 : 0 : }
361 : :
362 : : } // end of anonymous namespace
363 : :
364 : : //===== PresenterTimer ========================================================
365 : :
366 : 8 : ::rtl::Reference<PresenterClockTimer> PresenterClockTimer::mpInstance;
367 : :
368 : 0 : ::rtl::Reference<PresenterClockTimer> PresenterClockTimer::Instance (
369 : : const css::uno::Reference<css::uno::XComponentContext>& rxContext)
370 : : {
371 [ # # ][ # # ]: 0 : ::osl::MutexGuard aSolarGuard (::osl::Mutex::getGlobalMutex());
372 : :
373 : 0 : ::rtl::Reference<PresenterClockTimer> pTimer;
374 [ # # ]: 0 : if (mpInstance.is())
375 : : {
376 [ # # ]: 0 : pTimer = mpInstance;
377 : : }
378 [ # # ]: 0 : if ( ! pTimer.is())
379 : : {
380 [ # # ][ # # ]: 0 : pTimer = ::rtl::Reference<PresenterClockTimer>(new PresenterClockTimer(rxContext));
381 [ # # ]: 0 : mpInstance = pTimer;
382 : : }
383 [ # # ]: 0 : return pTimer;
384 : : }
385 : :
386 : 0 : PresenterClockTimer::PresenterClockTimer (const Reference<XComponentContext>& rxContext)
387 : : : PresenterClockTimerInterfaceBase(m_aMutex),
388 : : maListeners(),
389 : : maDateTime(),
390 : : mnTimerTaskId(PresenterTimer::NotAValidTaskId),
391 : : mbIsCallbackPending(false),
392 [ # # ][ # # ]: 0 : mxRequestCallback()
393 : : {
394 : : Reference<lang::XMultiComponentFactory> xFactory (
395 [ # # ][ # # ]: 0 : rxContext->getServiceManager(), UNO_QUERY);
[ # # ]
396 [ # # ]: 0 : if (xFactory.is())
397 : : mxRequestCallback = Reference<awt::XRequestCallback>(
398 [ # # ]: 0 : xFactory->createInstanceWithContext(
399 : : A2S("com.sun.star.awt.AsyncCallback"),
400 : 0 : rxContext),
401 [ # # ][ # # ]: 0 : UNO_QUERY_THROW);
[ # # ][ # # ]
402 : 0 : }
403 : :
404 [ # # ][ # # ]: 0 : PresenterClockTimer::~PresenterClockTimer (void)
405 : : {
406 [ # # ]: 0 : if (mnTimerTaskId != PresenterTimer::NotAValidTaskId)
407 : : {
408 [ # # ]: 0 : PresenterTimer::CancelTask(mnTimerTaskId);
409 : 0 : mnTimerTaskId = PresenterTimer::NotAValidTaskId;
410 : : }
411 : :
412 [ # # ]: 0 : Reference<lang::XComponent> xComponent (mxRequestCallback, UNO_QUERY);
413 [ # # ]: 0 : if (xComponent.is())
414 [ # # ][ # # ]: 0 : xComponent->dispose();
415 [ # # ]: 0 : mxRequestCallback = NULL;
416 [ # # ]: 0 : }
417 : :
418 : 0 : void PresenterClockTimer::AddListener (const SharedListener& rListener)
419 : : {
420 [ # # ]: 0 : osl::MutexGuard aGuard (maMutex);
421 : :
422 [ # # ]: 0 : maListeners.push_back(rListener);
423 : :
424 : : // Create a timer task when the first listener is added.
425 [ # # ]: 0 : if (mnTimerTaskId==PresenterTimer::NotAValidTaskId)
426 : : {
427 : : mnTimerTaskId = PresenterTimer::ScheduleRepeatedTask(
428 : : ::boost::bind(&PresenterClockTimer::CheckCurrentTime, this, _1),
429 : : 0,
430 [ # # ][ # # ]: 0 : 250000000 /*ns*/);
[ # # ][ # # ]
431 [ # # ]: 0 : }
432 : 0 : }
433 : :
434 : 0 : void PresenterClockTimer::RemoveListener (const SharedListener& rListener)
435 : : {
436 [ # # ]: 0 : osl::MutexGuard aGuard (maMutex);
437 : :
438 : : ListenerContainer::iterator iListener (::std::find(
439 : : maListeners.begin(),
440 : : maListeners.end(),
441 [ # # ]: 0 : rListener));
442 [ # # ][ # # ]: 0 : if (iListener != maListeners.end())
443 [ # # ]: 0 : maListeners.erase(iListener);
444 [ # # ]: 0 : if (maListeners.empty())
445 : : {
446 : : // We have no more clients and therefore are not interested in time changes.
447 [ # # ]: 0 : if (mnTimerTaskId != PresenterTimer::NotAValidTaskId)
448 : : {
449 [ # # ]: 0 : PresenterTimer::CancelTask(mnTimerTaskId);
450 : 0 : mnTimerTaskId = PresenterTimer::NotAValidTaskId;
451 : : }
452 [ # # ]: 0 : mpInstance = NULL;
453 [ # # ]: 0 : }
454 : 0 : }
455 : :
456 : 0 : oslDateTime PresenterClockTimer::GetCurrentTime (void)
457 : : {
458 : : TimeValue aCurrentTime;
459 [ # # ]: 0 : TimerScheduler::GetCurrentTime(aCurrentTime);
460 : : oslDateTime aDateTime;
461 [ # # ]: 0 : osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime);
462 : 0 : return aDateTime;
463 : : }
464 : :
465 : 0 : void PresenterClockTimer::CheckCurrentTime (const TimeValue& rCurrentTime)
466 : : {
467 : 0 : css::uno::Reference<css::awt::XRequestCallback> xRequestCallback;
468 : 0 : css::uno::Reference<css::awt::XCallback> xCallback;
469 : : {
470 [ # # ]: 0 : osl::MutexGuard aGuard (maMutex);
471 : :
472 : 0 : TimeValue aCurrentTime (rCurrentTime);
473 : : oslDateTime aDateTime;
474 [ # # ][ # # ]: 0 : if (osl_getDateTimeFromTimeValue(&aCurrentTime, &aDateTime))
475 : : {
476 [ # # ][ # # ]: 0 : if (aDateTime.Seconds != maDateTime.Seconds
[ # # ]
477 : : || aDateTime.Minutes != maDateTime.Minutes
478 : : || aDateTime.Hours != maDateTime.Hours)
479 : : {
480 : : // The displayed part of the current time has changed.
481 : : // Prepare to call the listeners.
482 : 0 : maDateTime = aDateTime;
483 : :
484 : : // Schedule notification of listeners.
485 [ # # ][ # # ]: 0 : if (mxRequestCallback.is() && ! mbIsCallbackPending)
[ # # ]
486 : : {
487 : 0 : mbIsCallbackPending = true;
488 [ # # ]: 0 : xRequestCallback = mxRequestCallback;
489 [ # # ]: 0 : xCallback = this;
490 : : }
491 : : }
492 [ # # ]: 0 : }
493 : : }
494 [ # # ][ # # ]: 0 : if (mxRequestCallback.is() && xCallback.is())
[ # # ]
495 [ # # ][ # # ]: 0 : xRequestCallback->addCallback(xCallback, Any());
496 : 0 : }
497 : :
498 : : //----- XCallback -------------------------------------------------------------
499 : :
500 : 0 : void SAL_CALL PresenterClockTimer::notify (const css::uno::Any& rUserData)
501 : : throw (css::uno::RuntimeException)
502 : : {
503 : : (void)rUserData;
504 : :
505 [ # # ]: 0 : ListenerContainer aListenerCopy (maListeners);
506 : :
507 : : {
508 [ # # ]: 0 : osl::MutexGuard aGuard (maMutex);
509 : :
510 : 0 : mbIsCallbackPending = false;
511 : :
512 : : ::std::copy(
513 : : maListeners.begin(),
514 : : maListeners.end(),
515 [ # # ][ # # ]: 0 : ::std::back_inserter(aListenerCopy));
[ # # ]
516 : : }
517 : :
518 [ # # ]: 0 : if (aListenerCopy.size() > 0)
519 : : {
520 : 0 : ListenerContainer::const_iterator iListener;
521 [ # # ]: 0 : ListenerContainer::const_iterator iEnd (aListenerCopy.end());
522 [ # # ][ # # ]: 0 : for (iListener=aListenerCopy.begin(); iListener!=iEnd; ++iListener)
[ # # ]
523 : : {
524 [ # # ]: 0 : (*iListener)->TimeHasChanged(maDateTime);
525 : : }
526 : 0 : }
527 : 0 : }
528 : :
529 [ + - ][ + - ]: 24 : } } // end of namespace ::sdext::presenter
530 : :
531 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|