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