1*70f497fbSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*70f497fbSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*70f497fbSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*70f497fbSAndrew Rist  * distributed with this work for additional information
6*70f497fbSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*70f497fbSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*70f497fbSAndrew Rist  * "License"); you may not use this file except in compliance
9*70f497fbSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*70f497fbSAndrew Rist  *
11*70f497fbSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*70f497fbSAndrew Rist  *
13*70f497fbSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*70f497fbSAndrew Rist  * software distributed under the License is distributed on an
15*70f497fbSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*70f497fbSAndrew Rist  * KIND, either express or implied.  See the License for the
17*70f497fbSAndrew Rist  * specific language governing permissions and limitations
18*70f497fbSAndrew Rist  * under the License.
19*70f497fbSAndrew Rist  *
20*70f497fbSAndrew Rist  *************************************************************/
21*70f497fbSAndrew Rist 
22*70f497fbSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_slideshow.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir // must be first
28cdf0e10cSrcweir #include <canvas/debug.hxx>
29cdf0e10cSrcweir #include <tools/diagnose_ex.h>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <comphelper/anytostring.hxx>
32cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <com/sun/star/awt/SystemPointer.hpp>
35cdf0e10cSrcweir #include <com/sun/star/awt/MouseButton.hpp>
36cdf0e10cSrcweir #include <com/sun/star/awt/MouseEvent.hpp>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include <boost/bind.hpp>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include "delayevent.hxx"
41cdf0e10cSrcweir #include "usereventqueue.hxx"
42cdf0e10cSrcweir #include "cursormanager.hxx"
43cdf0e10cSrcweir #include "slideshowexceptions.hxx"
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #include <vector>
46cdf0e10cSrcweir #include <queue>
47cdf0e10cSrcweir #include <map>
48cdf0e10cSrcweir #include <functional>
49cdf0e10cSrcweir #include <algorithm>
50cdf0e10cSrcweir 
51cdf0e10cSrcweir 
52cdf0e10cSrcweir using namespace com::sun::star;
53cdf0e10cSrcweir 
54cdf0e10cSrcweir /* Implementation of UserEventQueue class */
55cdf0e10cSrcweir 
56cdf0e10cSrcweir namespace slideshow {
57cdf0e10cSrcweir namespace internal {
58cdf0e10cSrcweir 
59cdf0e10cSrcweir namespace {
60cdf0e10cSrcweir 
61cdf0e10cSrcweir typedef std::vector<EventSharedPtr> ImpEventVector;
62cdf0e10cSrcweir typedef std::queue<EventSharedPtr> ImpEventQueue;
63cdf0e10cSrcweir typedef std::map<uno::Reference<animations::XAnimationNode>,
64cdf0e10cSrcweir                  ImpEventVector> ImpAnimationEventMap;
65cdf0e10cSrcweir typedef std::map<ShapeSharedPtr, ImpEventQueue,
66cdf0e10cSrcweir                  Shape::lessThanShape> ImpShapeEventMap;
67cdf0e10cSrcweir 
68cdf0e10cSrcweir // MouseEventHandler base class, not consuming any event:
69cdf0e10cSrcweir class MouseEventHandler_ : public MouseEventHandler
70cdf0e10cSrcweir {
71cdf0e10cSrcweir public:
handleMousePressed(awt::MouseEvent const &)72cdf0e10cSrcweir     virtual bool handleMousePressed( awt::MouseEvent const& /*e*/ ) { return false;}
handleMouseReleased(awt::MouseEvent const &)73cdf0e10cSrcweir     virtual bool handleMouseReleased( awt::MouseEvent const& /*e*/) { return false;}
handleMouseEntered(awt::MouseEvent const &)74cdf0e10cSrcweir     virtual bool handleMouseEntered( awt::MouseEvent const& /*e*/ ) { return false;}
handleMouseExited(awt::MouseEvent const &)75cdf0e10cSrcweir     virtual bool handleMouseExited( awt::MouseEvent const& /*e*/ ) { return false; }
handleMouseDragged(awt::MouseEvent const &)76cdf0e10cSrcweir     virtual bool handleMouseDragged( awt::MouseEvent const& /*e*/ ) { return false;}
handleMouseMoved(awt::MouseEvent const &)77cdf0e10cSrcweir     virtual bool handleMouseMoved( awt::MouseEvent const& /*e*/ ) { return false; }
78cdf0e10cSrcweir };
79cdf0e10cSrcweir 
80cdf0e10cSrcweir /** @return one event has been posted
81cdf0e10cSrcweir  */
82cdf0e10cSrcweir template <typename ContainerT>
fireSingleEvent(ContainerT & rQueue,EventQueue & rEventQueue)83cdf0e10cSrcweir bool fireSingleEvent( ContainerT & rQueue, EventQueue & rEventQueue )
84cdf0e10cSrcweir {
85cdf0e10cSrcweir     // post next event in given queue:
86cdf0e10cSrcweir     while (! rQueue.empty())
87cdf0e10cSrcweir     {
88cdf0e10cSrcweir         EventSharedPtr const pEvent(rQueue.front());
89cdf0e10cSrcweir         rQueue.pop();
90cdf0e10cSrcweir 
91cdf0e10cSrcweir         // skip all inactive events (as the purpose of
92cdf0e10cSrcweir         // nextEventFromQueue() is to activate the next
93cdf0e10cSrcweir         // event, and events which return false on
94cdf0e10cSrcweir         // isCharged() will never be activated by the
95cdf0e10cSrcweir         // EventQueue)
96cdf0e10cSrcweir         if(pEvent->isCharged())
97cdf0e10cSrcweir             return rEventQueue.addEvent( pEvent );
98cdf0e10cSrcweir     }
99cdf0e10cSrcweir     return false; // no more (active) events in queue
100cdf0e10cSrcweir }
101cdf0e10cSrcweir 
102cdf0e10cSrcweir /** @return at least one event has been posted
103cdf0e10cSrcweir  */
104cdf0e10cSrcweir template <typename ContainerT>
fireAllEvents(ContainerT & rQueue,EventQueue & rEventQueue)105cdf0e10cSrcweir bool fireAllEvents( ContainerT & rQueue, EventQueue & rEventQueue )
106cdf0e10cSrcweir {
107cdf0e10cSrcweir     bool bFiredAny = false;
108cdf0e10cSrcweir     while (fireSingleEvent( rQueue, rEventQueue ))
109cdf0e10cSrcweir         bFiredAny = true;
110cdf0e10cSrcweir     return bFiredAny;
111cdf0e10cSrcweir }
112cdf0e10cSrcweir 
113cdf0e10cSrcweir class EventContainer
114cdf0e10cSrcweir {
115cdf0e10cSrcweir public:
EventContainer()116cdf0e10cSrcweir     EventContainer() :
117cdf0e10cSrcweir         maEvents()
118cdf0e10cSrcweir     {}
119cdf0e10cSrcweir 
clearContainer()120cdf0e10cSrcweir     void clearContainer()
121cdf0e10cSrcweir     {
122cdf0e10cSrcweir         maEvents = ImpEventQueue();
123cdf0e10cSrcweir     }
124cdf0e10cSrcweir 
addEvent(const EventSharedPtr & rEvent)125cdf0e10cSrcweir     void addEvent( const EventSharedPtr& rEvent )
126cdf0e10cSrcweir     {
127cdf0e10cSrcweir         maEvents.push( rEvent );
128cdf0e10cSrcweir     }
129cdf0e10cSrcweir 
isEmpty()130cdf0e10cSrcweir     bool isEmpty()
131cdf0e10cSrcweir     {
132cdf0e10cSrcweir         return maEvents.empty();
133cdf0e10cSrcweir     }
134cdf0e10cSrcweir 
135cdf0e10cSrcweir protected:
136cdf0e10cSrcweir     ImpEventQueue maEvents;
137cdf0e10cSrcweir };
138cdf0e10cSrcweir 
139cdf0e10cSrcweir } // anon namespace
140cdf0e10cSrcweir 
141cdf0e10cSrcweir class PlainEventHandler : public EventHandler,
142cdf0e10cSrcweir                           public EventContainer
143cdf0e10cSrcweir {
144cdf0e10cSrcweir public:
PlainEventHandler(EventQueue & rEventQueue)145cdf0e10cSrcweir     PlainEventHandler( EventQueue & rEventQueue )
146cdf0e10cSrcweir         : EventContainer(), mrEventQueue(rEventQueue) {}
147cdf0e10cSrcweir 
dispose()148cdf0e10cSrcweir     virtual void dispose()
149cdf0e10cSrcweir     {
150cdf0e10cSrcweir         clearContainer();
151cdf0e10cSrcweir     }
152cdf0e10cSrcweir 
handleEvent()153cdf0e10cSrcweir     virtual bool handleEvent()
154cdf0e10cSrcweir     {
155cdf0e10cSrcweir         return fireAllEvents( maEvents, mrEventQueue );
156cdf0e10cSrcweir     }
157cdf0e10cSrcweir 
158cdf0e10cSrcweir private:
159cdf0e10cSrcweir     EventQueue & mrEventQueue;
160cdf0e10cSrcweir };
161cdf0e10cSrcweir 
162cdf0e10cSrcweir class AllAnimationEventHandler : public AnimationEventHandler
163cdf0e10cSrcweir {
164cdf0e10cSrcweir public:
AllAnimationEventHandler(EventQueue & rEventQueue)165cdf0e10cSrcweir     AllAnimationEventHandler( EventQueue& rEventQueue ) :
166cdf0e10cSrcweir         mrEventQueue( rEventQueue ),
167cdf0e10cSrcweir         maAnimationEventMap()
168cdf0e10cSrcweir     {}
169cdf0e10cSrcweir 
dispose()170cdf0e10cSrcweir     virtual void dispose()
171cdf0e10cSrcweir     {
172cdf0e10cSrcweir         maAnimationEventMap.clear();
173cdf0e10cSrcweir     }
174cdf0e10cSrcweir 
handleAnimationEvent(const AnimationNodeSharedPtr & rNode)175cdf0e10cSrcweir     virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
176cdf0e10cSrcweir     {
177cdf0e10cSrcweir         ENSURE_OR_RETURN_FALSE(
178cdf0e10cSrcweir             rNode,
179cdf0e10cSrcweir             "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );
180cdf0e10cSrcweir 
181cdf0e10cSrcweir         bool bRet( false );
182cdf0e10cSrcweir 
183cdf0e10cSrcweir         ImpAnimationEventMap::iterator aIter;
184cdf0e10cSrcweir         if( (aIter=maAnimationEventMap.find(
185cdf0e10cSrcweir                  rNode->getXAnimationNode() )) != maAnimationEventMap.end() )
186cdf0e10cSrcweir         {
187cdf0e10cSrcweir             ImpEventVector& rVec( aIter->second );
188cdf0e10cSrcweir 
189cdf0e10cSrcweir             bRet = !rVec.empty();
190cdf0e10cSrcweir 
191cdf0e10cSrcweir             // registered node found -> fire all events in the vector
192cdf0e10cSrcweir             std::for_each( rVec.begin(), rVec.end(),
193cdf0e10cSrcweir                            boost::bind( &EventQueue::addEvent,
194cdf0e10cSrcweir                                         boost::ref( mrEventQueue ), _1 ) );
195cdf0e10cSrcweir 
196cdf0e10cSrcweir             rVec.clear();
197cdf0e10cSrcweir         }
198cdf0e10cSrcweir 
199cdf0e10cSrcweir         return bRet;
200cdf0e10cSrcweir     }
201cdf0e10cSrcweir 
addEvent(const EventSharedPtr & rEvent,const uno::Reference<animations::XAnimationNode> & xNode)202cdf0e10cSrcweir     void addEvent( const EventSharedPtr&                                rEvent,
203cdf0e10cSrcweir                    const uno::Reference< animations::XAnimationNode >&  xNode )
204cdf0e10cSrcweir     {
205cdf0e10cSrcweir         ImpAnimationEventMap::iterator aIter;
206cdf0e10cSrcweir         if( (aIter=maAnimationEventMap.find( xNode )) ==
207cdf0e10cSrcweir             maAnimationEventMap.end() )
208cdf0e10cSrcweir         {
209cdf0e10cSrcweir             // no entry for this animation -> create one
210cdf0e10cSrcweir             aIter = maAnimationEventMap.insert(
211cdf0e10cSrcweir                 ImpAnimationEventMap::value_type( xNode,
212cdf0e10cSrcweir                                                   ImpEventVector() ) ).first;
213cdf0e10cSrcweir         }
214cdf0e10cSrcweir 
215cdf0e10cSrcweir         // add new event to queue
216cdf0e10cSrcweir         aIter->second.push_back( rEvent );
217cdf0e10cSrcweir     }
218cdf0e10cSrcweir 
isEmpty()219cdf0e10cSrcweir     bool isEmpty()
220cdf0e10cSrcweir     {
221cdf0e10cSrcweir         // find at least one animation with a non-empty vector
222cdf0e10cSrcweir         ImpAnimationEventMap::const_iterator aCurr( maAnimationEventMap.begin() );
223cdf0e10cSrcweir         const ImpAnimationEventMap::const_iterator aEnd( maAnimationEventMap.end() );
224cdf0e10cSrcweir         while( aCurr != aEnd )
225cdf0e10cSrcweir         {
226cdf0e10cSrcweir             if( !aCurr->second.empty() )
227cdf0e10cSrcweir                 return false; // at least one non-empty entry found
228cdf0e10cSrcweir 
229cdf0e10cSrcweir             ++aCurr;
230cdf0e10cSrcweir         }
231cdf0e10cSrcweir 
232cdf0e10cSrcweir         return true; // not a single non-empty entry found
233cdf0e10cSrcweir     }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir private:
236cdf0e10cSrcweir     EventQueue&             mrEventQueue;
237cdf0e10cSrcweir     ImpAnimationEventMap    maAnimationEventMap;
238cdf0e10cSrcweir };
239cdf0e10cSrcweir 
240cdf0e10cSrcweir class ClickEventHandler : public MouseEventHandler_,
241cdf0e10cSrcweir                           public EventHandler,
242cdf0e10cSrcweir                           public EventContainer
243cdf0e10cSrcweir {
244cdf0e10cSrcweir public:
ClickEventHandler(EventQueue & rEventQueue)245cdf0e10cSrcweir     ClickEventHandler( EventQueue& rEventQueue ) :
246cdf0e10cSrcweir         EventContainer(),
247cdf0e10cSrcweir         mrEventQueue( rEventQueue ),
248cdf0e10cSrcweir         mbAdvanceOnClick( true )
249cdf0e10cSrcweir     {}
250cdf0e10cSrcweir 
setAdvanceOnClick(bool bAdvanceOnClick)251cdf0e10cSrcweir     void setAdvanceOnClick( bool bAdvanceOnClick )
252cdf0e10cSrcweir     {
253cdf0e10cSrcweir         mbAdvanceOnClick = bAdvanceOnClick;
254cdf0e10cSrcweir     }
255cdf0e10cSrcweir 
256cdf0e10cSrcweir private:
dispose()257cdf0e10cSrcweir     virtual void dispose()
258cdf0e10cSrcweir     {
259cdf0e10cSrcweir         clearContainer();
260cdf0e10cSrcweir     }
261cdf0e10cSrcweir 
262cdf0e10cSrcweir     // triggered by API calls, e.g. space bar
handleEvent()263cdf0e10cSrcweir     virtual bool handleEvent()
264cdf0e10cSrcweir     {
265cdf0e10cSrcweir         return handleEvent_impl();
266cdf0e10cSrcweir     }
267cdf0e10cSrcweir 
268cdf0e10cSrcweir     // triggered by mouse release:
handleMouseReleased(const awt::MouseEvent & evt)269cdf0e10cSrcweir     virtual bool handleMouseReleased( const awt::MouseEvent& evt )
270cdf0e10cSrcweir     {
271cdf0e10cSrcweir         if(evt.Buttons != awt::MouseButton::LEFT)
272cdf0e10cSrcweir             return false;
273cdf0e10cSrcweir 
274cdf0e10cSrcweir         if( mbAdvanceOnClick ) {
275cdf0e10cSrcweir             // fire next event
276cdf0e10cSrcweir             return handleEvent_impl();
277cdf0e10cSrcweir         }
278cdf0e10cSrcweir         else {
279cdf0e10cSrcweir             return false; // advance-on-click disabled
280cdf0e10cSrcweir         }
281cdf0e10cSrcweir     }
282cdf0e10cSrcweir 
283cdf0e10cSrcweir     // triggered by both:
handleEvent_impl()284cdf0e10cSrcweir     virtual bool handleEvent_impl()
285cdf0e10cSrcweir     {
286cdf0e10cSrcweir         // fire next event:
287cdf0e10cSrcweir         return fireSingleEvent( maEvents, mrEventQueue );
288cdf0e10cSrcweir     }
289cdf0e10cSrcweir 
290cdf0e10cSrcweir private:
291cdf0e10cSrcweir     EventQueue& mrEventQueue;
292cdf0e10cSrcweir     bool        mbAdvanceOnClick;
293cdf0e10cSrcweir };
294cdf0e10cSrcweir 
295cdf0e10cSrcweir class SkipEffectEventHandler : public ClickEventHandler
296cdf0e10cSrcweir {
297cdf0e10cSrcweir public:
SkipEffectEventHandler(EventQueue & rEventQueue,EventMultiplexer & rEventMultiplexer)298cdf0e10cSrcweir     SkipEffectEventHandler( EventQueue & rEventQueue,
299cdf0e10cSrcweir                             EventMultiplexer & rEventMultiplexer )
300cdf0e10cSrcweir         : ClickEventHandler(rEventQueue),
301cdf0e10cSrcweir           mrEventQueue(rEventQueue),
302cdf0e10cSrcweir           mrEventMultiplexer(rEventMultiplexer),
303cdf0e10cSrcweir           mbSkipTriggersNextEffect(true) {}
304cdf0e10cSrcweir 
305cdf0e10cSrcweir     /** Remember to trigger (or not to trigger) the next effect after the
306cdf0e10cSrcweir         current effect is skiped.
307cdf0e10cSrcweir     */
setSkipTriggersNextEffect(const bool bSkipTriggersNextEffect)308cdf0e10cSrcweir     void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect)
309cdf0e10cSrcweir     { mbSkipTriggersNextEffect = bSkipTriggersNextEffect; }
310cdf0e10cSrcweir 
311cdf0e10cSrcweir     ///  Skip the current effect but do not triggere the next effect.
skipEffect(void)312cdf0e10cSrcweir     void skipEffect (void) { handleEvent_impl(false); }
313cdf0e10cSrcweir 
314cdf0e10cSrcweir private:
handleEvent_impl()315cdf0e10cSrcweir     virtual bool handleEvent_impl()
316cdf0e10cSrcweir     {
317cdf0e10cSrcweir         return handleEvent_impl(true);
318cdf0e10cSrcweir     }
319cdf0e10cSrcweir 
handleEvent_impl(bool bNotifyNextEffect)320cdf0e10cSrcweir     bool handleEvent_impl (bool bNotifyNextEffect)
321cdf0e10cSrcweir     {
322cdf0e10cSrcweir         // fire all events, so animation nodes can register their
323cdf0e10cSrcweir         // next effect listeners:
324cdf0e10cSrcweir         if(fireAllEvents( maEvents, mrEventQueue ))
325cdf0e10cSrcweir         {
326cdf0e10cSrcweir             if (mbSkipTriggersNextEffect && bNotifyNextEffect)
327cdf0e10cSrcweir             {
328cdf0e10cSrcweir                 // then simulate a next effect event: this skip effect
329cdf0e10cSrcweir                 // handler is triggered upon next effect events (multiplexer
330cdf0e10cSrcweir                 // prio=-1)!  Posting a notifyNextEffect() here is only safe
331cdf0e10cSrcweir                 // (we don't run into busy loop), because we assume that
332cdf0e10cSrcweir                 // someone has registerered above for next effects
333cdf0e10cSrcweir                 // (multiplexer prio=0) at the user event queue.
334cdf0e10cSrcweir                 return mrEventQueue.addEventWhenQueueIsEmpty(
335cdf0e10cSrcweir                     makeEvent( boost::bind( &EventMultiplexer::notifyNextEffect,
336cdf0e10cSrcweir                                             boost::ref(mrEventMultiplexer) ),
337cdf0e10cSrcweir                                "EventMultiplexer::notifyNextEffect") );
338cdf0e10cSrcweir             }
339cdf0e10cSrcweir             else
340cdf0e10cSrcweir                 return true;
341cdf0e10cSrcweir         }
342cdf0e10cSrcweir         return false;
343cdf0e10cSrcweir     }
344cdf0e10cSrcweir 
345cdf0e10cSrcweir private:
346cdf0e10cSrcweir     EventQueue & mrEventQueue;
347cdf0e10cSrcweir     EventMultiplexer & mrEventMultiplexer;
348cdf0e10cSrcweir     bool mbSkipTriggersNextEffect;
349cdf0e10cSrcweir };
350cdf0e10cSrcweir 
351cdf0e10cSrcweir class RewindEffectEventHandler : public MouseEventHandler_,
352cdf0e10cSrcweir                                  public EventContainer
353cdf0e10cSrcweir {
354cdf0e10cSrcweir public:
RewindEffectEventHandler(EventQueue & rEventQueue)355cdf0e10cSrcweir     RewindEffectEventHandler( EventQueue & rEventQueue )
356cdf0e10cSrcweir         : EventContainer(), mrEventQueue(rEventQueue) {}
357cdf0e10cSrcweir 
358cdf0e10cSrcweir private:
dispose()359cdf0e10cSrcweir     virtual void dispose()
360cdf0e10cSrcweir     {
361cdf0e10cSrcweir         clearContainer();
362cdf0e10cSrcweir     }
363cdf0e10cSrcweir 
handleMouseReleased(awt::MouseEvent const & evt)364cdf0e10cSrcweir     virtual bool handleMouseReleased( awt::MouseEvent const& evt )
365cdf0e10cSrcweir     {
366cdf0e10cSrcweir         if(evt.Buttons != awt::MouseButton::RIGHT)
367cdf0e10cSrcweir             return false;
368cdf0e10cSrcweir 
369cdf0e10cSrcweir         return fireAllEvents( maEvents, mrEventQueue );
370cdf0e10cSrcweir     }
371cdf0e10cSrcweir 
372cdf0e10cSrcweir private:
373cdf0e10cSrcweir     EventQueue & mrEventQueue;
374cdf0e10cSrcweir };
375cdf0e10cSrcweir 
376cdf0e10cSrcweir /** Base class to share some common code between
377cdf0e10cSrcweir     ShapeClickEventHandler and MouseMoveHandler
378cdf0e10cSrcweir 
379cdf0e10cSrcweir     @derive override necessary MouseEventHandler interface methods,
380cdf0e10cSrcweir     call sendEvent() method to actually process the event.
381cdf0e10cSrcweir */
382cdf0e10cSrcweir class MouseHandlerBase : public MouseEventHandler_
383cdf0e10cSrcweir {
384cdf0e10cSrcweir public:
MouseHandlerBase(EventQueue & rEventQueue)385cdf0e10cSrcweir     MouseHandlerBase( EventQueue& rEventQueue ) :
386cdf0e10cSrcweir         mrEventQueue( rEventQueue ),
387cdf0e10cSrcweir         maShapeEventMap()
388cdf0e10cSrcweir     {}
389cdf0e10cSrcweir 
dispose()390cdf0e10cSrcweir     virtual void dispose()
391cdf0e10cSrcweir     {
392cdf0e10cSrcweir         // TODO(Q1): Check whether plain vector with swap idiom is
393cdf0e10cSrcweir         // okay here
394cdf0e10cSrcweir         maShapeEventMap = ImpShapeEventMap();
395cdf0e10cSrcweir     }
396cdf0e10cSrcweir 
addEvent(const EventSharedPtr & rEvent,const ShapeSharedPtr & rShape)397cdf0e10cSrcweir     void addEvent( const EventSharedPtr& rEvent,
398cdf0e10cSrcweir                    const ShapeSharedPtr& rShape )
399cdf0e10cSrcweir     {
400cdf0e10cSrcweir         ImpShapeEventMap::iterator aIter;
401cdf0e10cSrcweir         if( (aIter=maShapeEventMap.find( rShape )) == maShapeEventMap.end() )
402cdf0e10cSrcweir         {
403cdf0e10cSrcweir             // no entry for this shape -> create one
404cdf0e10cSrcweir             aIter = maShapeEventMap.insert(
405cdf0e10cSrcweir                 ImpShapeEventMap::value_type( rShape,
406cdf0e10cSrcweir                                               ImpEventQueue() ) ).first;
407cdf0e10cSrcweir         }
408cdf0e10cSrcweir 
409cdf0e10cSrcweir         // add new event to queue
410cdf0e10cSrcweir         aIter->second.push( rEvent );
411cdf0e10cSrcweir     }
412cdf0e10cSrcweir 
isEmpty()413cdf0e10cSrcweir     bool isEmpty()
414cdf0e10cSrcweir     {
415cdf0e10cSrcweir         // find at least one shape with a non-empty queue
416cdf0e10cSrcweir         ImpShapeEventMap::reverse_iterator aCurrShape( maShapeEventMap.begin());
417cdf0e10cSrcweir         ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.end() );
418cdf0e10cSrcweir         while( aCurrShape != aEndShape )
419cdf0e10cSrcweir         {
420cdf0e10cSrcweir             if( !aCurrShape->second.empty() )
421cdf0e10cSrcweir                 return false; // at least one non-empty entry found
422cdf0e10cSrcweir 
423cdf0e10cSrcweir             ++aCurrShape;
424cdf0e10cSrcweir         }
425cdf0e10cSrcweir 
426cdf0e10cSrcweir         return true; // not a single non-empty entry found
427cdf0e10cSrcweir     }
428cdf0e10cSrcweir 
429cdf0e10cSrcweir protected:
hitTest(const awt::MouseEvent & e,ImpShapeEventMap::reverse_iterator & o_rHitShape)430cdf0e10cSrcweir     bool hitTest( const awt::MouseEvent&                e,
431cdf0e10cSrcweir                   ImpShapeEventMap::reverse_iterator&   o_rHitShape )
432cdf0e10cSrcweir     {
433cdf0e10cSrcweir         // find hit shape in map
434cdf0e10cSrcweir         const basegfx::B2DPoint aPosition( e.X, e.Y );
435cdf0e10cSrcweir 
436cdf0e10cSrcweir         // find matching shape (scan reversely, to coarsely match
437cdf0e10cSrcweir         // paint order)
438cdf0e10cSrcweir         ImpShapeEventMap::reverse_iterator       aCurrShape(maShapeEventMap.rbegin());
439cdf0e10cSrcweir         const ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.rend() );
440cdf0e10cSrcweir         while( aCurrShape != aEndShape )
441cdf0e10cSrcweir         {
442cdf0e10cSrcweir             // TODO(F2): Get proper geometry polygon from the
443cdf0e10cSrcweir             // shape, to avoid having areas outside the shape
444cdf0e10cSrcweir             // react on the mouse
445cdf0e10cSrcweir             if( aCurrShape->first->getBounds().isInside( aPosition ) &&
446cdf0e10cSrcweir                 aCurrShape->first->isVisible() )
447cdf0e10cSrcweir             {
448cdf0e10cSrcweir                 // shape hit, and shape is visible - report a
449cdf0e10cSrcweir                 // hit
450cdf0e10cSrcweir                 o_rHitShape = aCurrShape;
451cdf0e10cSrcweir                 return true;
452cdf0e10cSrcweir             }
453cdf0e10cSrcweir 
454cdf0e10cSrcweir             ++aCurrShape;
455cdf0e10cSrcweir         }
456cdf0e10cSrcweir 
457cdf0e10cSrcweir         return false; // nothing hit
458cdf0e10cSrcweir     }
459cdf0e10cSrcweir 
sendEvent(ImpShapeEventMap::reverse_iterator & io_rHitShape)460cdf0e10cSrcweir     bool sendEvent( ImpShapeEventMap::reverse_iterator& io_rHitShape )
461cdf0e10cSrcweir     {
462cdf0e10cSrcweir         // take next event from queue
463cdf0e10cSrcweir         const bool bRet( fireSingleEvent( io_rHitShape->second,
464cdf0e10cSrcweir                                           mrEventQueue ) );
465cdf0e10cSrcweir 
466cdf0e10cSrcweir         // clear shape entry, if its queue is
467cdf0e10cSrcweir         // empty. This is important, since the shapes
468cdf0e10cSrcweir         // are held by shared ptr, and might otherwise
469cdf0e10cSrcweir         // not get released, even after their owning
470cdf0e10cSrcweir         // slide is long gone.
471cdf0e10cSrcweir         if( io_rHitShape->second.empty() )
472cdf0e10cSrcweir         {
473cdf0e10cSrcweir             // this looks funny, since ::std::map does
474cdf0e10cSrcweir             // provide an erase( iterator )
475cdf0e10cSrcweir             // method. Unfortunately, stlport does not
476cdf0e10cSrcweir             // declare the obvious erase(
477cdf0e10cSrcweir             // reverse_iterator ) needed here (missing
478cdf0e10cSrcweir             // orthogonality, eh?)
479cdf0e10cSrcweir             maShapeEventMap.erase( io_rHitShape->first );
480cdf0e10cSrcweir         }
481cdf0e10cSrcweir 
482cdf0e10cSrcweir         return bRet;
483cdf0e10cSrcweir     }
484cdf0e10cSrcweir 
processEvent(const awt::MouseEvent & e)485cdf0e10cSrcweir     bool processEvent( const awt::MouseEvent& e )
486cdf0e10cSrcweir     {
487cdf0e10cSrcweir         ImpShapeEventMap::reverse_iterator aCurrShape;
488cdf0e10cSrcweir 
489cdf0e10cSrcweir         if( hitTest( e, aCurrShape ) )
490cdf0e10cSrcweir             return sendEvent( aCurrShape );
491cdf0e10cSrcweir 
492cdf0e10cSrcweir         return false; // did not handle the event
493cdf0e10cSrcweir     }
494cdf0e10cSrcweir 
495cdf0e10cSrcweir private:
496cdf0e10cSrcweir     EventQueue&         mrEventQueue;
497cdf0e10cSrcweir     ImpShapeEventMap    maShapeEventMap;
498cdf0e10cSrcweir };
499cdf0e10cSrcweir 
500cdf0e10cSrcweir class ShapeClickEventHandler : public MouseHandlerBase
501cdf0e10cSrcweir {
502cdf0e10cSrcweir public:
ShapeClickEventHandler(CursorManager & rCursorManager,EventQueue & rEventQueue)503cdf0e10cSrcweir     ShapeClickEventHandler( CursorManager& rCursorManager,
504cdf0e10cSrcweir                             EventQueue&    rEventQueue ) :
505cdf0e10cSrcweir         MouseHandlerBase( rEventQueue ),
506cdf0e10cSrcweir         mrCursorManager( rCursorManager )
507cdf0e10cSrcweir     {}
508cdf0e10cSrcweir 
handleMouseReleased(const awt::MouseEvent & e)509cdf0e10cSrcweir     virtual bool handleMouseReleased( const awt::MouseEvent& e )
510cdf0e10cSrcweir     {
511cdf0e10cSrcweir         if(e.Buttons != awt::MouseButton::LEFT)
512cdf0e10cSrcweir             return false;
513cdf0e10cSrcweir         return processEvent( e );
514cdf0e10cSrcweir     }
515cdf0e10cSrcweir 
handleMouseMoved(const awt::MouseEvent & e)516cdf0e10cSrcweir     virtual bool handleMouseMoved( const awt::MouseEvent& e )
517cdf0e10cSrcweir     {
518cdf0e10cSrcweir         // TODO(P2): Maybe buffer last shape touched
519cdf0e10cSrcweir 
520cdf0e10cSrcweir         // if we have a shape click event, and the mouse
521cdf0e10cSrcweir         // hovers over this shape, change cursor to hand
522cdf0e10cSrcweir         ImpShapeEventMap::reverse_iterator aDummy;
523cdf0e10cSrcweir         if( hitTest( e, aDummy ) )
524cdf0e10cSrcweir             mrCursorManager.requestCursor( awt::SystemPointer::REFHAND );
525cdf0e10cSrcweir 
526cdf0e10cSrcweir         return false; // we don't /eat/ this event. Lower prio
527cdf0e10cSrcweir         // handler should see it, too.
528cdf0e10cSrcweir     }
529cdf0e10cSrcweir 
530cdf0e10cSrcweir private:
531cdf0e10cSrcweir     CursorManager& mrCursorManager;
532cdf0e10cSrcweir };
533cdf0e10cSrcweir 
534cdf0e10cSrcweir class MouseEnterHandler : public MouseHandlerBase
535cdf0e10cSrcweir {
536cdf0e10cSrcweir public:
MouseEnterHandler(EventQueue & rEventQueue)537cdf0e10cSrcweir     MouseEnterHandler( EventQueue& rEventQueue )
538cdf0e10cSrcweir         : MouseHandlerBase( rEventQueue ),
539cdf0e10cSrcweir           mpLastShape() {}
540cdf0e10cSrcweir 
handleMouseMoved(const awt::MouseEvent & e)541cdf0e10cSrcweir     virtual bool handleMouseMoved( const awt::MouseEvent& e )
542cdf0e10cSrcweir     {
543cdf0e10cSrcweir         // TODO(P2): Maybe buffer last shape touched, and
544cdf0e10cSrcweir         // check against that _first_
545cdf0e10cSrcweir 
546cdf0e10cSrcweir         ImpShapeEventMap::reverse_iterator aCurr;
547cdf0e10cSrcweir         if( hitTest( e, aCurr ) )
548cdf0e10cSrcweir         {
549cdf0e10cSrcweir             if( aCurr->first != mpLastShape )
550cdf0e10cSrcweir             {
551cdf0e10cSrcweir                 // we actually hit a shape, and it's different
552cdf0e10cSrcweir                 // from the previous one - thus we just
553cdf0e10cSrcweir                 // entered it, raise event
554cdf0e10cSrcweir                 sendEvent( aCurr );
555cdf0e10cSrcweir                 mpLastShape = aCurr->first;
556cdf0e10cSrcweir             }
557cdf0e10cSrcweir         }
558cdf0e10cSrcweir         else
559cdf0e10cSrcweir         {
560cdf0e10cSrcweir             // don't hit no shape - thus, last shape is NULL
561cdf0e10cSrcweir             mpLastShape.reset();
562cdf0e10cSrcweir         }
563cdf0e10cSrcweir 
564cdf0e10cSrcweir         return false; // we don't /eat/ this event. Lower prio
565cdf0e10cSrcweir         // handler should see it, too.
566cdf0e10cSrcweir     }
567cdf0e10cSrcweir 
568cdf0e10cSrcweir private:
569cdf0e10cSrcweir     ShapeSharedPtr mpLastShape;
570cdf0e10cSrcweir };
571cdf0e10cSrcweir 
572cdf0e10cSrcweir class MouseLeaveHandler : public MouseHandlerBase
573cdf0e10cSrcweir {
574cdf0e10cSrcweir public:
MouseLeaveHandler(EventQueue & rEventQueue)575cdf0e10cSrcweir     MouseLeaveHandler( EventQueue& rEventQueue )
576cdf0e10cSrcweir         : MouseHandlerBase( rEventQueue ),
577cdf0e10cSrcweir           maLastIter() {}
578cdf0e10cSrcweir 
handleMouseMoved(const awt::MouseEvent & e)579cdf0e10cSrcweir     virtual bool handleMouseMoved( const awt::MouseEvent& e )
580cdf0e10cSrcweir     {
581cdf0e10cSrcweir         // TODO(P2): Maybe buffer last shape touched, and
582cdf0e10cSrcweir         // check against that _first_
583cdf0e10cSrcweir 
584cdf0e10cSrcweir         ImpShapeEventMap::reverse_iterator aCurr;
585cdf0e10cSrcweir         if( hitTest( e, aCurr ) )
586cdf0e10cSrcweir         {
587cdf0e10cSrcweir             maLastIter = aCurr;
588cdf0e10cSrcweir         }
589cdf0e10cSrcweir         else
590cdf0e10cSrcweir         {
591cdf0e10cSrcweir             if( maLastIter->first )
592cdf0e10cSrcweir             {
593cdf0e10cSrcweir                 // last time, we were over a shape, now we're
594cdf0e10cSrcweir                 // not - we thus just left that shape, raise
595cdf0e10cSrcweir                 // event
596cdf0e10cSrcweir                 sendEvent( maLastIter );
597cdf0e10cSrcweir             }
598cdf0e10cSrcweir 
599cdf0e10cSrcweir             // in any case, when we hit this else-branch: no
600cdf0e10cSrcweir             // shape hit, thus have to clear maLastIter
601cdf0e10cSrcweir             maLastIter = ImpShapeEventMap::reverse_iterator();
602cdf0e10cSrcweir         }
603cdf0e10cSrcweir 
604cdf0e10cSrcweir         return false; // we don't /eat/ this event. Lower prio
605cdf0e10cSrcweir         // handler should see it, too.
606cdf0e10cSrcweir     }
607cdf0e10cSrcweir 
608cdf0e10cSrcweir private:
609cdf0e10cSrcweir     ImpShapeEventMap::reverse_iterator maLastIter;
610cdf0e10cSrcweir };
611cdf0e10cSrcweir 
612cdf0e10cSrcweir template< typename Handler, typename Functor >
registerEvent(boost::shared_ptr<Handler> & rHandler,const EventSharedPtr & rEvent,const Functor & rRegistrationFunctor)613cdf0e10cSrcweir void UserEventQueue::registerEvent(
614cdf0e10cSrcweir     boost::shared_ptr< Handler >& rHandler,
615cdf0e10cSrcweir     const EventSharedPtr&         rEvent,
616cdf0e10cSrcweir     const Functor&                rRegistrationFunctor )
617cdf0e10cSrcweir {
618cdf0e10cSrcweir     ENSURE_OR_THROW( rEvent,
619cdf0e10cSrcweir                       "UserEventQueue::registerEvent(): Invalid event" );
620cdf0e10cSrcweir 
621cdf0e10cSrcweir     if( !rHandler ) {
622cdf0e10cSrcweir         // create handler
623cdf0e10cSrcweir         rHandler.reset( new Handler( mrEventQueue ) );
624cdf0e10cSrcweir         // register handler on EventMultiplexer
625cdf0e10cSrcweir         rRegistrationFunctor( rHandler );
626cdf0e10cSrcweir     }
627cdf0e10cSrcweir 
628cdf0e10cSrcweir     rHandler->addEvent( rEvent );
629cdf0e10cSrcweir }
630cdf0e10cSrcweir 
631cdf0e10cSrcweir template< typename Handler, typename Arg, typename Functor >
registerEvent(boost::shared_ptr<Handler> & rHandler,const EventSharedPtr & rEvent,const Arg & rArg,const Functor & rRegistrationFunctor)632cdf0e10cSrcweir void UserEventQueue::registerEvent(
633cdf0e10cSrcweir     boost::shared_ptr< Handler >& rHandler,
634cdf0e10cSrcweir     const EventSharedPtr&         rEvent,
635cdf0e10cSrcweir     const Arg&                    rArg,
636cdf0e10cSrcweir     const Functor&                rRegistrationFunctor )
637cdf0e10cSrcweir {
638cdf0e10cSrcweir     ENSURE_OR_THROW( rEvent,
639cdf0e10cSrcweir                       "UserEventQueue::registerEvent(): Invalid event" );
640cdf0e10cSrcweir 
641cdf0e10cSrcweir     if( !rHandler ) {
642cdf0e10cSrcweir         // create handler
643cdf0e10cSrcweir         rHandler.reset( new Handler( mrEventQueue ) );
644cdf0e10cSrcweir 
645cdf0e10cSrcweir         // register handler on EventMultiplexer
646cdf0e10cSrcweir         rRegistrationFunctor( rHandler );
647cdf0e10cSrcweir     }
648cdf0e10cSrcweir 
649cdf0e10cSrcweir     rHandler->addEvent( rEvent, rArg );
650cdf0e10cSrcweir }
651cdf0e10cSrcweir 
652cdf0e10cSrcweir 
653cdf0e10cSrcweir // Public methods
654cdf0e10cSrcweir // =====================================================
655cdf0e10cSrcweir 
UserEventQueue(EventMultiplexer & rMultiplexer,EventQueue & rEventQueue,CursorManager & rCursorManager)656cdf0e10cSrcweir UserEventQueue::UserEventQueue( EventMultiplexer&   rMultiplexer,
657cdf0e10cSrcweir                                 EventQueue&         rEventQueue,
658cdf0e10cSrcweir                                 CursorManager&      rCursorManager )
659cdf0e10cSrcweir     : mrMultiplexer( rMultiplexer ),
660cdf0e10cSrcweir       mrEventQueue( rEventQueue ),
661cdf0e10cSrcweir       mrCursorManager( rCursorManager ),
662cdf0e10cSrcweir       mpStartEventHandler(),
663cdf0e10cSrcweir       mpEndEventHandler(),
664cdf0e10cSrcweir       mpAnimationStartEventHandler(),
665cdf0e10cSrcweir       mpAnimationEndEventHandler(),
666cdf0e10cSrcweir       mpAudioStoppedEventHandler(),
667cdf0e10cSrcweir       mpClickEventHandler(),
668cdf0e10cSrcweir       mpSkipEffectEventHandler(),
669cdf0e10cSrcweir       mpRewindEffectEventHandler(),
670cdf0e10cSrcweir       mpDoubleClickEventHandler(),
671cdf0e10cSrcweir       mpMouseEnterHandler(),
672cdf0e10cSrcweir       mpMouseLeaveHandler(),
673cdf0e10cSrcweir       mbAdvanceOnClick( true )
674cdf0e10cSrcweir {
675cdf0e10cSrcweir }
676cdf0e10cSrcweir 
~UserEventQueue()677cdf0e10cSrcweir UserEventQueue::~UserEventQueue()
678cdf0e10cSrcweir {
679cdf0e10cSrcweir     try
680cdf0e10cSrcweir     {
681cdf0e10cSrcweir         // unregister all handlers
682cdf0e10cSrcweir         clear();
683cdf0e10cSrcweir     }
684cdf0e10cSrcweir     catch (uno::Exception &) {
685cdf0e10cSrcweir         OSL_ENSURE( false, rtl::OUStringToOString(
686cdf0e10cSrcweir                         comphelper::anyToString(
687cdf0e10cSrcweir                             cppu::getCaughtException() ),
688cdf0e10cSrcweir                         RTL_TEXTENCODING_UTF8 ).getStr() );
689cdf0e10cSrcweir     }
690cdf0e10cSrcweir }
691cdf0e10cSrcweir 
isEmpty() const692cdf0e10cSrcweir bool UserEventQueue::isEmpty() const
693cdf0e10cSrcweir {
694cdf0e10cSrcweir     // TODO(T2): This is not thread safe, the handlers are all
695cdf0e10cSrcweir     // only separately synchronized. This poses the danger of
696cdf0e10cSrcweir     // generating false empty status on XSlideShow::update(), such
697cdf0e10cSrcweir     // that the last events of a slide are not triggered.
698cdf0e10cSrcweir 
699cdf0e10cSrcweir     // we're empty iff all handler queues are empty
700cdf0e10cSrcweir     return
701cdf0e10cSrcweir         (mpStartEventHandler ? mpStartEventHandler->isEmpty() : true) &&
702cdf0e10cSrcweir         (mpEndEventHandler ? mpEndEventHandler->isEmpty() : true) &&
703cdf0e10cSrcweir         (mpAnimationStartEventHandler ? mpAnimationStartEventHandler->isEmpty() : true) &&
704cdf0e10cSrcweir         (mpAnimationEndEventHandler ? mpAnimationEndEventHandler->isEmpty() : true) &&
705cdf0e10cSrcweir         (mpAudioStoppedEventHandler ? mpAudioStoppedEventHandler->isEmpty() : true) &&
706cdf0e10cSrcweir         (mpShapeClickEventHandler ? mpShapeClickEventHandler->isEmpty() : true) &&
707cdf0e10cSrcweir         (mpClickEventHandler ? mpClickEventHandler->isEmpty() : true) &&
708cdf0e10cSrcweir         (mpSkipEffectEventHandler ? mpSkipEffectEventHandler->isEmpty() : true) &&
709cdf0e10cSrcweir         (mpRewindEffectEventHandler ? mpRewindEffectEventHandler->isEmpty() : true) &&
710cdf0e10cSrcweir         (mpShapeDoubleClickEventHandler ? mpShapeDoubleClickEventHandler->isEmpty() : true) &&
711cdf0e10cSrcweir         (mpDoubleClickEventHandler ? mpDoubleClickEventHandler->isEmpty() : true) &&
712cdf0e10cSrcweir         (mpMouseEnterHandler ? mpMouseEnterHandler->isEmpty() : true) &&
713cdf0e10cSrcweir         (mpMouseLeaveHandler ? mpMouseLeaveHandler->isEmpty() : true);
714cdf0e10cSrcweir }
715cdf0e10cSrcweir 
clear()716cdf0e10cSrcweir void UserEventQueue::clear()
717cdf0e10cSrcweir {
718cdf0e10cSrcweir     // unregister and delete all handlers
719cdf0e10cSrcweir     if( mpStartEventHandler ) {
720cdf0e10cSrcweir         mrMultiplexer.removeSlideStartHandler( mpStartEventHandler );
721cdf0e10cSrcweir         mpStartEventHandler.reset();
722cdf0e10cSrcweir     }
723cdf0e10cSrcweir     if( mpEndEventHandler ) {
724cdf0e10cSrcweir         mrMultiplexer.removeSlideEndHandler( mpEndEventHandler );
725cdf0e10cSrcweir         mpEndEventHandler.reset();
726cdf0e10cSrcweir     }
727cdf0e10cSrcweir     if( mpAnimationStartEventHandler ) {
728cdf0e10cSrcweir         mrMultiplexer.removeAnimationStartHandler(
729cdf0e10cSrcweir             mpAnimationStartEventHandler );
730cdf0e10cSrcweir         mpAnimationStartEventHandler.reset();
731cdf0e10cSrcweir     }
732cdf0e10cSrcweir     if( mpAnimationEndEventHandler ) {
733cdf0e10cSrcweir         mrMultiplexer.removeAnimationEndHandler( mpAnimationEndEventHandler );
734cdf0e10cSrcweir         mpAnimationEndEventHandler.reset();
735cdf0e10cSrcweir     }
736cdf0e10cSrcweir     if( mpAudioStoppedEventHandler ) {
737cdf0e10cSrcweir         mrMultiplexer.removeAudioStoppedHandler( mpAudioStoppedEventHandler );
738cdf0e10cSrcweir         mpAudioStoppedEventHandler.reset();
739cdf0e10cSrcweir     }
740cdf0e10cSrcweir     if( mpShapeClickEventHandler ) {
741cdf0e10cSrcweir         mrMultiplexer.removeClickHandler( mpShapeClickEventHandler );
742cdf0e10cSrcweir         mrMultiplexer.removeMouseMoveHandler( mpShapeClickEventHandler );
743cdf0e10cSrcweir         mpShapeClickEventHandler.reset();
744cdf0e10cSrcweir     }
745cdf0e10cSrcweir     if( mpClickEventHandler ) {
746cdf0e10cSrcweir         mrMultiplexer.removeClickHandler( mpClickEventHandler );
747cdf0e10cSrcweir         mrMultiplexer.removeNextEffectHandler( mpClickEventHandler );
748cdf0e10cSrcweir         mpClickEventHandler.reset();
749cdf0e10cSrcweir     }
750cdf0e10cSrcweir     if(mpSkipEffectEventHandler) {
751cdf0e10cSrcweir         mrMultiplexer.removeClickHandler( mpSkipEffectEventHandler );
752cdf0e10cSrcweir         mrMultiplexer.removeNextEffectHandler( mpSkipEffectEventHandler );
753cdf0e10cSrcweir         mpSkipEffectEventHandler.reset();
754cdf0e10cSrcweir     }
755cdf0e10cSrcweir     if(mpRewindEffectEventHandler) {
756cdf0e10cSrcweir         mrMultiplexer.removeClickHandler( mpRewindEffectEventHandler );
757cdf0e10cSrcweir         mpRewindEffectEventHandler.reset();
758cdf0e10cSrcweir     }
759cdf0e10cSrcweir     if( mpShapeDoubleClickEventHandler ) {
760cdf0e10cSrcweir         mrMultiplexer.removeDoubleClickHandler( mpShapeDoubleClickEventHandler );
761cdf0e10cSrcweir         mrMultiplexer.removeMouseMoveHandler( mpShapeDoubleClickEventHandler );
762cdf0e10cSrcweir         mpShapeDoubleClickEventHandler.reset();
763cdf0e10cSrcweir     }
764cdf0e10cSrcweir     if( mpDoubleClickEventHandler ) {
765cdf0e10cSrcweir         mrMultiplexer.removeDoubleClickHandler( mpDoubleClickEventHandler );
766cdf0e10cSrcweir         mpDoubleClickEventHandler.reset();
767cdf0e10cSrcweir     }
768cdf0e10cSrcweir     if( mpMouseEnterHandler ) {
769cdf0e10cSrcweir         mrMultiplexer.removeMouseMoveHandler( mpMouseEnterHandler );
770cdf0e10cSrcweir         mpMouseEnterHandler.reset();
771cdf0e10cSrcweir     }
772cdf0e10cSrcweir     if( mpMouseLeaveHandler ) {
773cdf0e10cSrcweir         mrMultiplexer.removeMouseMoveHandler( mpMouseLeaveHandler );
774cdf0e10cSrcweir         mpMouseLeaveHandler.reset();
775cdf0e10cSrcweir     }
776cdf0e10cSrcweir }
777cdf0e10cSrcweir 
setAdvanceOnClick(bool bAdvanceOnClick)778cdf0e10cSrcweir void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick )
779cdf0e10cSrcweir {
780cdf0e10cSrcweir     mbAdvanceOnClick = bAdvanceOnClick;
781cdf0e10cSrcweir 
782cdf0e10cSrcweir     // forward to handler, if existing. Otherwise, the handler
783cdf0e10cSrcweir     // creation will do the forwarding.
784cdf0e10cSrcweir     if( mpClickEventHandler )
785cdf0e10cSrcweir         mpClickEventHandler->setAdvanceOnClick( bAdvanceOnClick );
786cdf0e10cSrcweir }
787cdf0e10cSrcweir 
788cdf0e10cSrcweir 
registerSlideStartEvent(const EventSharedPtr & rEvent)789cdf0e10cSrcweir void UserEventQueue::registerSlideStartEvent( const EventSharedPtr& rEvent )
790cdf0e10cSrcweir {
791cdf0e10cSrcweir     registerEvent( mpStartEventHandler,
792cdf0e10cSrcweir                    rEvent,
793cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addSlideStartHandler,
794cdf0e10cSrcweir                                 boost::ref( mrMultiplexer ), _1 ) );
795cdf0e10cSrcweir }
796cdf0e10cSrcweir 
registerSlideEndEvent(const EventSharedPtr & rEvent)797cdf0e10cSrcweir void UserEventQueue::registerSlideEndEvent( const EventSharedPtr& rEvent )
798cdf0e10cSrcweir {
799cdf0e10cSrcweir     registerEvent( mpEndEventHandler,
800cdf0e10cSrcweir                    rEvent,
801cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addSlideEndHandler,
802cdf0e10cSrcweir                                 boost::ref( mrMultiplexer ), _1 ) );
803cdf0e10cSrcweir }
804cdf0e10cSrcweir 
registerAnimationStartEvent(const EventSharedPtr & rEvent,const uno::Reference<animations::XAnimationNode> & xNode)805cdf0e10cSrcweir void UserEventQueue::registerAnimationStartEvent(
806cdf0e10cSrcweir     const EventSharedPtr&                                 rEvent,
807cdf0e10cSrcweir     const uno::Reference< animations::XAnimationNode>&    xNode )
808cdf0e10cSrcweir {
809cdf0e10cSrcweir     registerEvent( mpAnimationStartEventHandler,
810cdf0e10cSrcweir                    rEvent,
811cdf0e10cSrcweir                    xNode,
812cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addAnimationStartHandler,
813cdf0e10cSrcweir                                 boost::ref( mrMultiplexer ), _1 ) );
814cdf0e10cSrcweir }
815cdf0e10cSrcweir 
registerAnimationEndEvent(const EventSharedPtr & rEvent,const uno::Reference<animations::XAnimationNode> & xNode)816cdf0e10cSrcweir void UserEventQueue::registerAnimationEndEvent(
817cdf0e10cSrcweir     const EventSharedPtr&                               rEvent,
818cdf0e10cSrcweir     const uno::Reference<animations::XAnimationNode>&   xNode )
819cdf0e10cSrcweir {
820cdf0e10cSrcweir     registerEvent( mpAnimationEndEventHandler,
821cdf0e10cSrcweir                    rEvent,
822cdf0e10cSrcweir                    xNode,
823cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addAnimationEndHandler,
824cdf0e10cSrcweir                                 boost::ref( mrMultiplexer ), _1 ) );
825cdf0e10cSrcweir }
826cdf0e10cSrcweir 
registerAudioStoppedEvent(const EventSharedPtr & rEvent,const uno::Reference<animations::XAnimationNode> & xNode)827cdf0e10cSrcweir void UserEventQueue::registerAudioStoppedEvent(
828cdf0e10cSrcweir     const EventSharedPtr&                               rEvent,
829cdf0e10cSrcweir     const uno::Reference<animations::XAnimationNode>&   xNode )
830cdf0e10cSrcweir {
831cdf0e10cSrcweir     registerEvent( mpAudioStoppedEventHandler,
832cdf0e10cSrcweir                    rEvent,
833cdf0e10cSrcweir                    xNode,
834cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addAudioStoppedHandler,
835cdf0e10cSrcweir                                 boost::ref( mrMultiplexer ), _1 ) );
836cdf0e10cSrcweir }
837cdf0e10cSrcweir 
registerShapeClickEvent(const EventSharedPtr & rEvent,const ShapeSharedPtr & rShape)838cdf0e10cSrcweir void UserEventQueue::registerShapeClickEvent( const EventSharedPtr& rEvent,
839cdf0e10cSrcweir                                               const ShapeSharedPtr& rShape )
840cdf0e10cSrcweir {
841cdf0e10cSrcweir     ENSURE_OR_THROW(
842cdf0e10cSrcweir         rEvent,
843cdf0e10cSrcweir         "UserEventQueue::registerShapeClickEvent(): Invalid event" );
844cdf0e10cSrcweir 
845cdf0e10cSrcweir     if( !mpShapeClickEventHandler )
846cdf0e10cSrcweir     {
847cdf0e10cSrcweir         // create handler
848cdf0e10cSrcweir         mpShapeClickEventHandler.reset(
849cdf0e10cSrcweir             new ShapeClickEventHandler(mrCursorManager,
850cdf0e10cSrcweir                                        mrEventQueue) );
851cdf0e10cSrcweir 
852cdf0e10cSrcweir         // register handler on EventMultiplexer
853cdf0e10cSrcweir         mrMultiplexer.addClickHandler( mpShapeClickEventHandler, 1.0 );
854cdf0e10cSrcweir         mrMultiplexer.addMouseMoveHandler( mpShapeClickEventHandler, 1.0 );
855cdf0e10cSrcweir     }
856cdf0e10cSrcweir 
857cdf0e10cSrcweir     mpShapeClickEventHandler->addEvent( rEvent, rShape );
858cdf0e10cSrcweir }
859cdf0e10cSrcweir 
860cdf0e10cSrcweir namespace {
861cdf0e10cSrcweir class ClickEventRegistrationFunctor
862cdf0e10cSrcweir {
863cdf0e10cSrcweir public:
ClickEventRegistrationFunctor(EventMultiplexer & rMultiplexer,double nPrio,bool bAdvanceOnClick)864cdf0e10cSrcweir     ClickEventRegistrationFunctor( EventMultiplexer& rMultiplexer,
865cdf0e10cSrcweir                                    double            nPrio,
866cdf0e10cSrcweir                                    bool              bAdvanceOnClick )
867cdf0e10cSrcweir         : mrMultiplexer( rMultiplexer ),
868cdf0e10cSrcweir           mnPrio(nPrio),
869cdf0e10cSrcweir           mbAdvanceOnClick( bAdvanceOnClick ) {}
870cdf0e10cSrcweir 
operator ()(const boost::shared_ptr<ClickEventHandler> & rHandler) const871cdf0e10cSrcweir     void operator()( const boost::shared_ptr<ClickEventHandler>& rHandler )const
872cdf0e10cSrcweir     {
873cdf0e10cSrcweir         // register the handler on _two_ sources: we want the
874cdf0e10cSrcweir         // nextEffect events, e.g. space bar, to trigger clicks, as well!
875cdf0e10cSrcweir         mrMultiplexer.addClickHandler( rHandler, mnPrio );
876cdf0e10cSrcweir         mrMultiplexer.addNextEffectHandler( rHandler, mnPrio );
877cdf0e10cSrcweir 
878cdf0e10cSrcweir         // forward advance-on-click state to newly
879cdf0e10cSrcweir         // generated handler (that's the only reason why
880cdf0e10cSrcweir         // we're called here)
881cdf0e10cSrcweir         rHandler->setAdvanceOnClick( mbAdvanceOnClick );
882cdf0e10cSrcweir     }
883cdf0e10cSrcweir 
884cdf0e10cSrcweir private:
885cdf0e10cSrcweir     EventMultiplexer&   mrMultiplexer;
886cdf0e10cSrcweir     double const        mnPrio;
887cdf0e10cSrcweir     bool const          mbAdvanceOnClick;
888cdf0e10cSrcweir };
889cdf0e10cSrcweir } // anon namespace
890cdf0e10cSrcweir 
registerNextEffectEvent(const EventSharedPtr & rEvent)891cdf0e10cSrcweir void UserEventQueue::registerNextEffectEvent( const EventSharedPtr& rEvent )
892cdf0e10cSrcweir {
893cdf0e10cSrcweir     // TODO: better name may be mpNextEffectEventHandler?  then we have
894cdf0e10cSrcweir     //       next effect (=> waiting to be started)
895cdf0e10cSrcweir     //       skip effect (skipping the currently running one)
896cdf0e10cSrcweir     //       rewind effect (rewinding back running one and waiting (again)
897cdf0e10cSrcweir     //                      to be started)
898cdf0e10cSrcweir     registerEvent( mpClickEventHandler,
899cdf0e10cSrcweir                    rEvent,
900cdf0e10cSrcweir                    ClickEventRegistrationFunctor( mrMultiplexer,
901cdf0e10cSrcweir                                                   0.0 /* default prio */,
902cdf0e10cSrcweir                                                   mbAdvanceOnClick ) );
903cdf0e10cSrcweir }
904cdf0e10cSrcweir 
registerSkipEffectEvent(EventSharedPtr const & pEvent,const bool bSkipTriggersNextEffect)905cdf0e10cSrcweir void UserEventQueue::registerSkipEffectEvent(
906cdf0e10cSrcweir     EventSharedPtr const & pEvent,
907cdf0e10cSrcweir     const bool bSkipTriggersNextEffect)
908cdf0e10cSrcweir {
909cdf0e10cSrcweir     if(!mpSkipEffectEventHandler)
910cdf0e10cSrcweir     {
911cdf0e10cSrcweir         mpSkipEffectEventHandler.reset(
912cdf0e10cSrcweir             new SkipEffectEventHandler( mrEventQueue, mrMultiplexer ) );
913cdf0e10cSrcweir         // register the handler on _two_ sources: we want the
914cdf0e10cSrcweir         // nextEffect events, e.g. space bar, to trigger clicks, as well!
915cdf0e10cSrcweir         mrMultiplexer.addClickHandler( mpSkipEffectEventHandler,
916cdf0e10cSrcweir                                        -1.0 /* prio below default */ );
917cdf0e10cSrcweir         mrMultiplexer.addNextEffectHandler( mpSkipEffectEventHandler,
918cdf0e10cSrcweir                                             -1.0 /* prio below default */ );
919cdf0e10cSrcweir         // forward advance-on-click state to newly
920cdf0e10cSrcweir         // generated handler (that's the only reason why
921cdf0e10cSrcweir         // we're called here)
922cdf0e10cSrcweir         mpSkipEffectEventHandler->setAdvanceOnClick( mbAdvanceOnClick );
923cdf0e10cSrcweir     }
924cdf0e10cSrcweir     mpSkipEffectEventHandler->setSkipTriggersNextEffect(bSkipTriggersNextEffect);
925cdf0e10cSrcweir     mpSkipEffectEventHandler->addEvent( pEvent );
926cdf0e10cSrcweir }
927cdf0e10cSrcweir 
registerRewindEffectEvent(EventSharedPtr const & pEvent)928cdf0e10cSrcweir void UserEventQueue::registerRewindEffectEvent( EventSharedPtr const& pEvent )
929cdf0e10cSrcweir {
930cdf0e10cSrcweir     registerEvent( mpRewindEffectEventHandler,
931cdf0e10cSrcweir                    pEvent,
932cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addClickHandler,
933cdf0e10cSrcweir                                 boost::ref(mrMultiplexer), _1,
934cdf0e10cSrcweir                                 -1.0 /* prio below default */ ) );
935cdf0e10cSrcweir }
936cdf0e10cSrcweir 
registerShapeDoubleClickEvent(const EventSharedPtr & rEvent,const ShapeSharedPtr & rShape)937cdf0e10cSrcweir void UserEventQueue::registerShapeDoubleClickEvent(
938cdf0e10cSrcweir     const EventSharedPtr& rEvent,
939cdf0e10cSrcweir     const ShapeSharedPtr& rShape )
940cdf0e10cSrcweir {
941cdf0e10cSrcweir     ENSURE_OR_THROW(
942cdf0e10cSrcweir         rEvent,
943cdf0e10cSrcweir         "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );
944cdf0e10cSrcweir 
945cdf0e10cSrcweir     if( !mpShapeDoubleClickEventHandler )
946cdf0e10cSrcweir     {
947cdf0e10cSrcweir         // create handler
948cdf0e10cSrcweir         mpShapeDoubleClickEventHandler.reset(
949cdf0e10cSrcweir             new ShapeClickEventHandler(mrCursorManager,
950cdf0e10cSrcweir                                        mrEventQueue) );
951cdf0e10cSrcweir 
952cdf0e10cSrcweir         // register handler on EventMultiplexer
953cdf0e10cSrcweir         mrMultiplexer.addDoubleClickHandler( mpShapeDoubleClickEventHandler,
954cdf0e10cSrcweir                                              1.0 );
955cdf0e10cSrcweir         mrMultiplexer.addMouseMoveHandler( mpShapeDoubleClickEventHandler,
956cdf0e10cSrcweir                                            1.0 );
957cdf0e10cSrcweir     }
958cdf0e10cSrcweir 
959cdf0e10cSrcweir     mpShapeDoubleClickEventHandler->addEvent( rEvent, rShape );
960cdf0e10cSrcweir }
961cdf0e10cSrcweir 
registerDoubleClickEvent(const EventSharedPtr & rEvent)962cdf0e10cSrcweir void UserEventQueue::registerDoubleClickEvent( const EventSharedPtr& rEvent )
963cdf0e10cSrcweir {
964cdf0e10cSrcweir     registerEvent( mpDoubleClickEventHandler,
965cdf0e10cSrcweir                    rEvent,
966cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addDoubleClickHandler,
967cdf0e10cSrcweir                                 boost::ref( mrMultiplexer ), _1,
968cdf0e10cSrcweir                                 0.0 /* default prio */ ) );
969cdf0e10cSrcweir }
970cdf0e10cSrcweir 
registerMouseEnterEvent(const EventSharedPtr & rEvent,const ShapeSharedPtr & rShape)971cdf0e10cSrcweir void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr& rEvent,
972cdf0e10cSrcweir                                               const ShapeSharedPtr& rShape )
973cdf0e10cSrcweir {
974cdf0e10cSrcweir     registerEvent( mpMouseEnterHandler,
975cdf0e10cSrcweir                    rEvent,
976cdf0e10cSrcweir                    rShape,
977cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addMouseMoveHandler,
978cdf0e10cSrcweir                                 boost::ref( mrMultiplexer ), _1,
979cdf0e10cSrcweir                                 0.0 /* default prio */ ) );
980cdf0e10cSrcweir }
981cdf0e10cSrcweir 
registerMouseLeaveEvent(const EventSharedPtr & rEvent,const ShapeSharedPtr & rShape)982cdf0e10cSrcweir void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr& rEvent,
983cdf0e10cSrcweir                                               const ShapeSharedPtr& rShape )
984cdf0e10cSrcweir {
985cdf0e10cSrcweir     registerEvent( mpMouseLeaveHandler,
986cdf0e10cSrcweir                    rEvent,
987cdf0e10cSrcweir                    rShape,
988cdf0e10cSrcweir                    boost::bind( &EventMultiplexer::addMouseMoveHandler,
989cdf0e10cSrcweir                                 boost::ref( mrMultiplexer ), _1,
990cdf0e10cSrcweir                                 0.0 /* default prio */ ) );
991cdf0e10cSrcweir }
992cdf0e10cSrcweir 
callSkipEffectEventHandler(void)993cdf0e10cSrcweir void UserEventQueue::callSkipEffectEventHandler (void)
994cdf0e10cSrcweir {
995cdf0e10cSrcweir     ::boost::shared_ptr<SkipEffectEventHandler> pHandler (
996cdf0e10cSrcweir         ::boost::dynamic_pointer_cast<SkipEffectEventHandler>(mpSkipEffectEventHandler));
997cdf0e10cSrcweir     if (pHandler)
998cdf0e10cSrcweir         pHandler->skipEffect();
999cdf0e10cSrcweir }
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir } // namespace internal
1002cdf0e10cSrcweir } // namespace presentation
1003cdf0e10cSrcweir 
1004