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 #ifndef INCLUDED_SLIDESHOW_INTERRUPTABLEDELAYEVENT_HXX
29 #define INCLUDED_SLIDESHOW_INTERRUPTABLEDELAYEVENT_HXX
30 
31 #include "delayevent.hxx"
32 
33 namespace slideshow
34 {
35     namespace internal
36     {
37         /** Event, which delays calling passed Event's fire() method
38             the given amount of time.
39 
40             This is actually a facade around the passed event object,
41             that passes on all calls to that object, and the sole
42             contribution of itself is the delay.
43         */
44         class DelayFacade : public Event
45         {
46         public:
47             DelayFacade( const EventSharedPtr& 	rEvent,
48                          double					nTimeout	) :
49 #if OSL_DEBUG_LEVEL > 1
50                 Event(::rtl::OUString::createFromAscii("DelayFacade")),
51 #endif
52                 mpEvent( rEvent ),
53                 mnTimeout( nTimeout )
54             {
55             }
56 
57             virtual bool fire()
58             {
59                 if( mpEvent && isCharged() )
60                 {
61                     // pass on directly - we're supposed to be called
62                     // from EventQueue here, anyway - and if not,
63                     // we're only keeping that incorrect transitively.
64                     return mpEvent->fire();
65                 }
66 
67                 return false;
68             }
69 
70             virtual bool isCharged() const
71             {
72                 // pass on to wrappee - this ensures that we return
73                 // false on isCharged(), even if the other event has
74                 // been fired outside our own fire() method
75                 return !mpEvent ? false : mpEvent->isCharged();
76             }
77 
78             virtual double getActivationTime( double nCurrentTime ) const
79             {
80                 // enforce _our_ timeout to our clients (this
81                 // overrides any timeout possibly set at the wrappee!)
82                 return nCurrentTime + mnTimeout;
83             }
84 
85             virtual void dispose()
86             {
87                 mpEvent.reset();
88             }
89 
90         private:
91             EventSharedPtr	mpEvent;
92             double			mnTimeout;
93         };
94 
95         /// Return value for makeInterruptableDelay()
96         struct InterruptableEventPair
97         {
98             /** This member contains a pointer to the timeout
99                 event. When enqueued, this event will fire the
100                 requested action only after the specified timeout.
101              */
102             EventSharedPtr	mpTimeoutEvent;
103 
104             /** This member contains a pointer to the interruption
105                 event. When enqueued, this event will fire
106                 immediately, interrupting a potentially waiting
107                 timeout event.
108              */
109             EventSharedPtr	mpImmediateEvent;
110         };
111 
112         /** Generate an interruptable delay event.
113 
114         	This function generates a pair of events, that are
115         	especially tailored to achieve the following behaviour: By
116         	default, the given functor is called after the specified
117         	timeout (after insertion of the event into the EventQueue,
118         	of course). But optionally, when the interruption event
119         	InterruptableEventPair::mpImmediateEvent is fired, the
120         	given functor is called <em>at once</em>, and the delay is
121         	ignored (that means, the given functor is guaranteed to be
122         	called at utmost once, and never twice. Furthermore, it is
123         	ensured that both events return false on isCharged(), once
124         	anyone of them has been fired already).
125 
126         	@param rFunctor
127             Functor to call when the event fires.
128 
129             @param nTimeout
130             Timeout in seconds, to wait until functor is called.
131 
132 			@returns a pair of events, where the first one waits the
133 			specified amount of time, and the other fires the given
134 			functor immediately.
135          */
136         template< typename Functor > InterruptableEventPair makeInterruptableDelay( const Functor& 	rFunctor,
137                                                                                     double			nTimeout	)
138         {
139             InterruptableEventPair aRes;
140 
141             aRes.mpImmediateEvent = makeEvent( rFunctor, "makeInterruptableDelay");
142             aRes.mpTimeoutEvent.reset( new DelayFacade( aRes.mpImmediateEvent,
143                                                         nTimeout ) );
144 
145             return aRes;
146         }
147     }
148 }
149 
150 #endif /* INCLUDED_SLIDESHOW_INTERRUPTABLEDELAYEVENT_HXX */
151