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_USEREVENTQUEUE_HXX
25 #define INCLUDED_SLIDESHOW_USEREVENTQUEUE_HXX
26 
27 #include <com/sun/star/animations/XAnimationNode.hpp>
28 
29 #include "eventmultiplexer.hxx"
30 #include "eventqueue.hxx"
31 #include "shape.hxx"
32 
33 #include <boost/noncopyable.hpp>
34 
35 /* Definition of UserEventQueue class */
36 
37 namespace slideshow {
38 namespace internal {
39 
40 class PlainEventHandler;
41 class AllAnimationEventHandler;
42 class ShapeClickEventHandler;
43 class ClickEventHandler;
44 class CursorManager;
45 class SkipEffectEventHandler;
46 class RewindEffectEventHandler;
47 class MouseEnterHandler;
48 class MouseLeaveHandler;
49 
50 /** This class schedules user-activated events.
51 
52     This class registeres at the EventMultiplexer and fires
53     events registered for certain user actions. Note that all
54     events will not be fired immediately after the user action
55     occurred, but always added to the EventQueue (and fired the
56     next time that queue is processed). Which is actually a
57     feature.
58 
59     Conceptually, an event is an object that typically is
60     fired only once. After that, the event is exhausted, and
61     should be discarded. Therefore, all events registered on
62     this object are fired and then all references to them are
63     removed.
64 */
65 class UserEventQueue : private ::boost::noncopyable
66 {
67 public:
68     /** Create a user event queue
69 
70         @param rEventMultiplexer
71         The slideshow-global event source, where this class
72         registeres its event handlers.
73 
74         @param rEventQueue
75         Reference to the main event queue. Since we hold this
76         object by plain reference, it must live longer than we
77         do. On the other hand, that queue must not fire events
78         after this object is destroyed, since we might
79         schedule events there which itself contain plain
80         references to this object. Basically, EventQueue and
81         UserEventQueue should have the same lifetime, and since
82         this is not possible, both must be destructed in a
83         phased mode: first clear both of any remaining events,
84         then destruct them.
85     */
86     UserEventQueue( EventMultiplexer&   rMultiplexer,
87                     EventQueue&         rEventQueue,
88                     CursorManager&      rCursorManager );
89     ~UserEventQueue();
90 
91     /** Query whether there are any events still pending.
92      */
93     bool isEmpty() const;
94 
95     /** Clear all registered events.
96 
97         This method clears all registered, but
98         not-yet-executed events. This comes in handy when
99         force-ending a slide, to avoid interference with the
100         next slide's event registration.
101     */
102     void clear();
103 
104     /** Set advance on click behaviour.
105 
106         @param bAdvanceOnClick
107         When true, a click somewhere on the slide will also
108         generate next effect event.  In this case, it is
109         irrelevant where on the slide the mouse is clicked,
110         i.e. the shape need not be hit by the mouse.
111     */
112     void setAdvanceOnClick( bool bAdvanceOnClick );
113 
114     /** Register an event that will be fired when the slide is
115         just shown.
116 
117         Note that <em>all</em> registered events will be fired
118         when the slide start occurs. This is in contrast to
119         the mouse events below.
120     */
121     void registerSlideStartEvent( const EventSharedPtr& rEvent );
122 
123     /** Register an event that will be fired when the slide is
124         about to vanish.
125 
126         Note that <em>all</em> registered events will be fired
127         when the slide end occurs. This is in contrast to
128         the mouse events below.
129     */
130     void registerSlideEndEvent( const EventSharedPtr& rEvent );
131 
132     /** Register an event that will be fired when the given
133         animation node starts.
134 
135         Note that <em>all</em> registered events will be fired
136         when the animation start occurs. This is in contrast to
137         the mouse events below.
138     */
139     void registerAnimationStartEvent(
140         const EventSharedPtr&                             rEvent,
141         const ::com::sun::star::uno::Reference<
142         ::com::sun::star::animations::XAnimationNode>&    xNode );
143 
144     /** Register an event that will be fired when the given
145         animation node ends its active duration.
146 
147         Note that <em>all</em> registered events will be fired
148         when the animation end occurs. This is in contrast to
149         the mouse events below.
150     */
151     void registerAnimationEndEvent(
152         const EventSharedPtr&                               rEvent,
153         const ::com::sun::star::uno::Reference<
154         ::com::sun::star::animations::XAnimationNode>&      xNode );
155 
156     /** Register an event that will be fired when audio output
157         stopped for the given animation node.
158 
159         Note that <em>all</em> registered events will be fired
160         when the audio stopping occurs. This is in contrast to
161         the mouse events below.
162     */
163     void registerAudioStoppedEvent(
164         const EventSharedPtr&                               rEvent,
165         const ::com::sun::star::uno::Reference<
166         ::com::sun::star::animations::XAnimationNode>&      xNode );
167 
168     /** Register an event that is fired when a shape is clicked
169 
170         For every mouse click, only one of the events
171         registered here is fired. The order of fired events is
172         the order of registration, i.e. the first event
173         registered will be the one fired for the first mouse
174         click on the given shape.
175     */
176     void registerShapeClickEvent( const EventSharedPtr& rEvent,
177                                   const ShapeSharedPtr& rShape );
178 
179     /** Registes an event that is fired when the current effects(s)
180         are skipped, .e.g. when the left mouse button is pressed.
181         Then, all registered events are fired and removed from this
182         queue.  After firing, a next effect event is issued to this
183         queue to start the next effect.
184         @param pEvent
185             The event to execute when skipping the current effect.
186         @param bSkipTriggersNextEffect
187             When <TRUE/> then after skipping the current effect the next
188             effect is triggered.  When <FALSE/> then the next effect is not
189             triggered.
190     */
191     void registerSkipEffectEvent(
192         EventSharedPtr const& pEvent,
193         const bool bSkipTriggersNextEffect);
194 
195     /** Registes an event that is fired when the current effects(s)
196         are rewound, .e.g. when the right mouse button is pressed.
197         Then, all registered events are fired and removed from this
198         queue.
199     */
200     void registerRewindEffectEvent( EventSharedPtr const& rEvent );
201 
202     /** Register an event that is fired to show the next event
203 
204         For every next effect event, only one of the events
205         registered here is fired. The order of fired events is
206         the order of registration, i.e. the first event
207         registered will be the one fired for the first mouse
208         click. When advance-on-click (see method
209         setAdvanceOnClick()) is enabled, a mouse click
210         somewhere on the slide will also generate a next
211         effect event. In this case, it is irrelevant where on
212         the slide the mouse is clicked, i.e. the shape need
213         not be hit by the mouse.
214     */
215     void registerNextEffectEvent( const EventSharedPtr& rEvent );
216 
217     /** Register an event that is fired on a double mouse
218         click on a shape
219 
220         For every mouse double click, only one of the events
221         registered here is fired. The order of fired events is
222         the order of registration, i.e. the first event
223         registered will be the one fired for the first mouse
224         double click. It is irrelevant where on the slide the
225         mouse is clicked, i.e. the shape need not be hit by
226         the mouse.
227     */
228     void registerShapeDoubleClickEvent( const EventSharedPtr& rEvent,
229                                         const ShapeSharedPtr& rShape );
230 
231     /** Register an event that is fired on a double mouse click
232 
233         For every mouse double click, only one of the events
234         registered here is fired. The order of fired events is
235         the order of registration, i.e. the first event
236         registered will be the one fired for the first mouse
237         double click. It is irrelevant where on the slide the
238         mouse is clicked, i.e. the shape need not be hit by
239         the mouse.
240     */
241     void registerDoubleClickEvent( const EventSharedPtr& rEvent );
242 
243     /** Register an event that is fired when the mouse enters
244         the area of the given shape
245 
246         For every enter, only one of the events registered
247         here is fired. The order of fired events is the order
248         of registration, i.e. the first event registered will
249         be the one fired for the first time the mouse enters
250         the given shape.
251     */
252     void registerMouseEnterEvent( const EventSharedPtr& rEvent,
253                                   const ShapeSharedPtr& rShape );
254 
255     /** Register an event that is fired when the mouse leaves
256         the area of the given shape
257 
258         For every leave, only one of the events registered
259         here is fired. The order of fired events is the order
260         of registration, i.e. the first event registered will
261         be the one fired for the first time the mouse leaves
262         the given shape area.
263     */
264     void registerMouseLeaveEvent( const EventSharedPtr& rEvent,
265                                   const ShapeSharedPtr& rShape );
266 
267     /** Typically skipping the current effect is triggered by mouse clicks
268         or key presses that trigger the next effect.  This method allows the
269         skipping of effects to be triggered programatically.
270     */
271     void callSkipEffectEventHandler (void);
272 
273 private:
274     /** Generically register an event on one of the handlers.
275 
276         If the handler is not yet created, do that and
277         register it via the Functor
278     */
279     template< typename Handler, typename Functor >
280     void registerEvent( ::boost::shared_ptr< Handler >& rHandler,
281                         const EventSharedPtr&           rEvent,
282                         const Functor&                  rRegistrationFunctor );
283 
284     /** Generically register an event on one of the handlers.
285 
286         If the handler is not yet created, do that and
287         register it via the Functor. This version of the
288         registerEvent method takes an additional parameter
289         rArg, which is passed as the second argument to
290         rHandler's addEvent() method.
291     */
292     template< typename Handler, typename Arg, typename Functor >
293     void registerEvent( ::boost::shared_ptr< Handler >& rHandler,
294                         const EventSharedPtr&           rEvent,
295                         const Arg&                      rArg,
296                         const Functor&                  rRegistrationFunctor );
297 
298     EventMultiplexer&                               mrMultiplexer;
299     EventQueue&                                     mrEventQueue;
300     CursorManager&                                  mrCursorManager;
301 
302     ::boost::shared_ptr<PlainEventHandler>          mpStartEventHandler;
303     ::boost::shared_ptr<PlainEventHandler>          mpEndEventHandler;
304     ::boost::shared_ptr<AllAnimationEventHandler>   mpAnimationStartEventHandler;
305     ::boost::shared_ptr<AllAnimationEventHandler>   mpAnimationEndEventHandler;
306     ::boost::shared_ptr<AllAnimationEventHandler>   mpAudioStoppedEventHandler;
307     ::boost::shared_ptr<ShapeClickEventHandler>     mpShapeClickEventHandler;
308     ::boost::shared_ptr<ClickEventHandler>          mpClickEventHandler;
309     ::boost::shared_ptr<SkipEffectEventHandler>     mpSkipEffectEventHandler;
310     ::boost::shared_ptr<RewindEffectEventHandler>   mpRewindEffectEventHandler;
311     ::boost::shared_ptr<ShapeClickEventHandler>     mpShapeDoubleClickEventHandler;
312     ::boost::shared_ptr<ClickEventHandler>          mpDoubleClickEventHandler;
313     ::boost::shared_ptr<MouseEnterHandler>          mpMouseEnterHandler;
314     ::boost::shared_ptr<MouseLeaveHandler>          mpMouseLeaveHandler;
315 
316     bool                                            mbAdvanceOnClick;
317 };
318 
319 } // namespace internal
320 } // namespace presentation
321 
322 #endif /* INCLUDED_SLIDESHOW_USEREVENTQUEUE_HXX */
323 
324