1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: usereventqueue.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
35 #include <canvas/debug.hxx>
36 #include <tools/diagnose_ex.h>
38 #include <comphelper/anytostring.hxx>
39 #include <cppuhelper/exc_hlp.hxx>
41 #include <com/sun/star/awt/SystemPointer.hpp>
42 #include <com/sun/star/awt/MouseButton.hpp>
43 #include <com/sun/star/awt/MouseEvent.hpp>
45 #include <boost/bind.hpp>
47 #include "delayevent.hxx"
48 #include "usereventqueue.hxx"
49 #include "cursormanager.hxx"
50 #include "slideshowexceptions.hxx"
59 using namespace com::sun::star
;
61 /* Implementation of UserEventQueue class */
68 typedef std::vector
<EventSharedPtr
> ImpEventVector
;
69 typedef std::queue
<EventSharedPtr
> ImpEventQueue
;
70 typedef std::map
<uno::Reference
<animations::XAnimationNode
>,
71 ImpEventVector
> ImpAnimationEventMap
;
72 typedef std::map
<ShapeSharedPtr
, ImpEventQueue
,
73 Shape::lessThanShape
> ImpShapeEventMap
;
75 // MouseEventHandler base class, not consuming any event:
76 class MouseEventHandler_
: public MouseEventHandler
79 virtual bool handleMousePressed( awt::MouseEvent
const& /*e*/ ) { return false;}
80 virtual bool handleMouseReleased( awt::MouseEvent
const& /*e*/) { return false;}
81 virtual bool handleMouseEntered( awt::MouseEvent
const& /*e*/ ) { return false;}
82 virtual bool handleMouseExited( awt::MouseEvent
const& /*e*/ ) { return false; }
83 virtual bool handleMouseDragged( awt::MouseEvent
const& /*e*/ ) { return false;}
84 virtual bool handleMouseMoved( awt::MouseEvent
const& /*e*/ ) { return false; }
87 /** @return one event has been posted
89 template <typename ContainerT
>
90 bool fireSingleEvent( ContainerT
& rQueue
, EventQueue
& rEventQueue
)
92 // post next event in given queue:
93 while (! rQueue
.empty())
95 EventSharedPtr
const pEvent(rQueue
.front());
98 // skip all inactive events (as the purpose of
99 // nextEventFromQueue() is to activate the next
100 // event, and events which return false on
101 // isCharged() will never be activated by the
103 if(pEvent
->isCharged())
104 return rEventQueue
.addEvent( pEvent
);
106 return false; // no more (active) events in queue
109 /** @return at least one event has been posted
111 template <typename ContainerT
>
112 bool fireAllEvents( ContainerT
& rQueue
, EventQueue
& rEventQueue
)
114 bool bFiredAny
= false;
115 while (fireSingleEvent( rQueue
, rEventQueue
))
127 void clearContainer()
129 maEvents
= ImpEventQueue();
132 void addEvent( const EventSharedPtr
& rEvent
)
134 maEvents
.push( rEvent
);
139 return maEvents
.empty();
143 ImpEventQueue maEvents
;
148 class PlainEventHandler
: public EventHandler
,
149 public EventContainer
152 PlainEventHandler( EventQueue
& rEventQueue
)
153 : EventContainer(), mrEventQueue(rEventQueue
) {}
155 virtual void dispose()
160 virtual bool handleEvent()
162 return fireAllEvents( maEvents
, mrEventQueue
);
166 EventQueue
& mrEventQueue
;
169 class AllAnimationEventHandler
: public AnimationEventHandler
172 AllAnimationEventHandler( EventQueue
& rEventQueue
) :
173 mrEventQueue( rEventQueue
),
174 maAnimationEventMap()
177 virtual void dispose()
179 maAnimationEventMap
.clear();
182 virtual bool handleAnimationEvent( const AnimationNodeSharedPtr
& rNode
)
186 "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );
190 ImpAnimationEventMap::iterator aIter
;
191 if( (aIter
=maAnimationEventMap
.find(
192 rNode
->getXAnimationNode() )) != maAnimationEventMap
.end() )
194 ImpEventVector
& rVec( aIter
->second
);
196 bRet
= !rVec
.empty();
198 // registered node found -> fire all events in the vector
199 std::for_each( rVec
.begin(), rVec
.end(),
200 boost::bind( &EventQueue::addEvent
,
201 boost::ref( mrEventQueue
), _1
) );
209 void addEvent( const EventSharedPtr
& rEvent
,
210 const uno::Reference
< animations::XAnimationNode
>& xNode
)
212 ImpAnimationEventMap::iterator aIter
;
213 if( (aIter
=maAnimationEventMap
.find( xNode
)) ==
214 maAnimationEventMap
.end() )
216 // no entry for this animation -> create one
217 aIter
= maAnimationEventMap
.insert(
218 ImpAnimationEventMap::value_type( xNode
,
219 ImpEventVector() ) ).first
;
222 // add new event to queue
223 aIter
->second
.push_back( rEvent
);
228 // find at least one animation with a non-empty vector
229 ImpAnimationEventMap::const_iterator
aCurr( maAnimationEventMap
.begin() );
230 const ImpAnimationEventMap::const_iterator
aEnd( maAnimationEventMap
.end() );
231 while( aCurr
!= aEnd
)
233 if( !aCurr
->second
.empty() )
234 return false; // at least one non-empty entry found
239 return true; // not a single non-empty entry found
243 EventQueue
& mrEventQueue
;
244 ImpAnimationEventMap maAnimationEventMap
;
247 class ClickEventHandler
: public MouseEventHandler_
,
249 public EventContainer
252 ClickEventHandler( EventQueue
& rEventQueue
) :
254 mrEventQueue( rEventQueue
),
255 mbAdvanceOnClick( true )
258 void setAdvanceOnClick( bool bAdvanceOnClick
)
260 mbAdvanceOnClick
= bAdvanceOnClick
;
264 virtual void dispose()
269 // triggered by API calls, e.g. space bar
270 virtual bool handleEvent()
272 return handleEvent_impl();
275 // triggered by mouse release:
276 virtual bool handleMouseReleased( const awt::MouseEvent
& evt
)
278 if(evt
.Buttons
!= awt::MouseButton::LEFT
)
281 if( mbAdvanceOnClick
) {
283 return handleEvent_impl();
286 return false; // advance-on-click disabled
290 // triggered by both:
291 virtual bool handleEvent_impl()
294 return fireSingleEvent( maEvents
, mrEventQueue
);
298 EventQueue
& mrEventQueue
;
299 bool mbAdvanceOnClick
;
302 class SkipEffectEventHandler
: public ClickEventHandler
305 SkipEffectEventHandler( EventQueue
& rEventQueue
,
306 EventMultiplexer
& rEventMultiplexer
)
307 : ClickEventHandler(rEventQueue
),
308 mrEventQueue(rEventQueue
),
309 mrEventMultiplexer(rEventMultiplexer
),
310 mbSkipTriggersNextEffect(true) {}
312 /** Remember to trigger (or not to trigger) the next effect after the
313 current effect is skiped.
315 void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect
)
316 { mbSkipTriggersNextEffect
= bSkipTriggersNextEffect
; }
318 /// Skip the current effect but do not triggere the next effect.
319 void skipEffect (void) { handleEvent_impl(false); }
322 virtual bool handleEvent_impl()
324 return handleEvent_impl(true);
327 bool handleEvent_impl (bool bNotifyNextEffect
)
329 // fire all events, so animation nodes can register their
330 // next effect listeners:
331 if(fireAllEvents( maEvents
, mrEventQueue
))
333 makeEvent(::boost::bind(&EventQueue::forceEmpty
, ::boost::ref(mrEventQueue
)));
334 if (mbSkipTriggersNextEffect
&& bNotifyNextEffect
)
336 // then simulate a next effect event: this skip effect
337 // handler is triggered upon next effect events (multiplexer
338 // prio=-1)! Posting a notifyNextEffect() here is only safe
339 // (we don't run into busy loop), because we assume that
340 // someone has registerered above for next effects
341 // (multiplexer prio=0) at the user event queue.
342 return mrEventQueue
.addEventWhenQueueIsEmpty(
343 makeEvent( boost::bind(
344 &EventMultiplexer::notifyNextEffect
,
345 boost::ref(mrEventMultiplexer
) ) ) );
354 EventQueue
& mrEventQueue
;
355 EventMultiplexer
& mrEventMultiplexer
;
356 bool mbSkipTriggersNextEffect
;
359 class RewindEffectEventHandler
: public MouseEventHandler_
,
360 public EventContainer
363 RewindEffectEventHandler( EventQueue
& rEventQueue
)
364 : EventContainer(), mrEventQueue(rEventQueue
) {}
367 virtual void dispose()
372 virtual bool handleMouseReleased( awt::MouseEvent
const& evt
)
374 if(evt
.Buttons
!= awt::MouseButton::RIGHT
)
377 return fireAllEvents( maEvents
, mrEventQueue
);
381 EventQueue
& mrEventQueue
;
384 /** Base class to share some common code between
385 ShapeClickEventHandler and MouseMoveHandler
387 @derive override necessary MouseEventHandler interface methods,
388 call sendEvent() method to actually process the event.
390 class MouseHandlerBase
: public MouseEventHandler_
393 MouseHandlerBase( EventQueue
& rEventQueue
) :
394 mrEventQueue( rEventQueue
),
398 virtual void dispose()
400 // TODO(Q1): Check whether plain vector with swap idiom is
402 maShapeEventMap
= ImpShapeEventMap();
405 void addEvent( const EventSharedPtr
& rEvent
,
406 const ShapeSharedPtr
& rShape
)
408 ImpShapeEventMap::iterator aIter
;
409 if( (aIter
=maShapeEventMap
.find( rShape
)) == maShapeEventMap
.end() )
411 // no entry for this shape -> create one
412 aIter
= maShapeEventMap
.insert(
413 ImpShapeEventMap::value_type( rShape
,
414 ImpEventQueue() ) ).first
;
417 // add new event to queue
418 aIter
->second
.push( rEvent
);
423 // find at least one shape with a non-empty queue
424 ImpShapeEventMap::reverse_iterator
aCurrShape( maShapeEventMap
.begin());
425 ImpShapeEventMap::reverse_iterator
aEndShape( maShapeEventMap
.end() );
426 while( aCurrShape
!= aEndShape
)
428 if( !aCurrShape
->second
.empty() )
429 return false; // at least one non-empty entry found
434 return true; // not a single non-empty entry found
438 bool hitTest( const awt::MouseEvent
& e
,
439 ImpShapeEventMap::reverse_iterator
& o_rHitShape
)
441 // find hit shape in map
442 const basegfx::B2DPoint
aPosition( e
.X
, e
.Y
);
444 // find matching shape (scan reversely, to coarsely match
446 ImpShapeEventMap::reverse_iterator
aCurrShape(maShapeEventMap
.rbegin());
447 const ImpShapeEventMap::reverse_iterator
aEndShape( maShapeEventMap
.rend() );
448 while( aCurrShape
!= aEndShape
)
450 // TODO(F2): Get proper geometry polygon from the
451 // shape, to avoid having areas outside the shape
452 // react on the mouse
453 if( aCurrShape
->first
->getBounds().isInside( aPosition
) &&
454 aCurrShape
->first
->isVisible() )
456 // shape hit, and shape is visible - report a
458 o_rHitShape
= aCurrShape
;
465 return false; // nothing hit
468 bool sendEvent( ImpShapeEventMap::reverse_iterator
& io_rHitShape
)
470 // take next event from queue
471 const bool bRet( fireSingleEvent( io_rHitShape
->second
,
474 // clear shape entry, if its queue is
475 // empty. This is important, since the shapes
476 // are held by shared ptr, and might otherwise
477 // not get released, even after their owning
478 // slide is long gone.
479 if( io_rHitShape
->second
.empty() )
481 // this looks funny, since ::std::map does
482 // provide an erase( iterator )
483 // method. Unfortunately, stlport does not
484 // declare the obvious erase(
485 // reverse_iterator ) needed here (missing
486 // orthogonality, eh?)
487 maShapeEventMap
.erase( io_rHitShape
->first
);
493 bool processEvent( const awt::MouseEvent
& e
)
495 ImpShapeEventMap::reverse_iterator aCurrShape
;
497 if( hitTest( e
, aCurrShape
) )
498 return sendEvent( aCurrShape
);
500 return false; // did not handle the event
504 EventQueue
& mrEventQueue
;
505 ImpShapeEventMap maShapeEventMap
;
508 class ShapeClickEventHandler
: public MouseHandlerBase
511 ShapeClickEventHandler( CursorManager
& rCursorManager
,
512 EventQueue
& rEventQueue
) :
513 MouseHandlerBase( rEventQueue
),
514 mrCursorManager( rCursorManager
)
517 virtual bool handleMouseReleased( const awt::MouseEvent
& e
)
519 if(e
.Buttons
!= awt::MouseButton::LEFT
)
521 return processEvent( e
);
524 virtual bool handleMouseMoved( const awt::MouseEvent
& e
)
526 // TODO(P2): Maybe buffer last shape touched
528 // if we have a shape click event, and the mouse
529 // hovers over this shape, change cursor to hand
530 ImpShapeEventMap::reverse_iterator aDummy
;
531 if( hitTest( e
, aDummy
) )
532 mrCursorManager
.requestCursor( awt::SystemPointer::REFHAND
);
534 return false; // we don't /eat/ this event. Lower prio
535 // handler should see it, too.
539 CursorManager
& mrCursorManager
;
542 class MouseEnterHandler
: public MouseHandlerBase
545 MouseEnterHandler( EventQueue
& rEventQueue
)
546 : MouseHandlerBase( rEventQueue
),
549 virtual bool handleMouseMoved( const awt::MouseEvent
& e
)
551 // TODO(P2): Maybe buffer last shape touched, and
552 // check against that _first_
554 ImpShapeEventMap::reverse_iterator aCurr
;
555 if( hitTest( e
, aCurr
) )
557 if( aCurr
->first
!= mpLastShape
)
559 // we actually hit a shape, and it's different
560 // from the previous one - thus we just
561 // entered it, raise event
563 mpLastShape
= aCurr
->first
;
568 // don't hit no shape - thus, last shape is NULL
572 return false; // we don't /eat/ this event. Lower prio
573 // handler should see it, too.
577 ShapeSharedPtr mpLastShape
;
580 class MouseLeaveHandler
: public MouseHandlerBase
583 MouseLeaveHandler( EventQueue
& rEventQueue
)
584 : MouseHandlerBase( rEventQueue
),
587 virtual bool handleMouseMoved( const awt::MouseEvent
& e
)
589 // TODO(P2): Maybe buffer last shape touched, and
590 // check against that _first_
592 ImpShapeEventMap::reverse_iterator aCurr
;
593 if( hitTest( e
, aCurr
) )
599 if( maLastIter
->first
)
601 // last time, we were over a shape, now we're
602 // not - we thus just left that shape, raise
604 sendEvent( maLastIter
);
607 // in any case, when we hit this else-branch: no
608 // shape hit, thus have to clear maLastIter
609 maLastIter
= ImpShapeEventMap::reverse_iterator();
612 return false; // we don't /eat/ this event. Lower prio
613 // handler should see it, too.
617 ImpShapeEventMap::reverse_iterator maLastIter
;
620 template< typename Handler
, typename Functor
>
621 void UserEventQueue::registerEvent(
622 boost::shared_ptr
< Handler
>& rHandler
,
623 const EventSharedPtr
& rEvent
,
624 const Functor
& rRegistrationFunctor
)
626 ENSURE_OR_THROW( rEvent
,
627 "UserEventQueue::registerEvent(): Invalid event" );
631 rHandler
.reset( new Handler( mrEventQueue
) );
632 // register handler on EventMultiplexer
633 rRegistrationFunctor( rHandler
);
636 rHandler
->addEvent( rEvent
);
639 template< typename Handler
, typename Arg
, typename Functor
>
640 void UserEventQueue::registerEvent(
641 boost::shared_ptr
< Handler
>& rHandler
,
642 const EventSharedPtr
& rEvent
,
644 const Functor
& rRegistrationFunctor
)
646 ENSURE_OR_THROW( rEvent
,
647 "UserEventQueue::registerEvent(): Invalid event" );
651 rHandler
.reset( new Handler( mrEventQueue
) );
653 // register handler on EventMultiplexer
654 rRegistrationFunctor( rHandler
);
657 rHandler
->addEvent( rEvent
, rArg
);
662 // =====================================================
664 UserEventQueue::UserEventQueue( EventMultiplexer
& rMultiplexer
,
665 EventQueue
& rEventQueue
,
666 CursorManager
& rCursorManager
)
667 : mrMultiplexer( rMultiplexer
),
668 mrEventQueue( rEventQueue
),
669 mrCursorManager( rCursorManager
),
670 mpStartEventHandler(),
672 mpAnimationStartEventHandler(),
673 mpAnimationEndEventHandler(),
674 mpAudioStoppedEventHandler(),
675 mpClickEventHandler(),
676 mpSkipEffectEventHandler(),
677 mpRewindEffectEventHandler(),
678 mpDoubleClickEventHandler(),
679 mpMouseEnterHandler(),
680 mpMouseLeaveHandler(),
681 mbAdvanceOnClick( true )
685 UserEventQueue::~UserEventQueue()
689 // unregister all handlers
692 catch (uno::Exception
&) {
693 OSL_ENSURE( false, rtl::OUStringToOString(
694 comphelper::anyToString(
695 cppu::getCaughtException() ),
696 RTL_TEXTENCODING_UTF8
).getStr() );
700 bool UserEventQueue::isEmpty() const
702 // TODO(T2): This is not thread safe, the handlers are all
703 // only separately synchronized. This poses the danger of
704 // generating false empty status on XSlideShow::update(), such
705 // that the last events of a slide are not triggered.
707 // we're empty iff all handler queues are empty
709 (mpStartEventHandler
? mpStartEventHandler
->isEmpty() : true) &&
710 (mpEndEventHandler
? mpEndEventHandler
->isEmpty() : true) &&
711 (mpAnimationStartEventHandler
? mpAnimationStartEventHandler
->isEmpty() : true) &&
712 (mpAnimationEndEventHandler
? mpAnimationEndEventHandler
->isEmpty() : true) &&
713 (mpAudioStoppedEventHandler
? mpAudioStoppedEventHandler
->isEmpty() : true) &&
714 (mpShapeClickEventHandler
? mpShapeClickEventHandler
->isEmpty() : true) &&
715 (mpClickEventHandler
? mpClickEventHandler
->isEmpty() : true) &&
716 (mpSkipEffectEventHandler
? mpSkipEffectEventHandler
->isEmpty() : true) &&
717 (mpRewindEffectEventHandler
? mpRewindEffectEventHandler
->isEmpty() : true) &&
718 (mpShapeDoubleClickEventHandler
? mpShapeDoubleClickEventHandler
->isEmpty() : true) &&
719 (mpDoubleClickEventHandler
? mpDoubleClickEventHandler
->isEmpty() : true) &&
720 (mpMouseEnterHandler
? mpMouseEnterHandler
->isEmpty() : true) &&
721 (mpMouseLeaveHandler
? mpMouseLeaveHandler
->isEmpty() : true);
724 void UserEventQueue::clear()
726 // unregister and delete all handlers
727 if( mpStartEventHandler
) {
728 mrMultiplexer
.removeSlideStartHandler( mpStartEventHandler
);
729 mpStartEventHandler
.reset();
731 if( mpEndEventHandler
) {
732 mrMultiplexer
.removeSlideEndHandler( mpEndEventHandler
);
733 mpEndEventHandler
.reset();
735 if( mpAnimationStartEventHandler
) {
736 mrMultiplexer
.removeAnimationStartHandler(
737 mpAnimationStartEventHandler
);
738 mpAnimationStartEventHandler
.reset();
740 if( mpAnimationEndEventHandler
) {
741 mrMultiplexer
.removeAnimationEndHandler( mpAnimationEndEventHandler
);
742 mpAnimationEndEventHandler
.reset();
744 if( mpAudioStoppedEventHandler
) {
745 mrMultiplexer
.removeAudioStoppedHandler( mpAudioStoppedEventHandler
);
746 mpAudioStoppedEventHandler
.reset();
748 if( mpShapeClickEventHandler
) {
749 mrMultiplexer
.removeClickHandler( mpShapeClickEventHandler
);
750 mrMultiplexer
.removeMouseMoveHandler( mpShapeClickEventHandler
);
751 mpShapeClickEventHandler
.reset();
753 if( mpClickEventHandler
) {
754 mrMultiplexer
.removeClickHandler( mpClickEventHandler
);
755 mrMultiplexer
.removeNextEffectHandler( mpClickEventHandler
);
756 mpClickEventHandler
.reset();
758 if(mpSkipEffectEventHandler
) {
759 mrMultiplexer
.removeClickHandler( mpSkipEffectEventHandler
);
760 mrMultiplexer
.removeNextEffectHandler( mpSkipEffectEventHandler
);
761 mpSkipEffectEventHandler
.reset();
763 if(mpRewindEffectEventHandler
) {
764 mrMultiplexer
.removeClickHandler( mpRewindEffectEventHandler
);
765 mpRewindEffectEventHandler
.reset();
767 if( mpShapeDoubleClickEventHandler
) {
768 mrMultiplexer
.removeDoubleClickHandler( mpShapeDoubleClickEventHandler
);
769 mrMultiplexer
.removeMouseMoveHandler( mpShapeDoubleClickEventHandler
);
770 mpShapeDoubleClickEventHandler
.reset();
772 if( mpDoubleClickEventHandler
) {
773 mrMultiplexer
.removeDoubleClickHandler( mpDoubleClickEventHandler
);
774 mpDoubleClickEventHandler
.reset();
776 if( mpMouseEnterHandler
) {
777 mrMultiplexer
.removeMouseMoveHandler( mpMouseEnterHandler
);
778 mpMouseEnterHandler
.reset();
780 if( mpMouseLeaveHandler
) {
781 mrMultiplexer
.removeMouseMoveHandler( mpMouseLeaveHandler
);
782 mpMouseLeaveHandler
.reset();
786 void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick
)
788 mbAdvanceOnClick
= bAdvanceOnClick
;
790 // forward to handler, if existing. Otherwise, the handler
791 // creation will do the forwarding.
792 if( mpClickEventHandler
)
793 mpClickEventHandler
->setAdvanceOnClick( bAdvanceOnClick
);
796 void UserEventQueue::registerSlideStartEvent( const EventSharedPtr
& rEvent
)
798 registerEvent( mpStartEventHandler
,
800 boost::bind( &EventMultiplexer::addSlideStartHandler
,
801 boost::ref( mrMultiplexer
), _1
) );
804 void UserEventQueue::registerSlideEndEvent( const EventSharedPtr
& rEvent
)
806 registerEvent( mpEndEventHandler
,
808 boost::bind( &EventMultiplexer::addSlideEndHandler
,
809 boost::ref( mrMultiplexer
), _1
) );
812 void UserEventQueue::registerAnimationStartEvent(
813 const EventSharedPtr
& rEvent
,
814 const uno::Reference
< animations::XAnimationNode
>& xNode
)
816 registerEvent( mpAnimationStartEventHandler
,
819 boost::bind( &EventMultiplexer::addAnimationStartHandler
,
820 boost::ref( mrMultiplexer
), _1
) );
823 void UserEventQueue::registerAnimationEndEvent(
824 const EventSharedPtr
& rEvent
,
825 const uno::Reference
<animations::XAnimationNode
>& xNode
)
827 registerEvent( mpAnimationEndEventHandler
,
830 boost::bind( &EventMultiplexer::addAnimationEndHandler
,
831 boost::ref( mrMultiplexer
), _1
) );
834 void UserEventQueue::registerAudioStoppedEvent(
835 const EventSharedPtr
& rEvent
,
836 const uno::Reference
<animations::XAnimationNode
>& xNode
)
838 registerEvent( mpAudioStoppedEventHandler
,
841 boost::bind( &EventMultiplexer::addAudioStoppedHandler
,
842 boost::ref( mrMultiplexer
), _1
) );
845 void UserEventQueue::registerShapeClickEvent( const EventSharedPtr
& rEvent
,
846 const ShapeSharedPtr
& rShape
)
850 "UserEventQueue::registerShapeClickEvent(): Invalid event" );
852 if( !mpShapeClickEventHandler
)
855 mpShapeClickEventHandler
.reset(
856 new ShapeClickEventHandler(mrCursorManager
,
859 // register handler on EventMultiplexer
860 mrMultiplexer
.addClickHandler( mpShapeClickEventHandler
, 1.0 );
861 mrMultiplexer
.addMouseMoveHandler( mpShapeClickEventHandler
, 1.0 );
864 mpShapeClickEventHandler
->addEvent( rEvent
, rShape
);
868 class ClickEventRegistrationFunctor
871 ClickEventRegistrationFunctor( EventMultiplexer
& rMultiplexer
,
873 bool bAdvanceOnClick
)
874 : mrMultiplexer( rMultiplexer
),
876 mbAdvanceOnClick( bAdvanceOnClick
) {}
878 void operator()( const boost::shared_ptr
<ClickEventHandler
>& rHandler
)const
880 // register the handler on _two_ sources: we want the
881 // nextEffect events, e.g. space bar, to trigger clicks, as well!
882 mrMultiplexer
.addClickHandler( rHandler
, mnPrio
);
883 mrMultiplexer
.addNextEffectHandler( rHandler
, mnPrio
);
885 // forward advance-on-click state to newly
886 // generated handler (that's the only reason why
887 // we're called here)
888 rHandler
->setAdvanceOnClick( mbAdvanceOnClick
);
892 EventMultiplexer
& mrMultiplexer
;
894 bool const mbAdvanceOnClick
;
898 void UserEventQueue::registerNextEffectEvent( const EventSharedPtr
& rEvent
)
900 // TODO: better name may be mpNextEffectEventHandler? then we have
901 // next effect (=> waiting to be started)
902 // skip effect (skipping the currently running one)
903 // rewind effect (rewinding back running one and waiting (again)
905 registerEvent( mpClickEventHandler
,
907 ClickEventRegistrationFunctor( mrMultiplexer
,
908 0.0 /* default prio */,
909 mbAdvanceOnClick
) );
912 void UserEventQueue::registerSkipEffectEvent(
913 EventSharedPtr
const & pEvent
,
914 const bool bSkipTriggersNextEffect
)
916 if(!mpSkipEffectEventHandler
)
918 mpSkipEffectEventHandler
.reset(
919 new SkipEffectEventHandler( mrEventQueue
, mrMultiplexer
) );
920 // register the handler on _two_ sources: we want the
921 // nextEffect events, e.g. space bar, to trigger clicks, as well!
922 mrMultiplexer
.addClickHandler( mpSkipEffectEventHandler
,
923 -1.0 /* prio below default */ );
924 mrMultiplexer
.addNextEffectHandler( mpSkipEffectEventHandler
,
925 -1.0 /* prio below default */ );
926 // forward advance-on-click state to newly
927 // generated handler (that's the only reason why
928 // we're called here)
929 mpSkipEffectEventHandler
->setAdvanceOnClick( mbAdvanceOnClick
);
931 mpSkipEffectEventHandler
->setSkipTriggersNextEffect(bSkipTriggersNextEffect
);
932 mpSkipEffectEventHandler
->addEvent( pEvent
);
935 void UserEventQueue::registerRewindEffectEvent( EventSharedPtr
const& pEvent
)
937 registerEvent( mpRewindEffectEventHandler
,
939 boost::bind( &EventMultiplexer::addClickHandler
,
940 boost::ref(mrMultiplexer
), _1
,
941 -1.0 /* prio below default */ ) );
944 void UserEventQueue::registerShapeDoubleClickEvent(
945 const EventSharedPtr
& rEvent
,
946 const ShapeSharedPtr
& rShape
)
950 "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );
952 if( !mpShapeDoubleClickEventHandler
)
955 mpShapeDoubleClickEventHandler
.reset(
956 new ShapeClickEventHandler(mrCursorManager
,
959 // register handler on EventMultiplexer
960 mrMultiplexer
.addDoubleClickHandler( mpShapeDoubleClickEventHandler
,
962 mrMultiplexer
.addMouseMoveHandler( mpShapeDoubleClickEventHandler
,
966 mpShapeDoubleClickEventHandler
->addEvent( rEvent
, rShape
);
969 void UserEventQueue::registerDoubleClickEvent( const EventSharedPtr
& rEvent
)
971 registerEvent( mpDoubleClickEventHandler
,
973 boost::bind( &EventMultiplexer::addDoubleClickHandler
,
974 boost::ref( mrMultiplexer
), _1
,
975 0.0 /* default prio */ ) );
978 void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr
& rEvent
,
979 const ShapeSharedPtr
& rShape
)
981 registerEvent( mpMouseEnterHandler
,
984 boost::bind( &EventMultiplexer::addMouseMoveHandler
,
985 boost::ref( mrMultiplexer
), _1
,
986 0.0 /* default prio */ ) );
989 void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr
& rEvent
,
990 const ShapeSharedPtr
& rShape
)
992 registerEvent( mpMouseLeaveHandler
,
995 boost::bind( &EventMultiplexer::addMouseMoveHandler
,
996 boost::ref( mrMultiplexer
), _1
,
997 0.0 /* default prio */ ) );
1000 void UserEventQueue::callSkipEffectEventHandler (void)
1002 ::boost::shared_ptr
<SkipEffectEventHandler
> pHandler (
1003 ::boost::dynamic_pointer_cast
<SkipEffectEventHandler
>(mpSkipEffectEventHandler
));
1005 pHandler
->skipEffect();
1008 } // namespace internal
1009 } // namespace presentation