1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <canvas/debug.hxx>
23 #include <tools/diagnose_ex.h>
25 #include <comphelper/anytostring.hxx>
26 #include <cppuhelper/exc_hlp.hxx>
28 #include <com/sun/star/awt/SystemPointer.hpp>
29 #include <com/sun/star/awt/MouseButton.hpp>
30 #include <com/sun/star/awt/MouseEvent.hpp>
32 #include <boost/bind.hpp>
34 #include "delayevent.hxx"
35 #include "usereventqueue.hxx"
36 #include "cursormanager.hxx"
37 #include "slideshowexceptions.hxx"
46 using namespace com::sun::star
;
48 /* Implementation of UserEventQueue class */
55 typedef std::vector
<EventSharedPtr
> ImpEventVector
;
56 typedef std::queue
<EventSharedPtr
> ImpEventQueue
;
57 typedef std::map
<uno::Reference
<animations::XAnimationNode
>,
58 ImpEventVector
> ImpAnimationEventMap
;
59 typedef std::map
<ShapeSharedPtr
, ImpEventQueue
,
60 Shape::lessThanShape
> ImpShapeEventMap
;
62 // MouseEventHandler base class, not consuming any event:
63 class MouseEventHandler_
: public MouseEventHandler
66 virtual bool handleMousePressed( awt::MouseEvent
const& /*e*/ ) { return false;}
67 virtual bool handleMouseReleased( awt::MouseEvent
const& /*e*/) { return false;}
68 virtual bool handleMouseEntered( awt::MouseEvent
const& /*e*/ ) { return false;}
69 virtual bool handleMouseExited( awt::MouseEvent
const& /*e*/ ) { return false; }
70 virtual bool handleMouseDragged( awt::MouseEvent
const& /*e*/ ) { return false;}
71 virtual bool handleMouseMoved( awt::MouseEvent
const& /*e*/ ) { return false; }
74 /** @return one event has been posted
76 template <typename ContainerT
>
77 bool fireSingleEvent( ContainerT
& rQueue
, EventQueue
& rEventQueue
)
79 // post next event in given queue:
80 while (! rQueue
.empty())
82 EventSharedPtr
const pEvent(rQueue
.front());
85 // skip all inactive events (as the purpose of
86 // nextEventFromQueue() is to activate the next
87 // event, and events which return false on
88 // isCharged() will never be activated by the
90 if(pEvent
->isCharged())
91 return rEventQueue
.addEvent( pEvent
);
93 return false; // no more (active) events in queue
96 /** @return at least one event has been posted
98 template <typename ContainerT
>
99 bool fireAllEvents( ContainerT
& rQueue
, EventQueue
& rEventQueue
)
101 bool bFiredAny
= false;
102 while (fireSingleEvent( rQueue
, rEventQueue
))
114 void clearContainer()
116 maEvents
= ImpEventQueue();
119 void addEvent( const EventSharedPtr
& rEvent
)
121 maEvents
.push( rEvent
);
126 return maEvents
.empty();
130 ImpEventQueue maEvents
;
135 class PlainEventHandler
: public EventHandler
,
136 public EventContainer
139 PlainEventHandler( EventQueue
& rEventQueue
)
140 : EventContainer(), mrEventQueue(rEventQueue
) {}
142 virtual void dispose()
147 virtual bool handleEvent()
149 return fireAllEvents( maEvents
, mrEventQueue
);
153 EventQueue
& mrEventQueue
;
156 class AllAnimationEventHandler
: public AnimationEventHandler
159 AllAnimationEventHandler( EventQueue
& rEventQueue
) :
160 mrEventQueue( rEventQueue
),
161 maAnimationEventMap()
164 virtual void dispose()
166 maAnimationEventMap
.clear();
169 virtual bool handleAnimationEvent( const AnimationNodeSharedPtr
& rNode
)
171 ENSURE_OR_RETURN_FALSE(
173 "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );
177 ImpAnimationEventMap::iterator aIter
;
178 if( (aIter
=maAnimationEventMap
.find(
179 rNode
->getXAnimationNode() )) != maAnimationEventMap
.end() )
181 ImpEventVector
& rVec( aIter
->second
);
183 bRet
= !rVec
.empty();
185 // registered node found -> fire all events in the vector
186 std::for_each( rVec
.begin(), rVec
.end(),
187 boost::bind( &EventQueue::addEvent
,
188 boost::ref( mrEventQueue
), _1
) );
196 void addEvent( const EventSharedPtr
& rEvent
,
197 const uno::Reference
< animations::XAnimationNode
>& xNode
)
199 ImpAnimationEventMap::iterator aIter
;
200 if( (aIter
=maAnimationEventMap
.find( xNode
)) ==
201 maAnimationEventMap
.end() )
203 // no entry for this animation -> create one
204 aIter
= maAnimationEventMap
.insert(
205 ImpAnimationEventMap::value_type( xNode
,
206 ImpEventVector() ) ).first
;
209 // add new event to queue
210 aIter
->second
.push_back( rEvent
);
215 // find at least one animation with a non-empty vector
216 ImpAnimationEventMap::const_iterator
aCurr( maAnimationEventMap
.begin() );
217 const ImpAnimationEventMap::const_iterator
aEnd( maAnimationEventMap
.end() );
218 while( aCurr
!= aEnd
)
220 if( !aCurr
->second
.empty() )
221 return false; // at least one non-empty entry found
226 return true; // not a single non-empty entry found
230 EventQueue
& mrEventQueue
;
231 ImpAnimationEventMap maAnimationEventMap
;
234 class ClickEventHandler
: public MouseEventHandler_
,
236 public EventContainer
239 ClickEventHandler( EventQueue
& rEventQueue
) :
241 mrEventQueue( rEventQueue
),
242 mbAdvanceOnClick( true )
245 void setAdvanceOnClick( bool bAdvanceOnClick
)
247 mbAdvanceOnClick
= bAdvanceOnClick
;
251 virtual void dispose()
256 // triggered by API calls, e.g. space bar
257 virtual bool handleEvent()
259 return handleEvent_impl();
262 // triggered by mouse release:
263 virtual bool handleMouseReleased( const awt::MouseEvent
& evt
)
265 if(evt
.Buttons
!= awt::MouseButton::LEFT
)
268 if( mbAdvanceOnClick
) {
270 return handleEvent_impl();
273 return false; // advance-on-click disabled
277 // triggered by both:
278 virtual bool handleEvent_impl()
281 return fireSingleEvent( maEvents
, mrEventQueue
);
285 EventQueue
& mrEventQueue
;
286 bool mbAdvanceOnClick
;
289 class SkipEffectEventHandler
: public ClickEventHandler
292 SkipEffectEventHandler( EventQueue
& rEventQueue
,
293 EventMultiplexer
& rEventMultiplexer
)
294 : ClickEventHandler(rEventQueue
),
295 mrEventQueue(rEventQueue
),
296 mrEventMultiplexer(rEventMultiplexer
),
297 mbSkipTriggersNextEffect(true) {}
299 /** Remember to trigger (or not to trigger) the next effect after the
300 current effect is skiped.
302 void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect
)
303 { mbSkipTriggersNextEffect
= bSkipTriggersNextEffect
; }
305 /// Skip the current effect but do not triggere the next effect.
306 void skipEffect (void) { handleEvent_impl(false); }
309 virtual bool handleEvent_impl()
311 return handleEvent_impl(true);
314 bool handleEvent_impl (bool bNotifyNextEffect
)
316 // fire all events, so animation nodes can register their
317 // next effect listeners:
318 if(fireAllEvents( maEvents
, mrEventQueue
))
320 if (mbSkipTriggersNextEffect
&& bNotifyNextEffect
)
322 // then simulate a next effect event: this skip effect
323 // handler is triggered upon next effect events (multiplexer
324 // prio=-1)! Posting a notifyNextEffect() here is only safe
325 // (we don't run into busy loop), because we assume that
326 // someone has registerered above for next effects
327 // (multiplexer prio=0) at the user event queue.
328 return mrEventQueue
.addEventWhenQueueIsEmpty(
329 makeEvent( boost::bind( &EventMultiplexer::notifyNextEffect
,
330 boost::ref(mrEventMultiplexer
) ),
331 "EventMultiplexer::notifyNextEffect") );
340 EventQueue
& mrEventQueue
;
341 EventMultiplexer
& mrEventMultiplexer
;
342 bool mbSkipTriggersNextEffect
;
345 class RewindEffectEventHandler
: public MouseEventHandler_
,
346 public EventContainer
349 RewindEffectEventHandler( EventQueue
& rEventQueue
)
350 : EventContainer(), mrEventQueue(rEventQueue
) {}
353 virtual void dispose()
358 virtual bool handleMouseReleased( awt::MouseEvent
const& evt
)
360 if(evt
.Buttons
!= awt::MouseButton::RIGHT
)
363 return fireAllEvents( maEvents
, mrEventQueue
);
367 EventQueue
& mrEventQueue
;
370 /** Base class to share some common code between
371 ShapeClickEventHandler and MouseMoveHandler
373 @derive override necessary MouseEventHandler interface methods,
374 call sendEvent() method to actually process the event.
376 class MouseHandlerBase
: public MouseEventHandler_
379 MouseHandlerBase( EventQueue
& rEventQueue
) :
380 mrEventQueue( rEventQueue
),
384 virtual void dispose()
386 // TODO(Q1): Check whether plain vector with swap idiom is
388 maShapeEventMap
= ImpShapeEventMap();
391 void addEvent( const EventSharedPtr
& rEvent
,
392 const ShapeSharedPtr
& rShape
)
394 ImpShapeEventMap::iterator aIter
;
395 if( (aIter
=maShapeEventMap
.find( rShape
)) == maShapeEventMap
.end() )
397 // no entry for this shape -> create one
398 aIter
= maShapeEventMap
.insert(
399 ImpShapeEventMap::value_type( rShape
,
400 ImpEventQueue() ) ).first
;
403 // add new event to queue
404 aIter
->second
.push( rEvent
);
409 // find at least one shape with a non-empty queue
410 ImpShapeEventMap::reverse_iterator
aCurrShape( maShapeEventMap
.begin());
411 ImpShapeEventMap::reverse_iterator
aEndShape( maShapeEventMap
.end() );
412 while( aCurrShape
!= aEndShape
)
414 if( !aCurrShape
->second
.empty() )
415 return false; // at least one non-empty entry found
420 return true; // not a single non-empty entry found
424 bool hitTest( const awt::MouseEvent
& e
,
425 ImpShapeEventMap::reverse_iterator
& o_rHitShape
)
427 // find hit shape in map
428 const basegfx::B2DPoint
aPosition( e
.X
, e
.Y
);
430 // find matching shape (scan reversely, to coarsely match
432 ImpShapeEventMap::reverse_iterator
aCurrShape(maShapeEventMap
.rbegin());
433 const ImpShapeEventMap::reverse_iterator
aEndShape( maShapeEventMap
.rend() );
434 while( aCurrShape
!= aEndShape
)
436 // TODO(F2): Get proper geometry polygon from the
437 // shape, to avoid having areas outside the shape
438 // react on the mouse
439 if( aCurrShape
->first
->getBounds().isInside( aPosition
) &&
440 aCurrShape
->first
->isVisible() )
442 // shape hit, and shape is visible - report a
444 o_rHitShape
= aCurrShape
;
451 return false; // nothing hit
454 bool sendEvent( ImpShapeEventMap::reverse_iterator
& io_rHitShape
)
456 // take next event from queue
457 const bool bRet( fireSingleEvent( io_rHitShape
->second
,
460 // clear shape entry, if its queue is
461 // empty. This is important, since the shapes
462 // are held by shared ptr, and might otherwise
463 // not get released, even after their owning
464 // slide is long gone.
465 if( io_rHitShape
->second
.empty() )
467 // this looks funny, since ::std::map does
468 // provide an erase( iterator )
469 // method. Unfortunately, C++ does not
470 // declare the obvious erase(
471 // reverse_iterator ) needed here (missing
472 // orthogonality, eh?)
473 maShapeEventMap
.erase( io_rHitShape
->first
);
479 bool processEvent( const awt::MouseEvent
& e
)
481 ImpShapeEventMap::reverse_iterator aCurrShape
;
483 if( hitTest( e
, aCurrShape
) )
484 return sendEvent( aCurrShape
);
486 return false; // did not handle the event
490 EventQueue
& mrEventQueue
;
491 ImpShapeEventMap maShapeEventMap
;
494 class ShapeClickEventHandler
: public MouseHandlerBase
497 ShapeClickEventHandler( CursorManager
& rCursorManager
,
498 EventQueue
& rEventQueue
) :
499 MouseHandlerBase( rEventQueue
),
500 mrCursorManager( rCursorManager
)
503 virtual bool handleMouseReleased( const awt::MouseEvent
& e
)
505 if(e
.Buttons
!= awt::MouseButton::LEFT
)
507 return processEvent( e
);
510 virtual bool handleMouseMoved( const awt::MouseEvent
& e
)
512 // TODO(P2): Maybe buffer last shape touched
514 // if we have a shape click event, and the mouse
515 // hovers over this shape, change cursor to hand
516 ImpShapeEventMap::reverse_iterator aDummy
;
517 if( hitTest( e
, aDummy
) )
518 mrCursorManager
.requestCursor( awt::SystemPointer::REFHAND
);
520 return false; // we don't /eat/ this event. Lower prio
521 // handler should see it, too.
525 CursorManager
& mrCursorManager
;
528 class MouseEnterHandler
: public MouseHandlerBase
531 MouseEnterHandler( EventQueue
& rEventQueue
)
532 : MouseHandlerBase( rEventQueue
),
535 virtual bool handleMouseMoved( const awt::MouseEvent
& e
)
537 // TODO(P2): Maybe buffer last shape touched, and
538 // check against that _first_
540 ImpShapeEventMap::reverse_iterator aCurr
;
541 if( hitTest( e
, aCurr
) )
543 if( aCurr
->first
!= mpLastShape
)
545 // we actually hit a shape, and it's different
546 // from the previous one - thus we just
547 // entered it, raise event
549 mpLastShape
= aCurr
->first
;
554 // don't hit no shape - thus, last shape is NULL
558 return false; // we don't /eat/ this event. Lower prio
559 // handler should see it, too.
563 ShapeSharedPtr mpLastShape
;
566 class MouseLeaveHandler
: public MouseHandlerBase
569 MouseLeaveHandler( EventQueue
& rEventQueue
)
570 : MouseHandlerBase( rEventQueue
),
573 virtual bool handleMouseMoved( const awt::MouseEvent
& e
)
575 // TODO(P2): Maybe buffer last shape touched, and
576 // check against that _first_
578 ImpShapeEventMap::reverse_iterator aCurr
;
579 if( hitTest( e
, aCurr
) )
585 if( maLastIter
->first
)
587 // last time, we were over a shape, now we're
588 // not - we thus just left that shape, raise
590 sendEvent( maLastIter
);
593 // in any case, when we hit this else-branch: no
594 // shape hit, thus have to clear maLastIter
595 maLastIter
= ImpShapeEventMap::reverse_iterator();
598 return false; // we don't /eat/ this event. Lower prio
599 // handler should see it, too.
603 ImpShapeEventMap::reverse_iterator maLastIter
;
606 template< typename Handler
, typename Functor
>
607 void UserEventQueue::registerEvent(
608 boost::shared_ptr
< Handler
>& rHandler
,
609 const EventSharedPtr
& rEvent
,
610 const Functor
& rRegistrationFunctor
)
612 ENSURE_OR_THROW( rEvent
,
613 "UserEventQueue::registerEvent(): Invalid event" );
617 rHandler
.reset( new Handler( mrEventQueue
) );
618 // register handler on EventMultiplexer
619 rRegistrationFunctor( rHandler
);
622 rHandler
->addEvent( rEvent
);
625 template< typename Handler
, typename Arg
, typename Functor
>
626 void UserEventQueue::registerEvent(
627 boost::shared_ptr
< Handler
>& rHandler
,
628 const EventSharedPtr
& rEvent
,
630 const Functor
& rRegistrationFunctor
)
632 ENSURE_OR_THROW( rEvent
,
633 "UserEventQueue::registerEvent(): Invalid event" );
637 rHandler
.reset( new Handler( mrEventQueue
) );
639 // register handler on EventMultiplexer
640 rRegistrationFunctor( rHandler
);
643 rHandler
->addEvent( rEvent
, rArg
);
648 // =====================================================
650 UserEventQueue::UserEventQueue( EventMultiplexer
& rMultiplexer
,
651 EventQueue
& rEventQueue
,
652 CursorManager
& rCursorManager
)
653 : mrMultiplexer( rMultiplexer
),
654 mrEventQueue( rEventQueue
),
655 mrCursorManager( rCursorManager
),
656 mpStartEventHandler(),
658 mpAnimationStartEventHandler(),
659 mpAnimationEndEventHandler(),
660 mpAudioStoppedEventHandler(),
661 mpClickEventHandler(),
662 mpSkipEffectEventHandler(),
663 mpRewindEffectEventHandler(),
664 mpDoubleClickEventHandler(),
665 mpMouseEnterHandler(),
666 mpMouseLeaveHandler(),
667 mbAdvanceOnClick( true )
671 UserEventQueue::~UserEventQueue()
675 // unregister all handlers
678 catch (uno::Exception
&) {
679 OSL_FAIL( OUStringToOString(
680 comphelper::anyToString(
681 cppu::getCaughtException() ),
682 RTL_TEXTENCODING_UTF8
).getStr() );
686 void UserEventQueue::clear()
688 // unregister and delete all handlers
689 if( mpStartEventHandler
) {
690 mrMultiplexer
.removeSlideStartHandler( mpStartEventHandler
);
691 mpStartEventHandler
.reset();
693 if( mpEndEventHandler
) {
694 mrMultiplexer
.removeSlideEndHandler( mpEndEventHandler
);
695 mpEndEventHandler
.reset();
697 if( mpAnimationStartEventHandler
) {
698 mrMultiplexer
.removeAnimationStartHandler(
699 mpAnimationStartEventHandler
);
700 mpAnimationStartEventHandler
.reset();
702 if( mpAnimationEndEventHandler
) {
703 mrMultiplexer
.removeAnimationEndHandler( mpAnimationEndEventHandler
);
704 mpAnimationEndEventHandler
.reset();
706 if( mpAudioStoppedEventHandler
) {
707 mrMultiplexer
.removeAudioStoppedHandler( mpAudioStoppedEventHandler
);
708 mpAudioStoppedEventHandler
.reset();
710 if( mpShapeClickEventHandler
) {
711 mrMultiplexer
.removeClickHandler( mpShapeClickEventHandler
);
712 mrMultiplexer
.removeMouseMoveHandler( mpShapeClickEventHandler
);
713 mpShapeClickEventHandler
.reset();
715 if( mpClickEventHandler
) {
716 mrMultiplexer
.removeClickHandler( mpClickEventHandler
);
717 mrMultiplexer
.removeNextEffectHandler( mpClickEventHandler
);
718 mpClickEventHandler
.reset();
720 if(mpSkipEffectEventHandler
) {
721 mrMultiplexer
.removeClickHandler( mpSkipEffectEventHandler
);
722 mrMultiplexer
.removeNextEffectHandler( mpSkipEffectEventHandler
);
723 mpSkipEffectEventHandler
.reset();
725 if(mpRewindEffectEventHandler
) {
726 mrMultiplexer
.removeClickHandler( mpRewindEffectEventHandler
);
727 mpRewindEffectEventHandler
.reset();
729 if( mpShapeDoubleClickEventHandler
) {
730 mrMultiplexer
.removeDoubleClickHandler( mpShapeDoubleClickEventHandler
);
731 mrMultiplexer
.removeMouseMoveHandler( mpShapeDoubleClickEventHandler
);
732 mpShapeDoubleClickEventHandler
.reset();
734 if( mpDoubleClickEventHandler
) {
735 mrMultiplexer
.removeDoubleClickHandler( mpDoubleClickEventHandler
);
736 mpDoubleClickEventHandler
.reset();
738 if( mpMouseEnterHandler
) {
739 mrMultiplexer
.removeMouseMoveHandler( mpMouseEnterHandler
);
740 mpMouseEnterHandler
.reset();
742 if( mpMouseLeaveHandler
) {
743 mrMultiplexer
.removeMouseMoveHandler( mpMouseLeaveHandler
);
744 mpMouseLeaveHandler
.reset();
748 void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick
)
750 mbAdvanceOnClick
= bAdvanceOnClick
;
752 // forward to handler, if existing. Otherwise, the handler
753 // creation will do the forwarding.
754 if( mpClickEventHandler
)
755 mpClickEventHandler
->setAdvanceOnClick( bAdvanceOnClick
);
758 void UserEventQueue::registerAnimationStartEvent(
759 const EventSharedPtr
& rEvent
,
760 const uno::Reference
< animations::XAnimationNode
>& xNode
)
762 registerEvent( mpAnimationStartEventHandler
,
765 boost::bind( &EventMultiplexer::addAnimationStartHandler
,
766 boost::ref( mrMultiplexer
), _1
) );
769 void UserEventQueue::registerAnimationEndEvent(
770 const EventSharedPtr
& rEvent
,
771 const uno::Reference
<animations::XAnimationNode
>& xNode
)
773 registerEvent( mpAnimationEndEventHandler
,
776 boost::bind( &EventMultiplexer::addAnimationEndHandler
,
777 boost::ref( mrMultiplexer
), _1
) );
780 void UserEventQueue::registerAudioStoppedEvent(
781 const EventSharedPtr
& rEvent
,
782 const uno::Reference
<animations::XAnimationNode
>& xNode
)
784 registerEvent( mpAudioStoppedEventHandler
,
787 boost::bind( &EventMultiplexer::addAudioStoppedHandler
,
788 boost::ref( mrMultiplexer
), _1
) );
791 void UserEventQueue::registerShapeClickEvent( const EventSharedPtr
& rEvent
,
792 const ShapeSharedPtr
& rShape
)
796 "UserEventQueue::registerShapeClickEvent(): Invalid event" );
798 if( !mpShapeClickEventHandler
)
801 mpShapeClickEventHandler
.reset(
802 new ShapeClickEventHandler(mrCursorManager
,
805 // register handler on EventMultiplexer
806 mrMultiplexer
.addClickHandler( mpShapeClickEventHandler
, 1.0 );
807 mrMultiplexer
.addMouseMoveHandler( mpShapeClickEventHandler
, 1.0 );
810 mpShapeClickEventHandler
->addEvent( rEvent
, rShape
);
814 class ClickEventRegistrationFunctor
817 ClickEventRegistrationFunctor( EventMultiplexer
& rMultiplexer
,
819 bool bAdvanceOnClick
)
820 : mrMultiplexer( rMultiplexer
),
822 mbAdvanceOnClick( bAdvanceOnClick
) {}
824 void operator()( const boost::shared_ptr
<ClickEventHandler
>& rHandler
)const
826 // register the handler on _two_ sources: we want the
827 // nextEffect events, e.g. space bar, to trigger clicks, as well!
828 mrMultiplexer
.addClickHandler( rHandler
, mnPrio
);
829 mrMultiplexer
.addNextEffectHandler( rHandler
, mnPrio
);
831 // forward advance-on-click state to newly
832 // generated handler (that's the only reason why
833 // we're called here)
834 rHandler
->setAdvanceOnClick( mbAdvanceOnClick
);
838 EventMultiplexer
& mrMultiplexer
;
840 bool const mbAdvanceOnClick
;
844 void UserEventQueue::registerNextEffectEvent( const EventSharedPtr
& rEvent
)
846 // TODO: better name may be mpNextEffectEventHandler? then we have
847 // next effect (=> waiting to be started)
848 // skip effect (skipping the currently running one)
849 // rewind effect (rewinding back running one and waiting (again)
851 registerEvent( mpClickEventHandler
,
853 ClickEventRegistrationFunctor( mrMultiplexer
,
854 0.0 /* default prio */,
855 mbAdvanceOnClick
) );
858 void UserEventQueue::registerSkipEffectEvent(
859 EventSharedPtr
const & pEvent
,
860 const bool bSkipTriggersNextEffect
)
862 if(!mpSkipEffectEventHandler
)
864 mpSkipEffectEventHandler
.reset(
865 new SkipEffectEventHandler( mrEventQueue
, mrMultiplexer
) );
866 // register the handler on _two_ sources: we want the
867 // nextEffect events, e.g. space bar, to trigger clicks, as well!
868 mrMultiplexer
.addClickHandler( mpSkipEffectEventHandler
,
869 -1.0 /* prio below default */ );
870 mrMultiplexer
.addNextEffectHandler( mpSkipEffectEventHandler
,
871 -1.0 /* prio below default */ );
872 // forward advance-on-click state to newly
873 // generated handler (that's the only reason why
874 // we're called here)
875 mpSkipEffectEventHandler
->setAdvanceOnClick( mbAdvanceOnClick
);
877 mpSkipEffectEventHandler
->setSkipTriggersNextEffect(bSkipTriggersNextEffect
);
878 mpSkipEffectEventHandler
->addEvent( pEvent
);
881 void UserEventQueue::registerRewindEffectEvent( EventSharedPtr
const& pEvent
)
883 registerEvent( mpRewindEffectEventHandler
,
885 boost::bind( &EventMultiplexer::addClickHandler
,
886 boost::ref(mrMultiplexer
), _1
,
887 -1.0 /* prio below default */ ) );
890 void UserEventQueue::registerShapeDoubleClickEvent(
891 const EventSharedPtr
& rEvent
,
892 const ShapeSharedPtr
& rShape
)
896 "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );
898 if( !mpShapeDoubleClickEventHandler
)
901 mpShapeDoubleClickEventHandler
.reset(
902 new ShapeClickEventHandler(mrCursorManager
,
905 // register handler on EventMultiplexer
906 mrMultiplexer
.addDoubleClickHandler( mpShapeDoubleClickEventHandler
,
908 mrMultiplexer
.addMouseMoveHandler( mpShapeDoubleClickEventHandler
,
912 mpShapeDoubleClickEventHandler
->addEvent( rEvent
, rShape
);
915 void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr
& rEvent
,
916 const ShapeSharedPtr
& rShape
)
918 registerEvent( mpMouseEnterHandler
,
921 boost::bind( &EventMultiplexer::addMouseMoveHandler
,
922 boost::ref( mrMultiplexer
), _1
,
923 0.0 /* default prio */ ) );
926 void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr
& rEvent
,
927 const ShapeSharedPtr
& rShape
)
929 registerEvent( mpMouseLeaveHandler
,
932 boost::bind( &EventMultiplexer::addMouseMoveHandler
,
933 boost::ref( mrMultiplexer
), _1
,
934 0.0 /* default prio */ ) );
937 void UserEventQueue::callSkipEffectEventHandler (void)
939 ::boost::shared_ptr
<SkipEffectEventHandler
> pHandler (
940 ::boost::dynamic_pointer_cast
<SkipEffectEventHandler
>(mpSkipEffectEventHandler
));
942 pHandler
->skipEffect();
945 } // namespace internal
946 } // namespace presentation
948 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */