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