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