fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / slideshow / source / engine / usereventqueue.cxx
blobaf5f0529920ddb61d4ed5c357bbd441de5cc1be1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 // must be first
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"
39 #include <vector>
40 #include <queue>
41 #include <map>
42 #include <functional>
43 #include <algorithm>
46 using namespace com::sun::star;
48 /* Implementation of UserEventQueue class */
50 namespace slideshow {
51 namespace internal {
53 namespace {
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
65 public:
66 virtual bool handleMousePressed( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false;}
67 virtual bool handleMouseReleased( awt::MouseEvent const& /*e*/) SAL_OVERRIDE { return false;}
68 virtual bool handleMouseEntered( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false;}
69 virtual bool handleMouseExited( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false; }
70 virtual bool handleMouseDragged( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false;}
71 virtual bool handleMouseMoved( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { 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());
83 rQueue.pop();
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
89 // EventQueue)
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 ))
103 bFiredAny = true;
104 return bFiredAny;
107 class EventContainer
109 public:
110 EventContainer() :
111 maEvents()
114 void addEvent( const EventSharedPtr& rEvent )
116 maEvents.push( rEvent );
119 protected:
120 ImpEventQueue maEvents;
123 } // anon namespace
125 class AllAnimationEventHandler : public AnimationEventHandler
127 public:
128 AllAnimationEventHandler( EventQueue& rEventQueue ) :
129 mrEventQueue( rEventQueue ),
130 maAnimationEventMap()
133 virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) SAL_OVERRIDE
135 ENSURE_OR_RETURN_FALSE(
136 rNode,
137 "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );
139 bool bRet( false );
141 ImpAnimationEventMap::iterator aIter;
142 if( (aIter=maAnimationEventMap.find(
143 rNode->getXAnimationNode() )) != maAnimationEventMap.end() )
145 ImpEventVector& rVec( aIter->second );
147 bRet = !rVec.empty();
149 // registered node found -> fire all events in the vector
150 std::for_each( rVec.begin(), rVec.end(),
151 boost::bind( &EventQueue::addEvent,
152 boost::ref( mrEventQueue ), _1 ) );
154 rVec.clear();
157 return bRet;
160 void addEvent( const EventSharedPtr& rEvent,
161 const uno::Reference< animations::XAnimationNode >& xNode )
163 ImpAnimationEventMap::iterator aIter;
164 if( (aIter=maAnimationEventMap.find( xNode )) ==
165 maAnimationEventMap.end() )
167 // no entry for this animation -> create one
168 aIter = maAnimationEventMap.insert(
169 ImpAnimationEventMap::value_type( xNode,
170 ImpEventVector() ) ).first;
173 // add new event to queue
174 aIter->second.push_back( rEvent );
177 private:
178 EventQueue& mrEventQueue;
179 ImpAnimationEventMap maAnimationEventMap;
182 class ClickEventHandler : public MouseEventHandler_,
183 public EventHandler,
184 public EventContainer
186 public:
187 ClickEventHandler( EventQueue& rEventQueue ) :
188 EventContainer(),
189 mrEventQueue( rEventQueue ),
190 mbAdvanceOnClick( true )
193 void setAdvanceOnClick( bool bAdvanceOnClick )
195 mbAdvanceOnClick = bAdvanceOnClick;
198 private:
200 // triggered by API calls, e.g. space bar
201 virtual bool handleEvent() SAL_OVERRIDE
203 return handleEvent_impl();
206 // triggered by mouse release:
207 virtual bool handleMouseReleased( const awt::MouseEvent& evt ) SAL_OVERRIDE
209 if(evt.Buttons != awt::MouseButton::LEFT)
210 return false;
212 if( mbAdvanceOnClick ) {
213 // fire next event
214 return handleEvent_impl();
216 else {
217 return false; // advance-on-click disabled
221 // triggered by both:
222 virtual bool handleEvent_impl()
224 // fire next event:
225 return fireSingleEvent( maEvents, mrEventQueue );
228 private:
229 EventQueue& mrEventQueue;
230 bool mbAdvanceOnClick;
233 class SkipEffectEventHandler : public ClickEventHandler
235 public:
236 SkipEffectEventHandler( EventQueue & rEventQueue,
237 EventMultiplexer & rEventMultiplexer )
238 : ClickEventHandler(rEventQueue),
239 mrEventQueue(rEventQueue),
240 mrEventMultiplexer(rEventMultiplexer),
241 mbSkipTriggersNextEffect(true) {}
243 /** Remember to trigger (or not to trigger) the next effect after the
244 current effect is skipped.
246 void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect)
247 { mbSkipTriggersNextEffect = bSkipTriggersNextEffect; }
249 /// Skip the current effect but do not trigger the next effect.
250 void skipEffect() { handleEvent_impl(false); }
252 private:
253 virtual bool handleEvent_impl() SAL_OVERRIDE
255 return handleEvent_impl(true);
258 bool handleEvent_impl (bool bNotifyNextEffect)
260 // fire all events, so animation nodes can register their
261 // next effect listeners:
262 if(fireAllEvents( maEvents, mrEventQueue ))
264 if (mbSkipTriggersNextEffect && bNotifyNextEffect)
266 // then simulate a next effect event: this skip effect
267 // handler is triggered upon next effect events (multiplexer
268 // prio=-1)! Posting a notifyNextEffect() here is only safe
269 // (we don't run into busy loop), because we assume that
270 // someone has registerered above for next effects
271 // (multiplexer prio=0) at the user event queue.
272 return mrEventQueue.addEventWhenQueueIsEmpty(
273 makeEvent( boost::bind( &EventMultiplexer::notifyNextEffect,
274 boost::ref(mrEventMultiplexer) ),
275 "EventMultiplexer::notifyNextEffect") );
277 else
278 return true;
280 return false;
283 private:
284 EventQueue & mrEventQueue;
285 EventMultiplexer & mrEventMultiplexer;
286 bool mbSkipTriggersNextEffect;
289 /** Base class to share some common code between
290 ShapeClickEventHandler and MouseMoveHandler
292 @derive override necessary MouseEventHandler interface methods,
293 call sendEvent() method to actually process the event.
295 class MouseHandlerBase : public MouseEventHandler_
297 public:
298 MouseHandlerBase( EventQueue& rEventQueue ) :
299 mrEventQueue( rEventQueue ),
300 maShapeEventMap()
303 void addEvent( const EventSharedPtr& rEvent,
304 const ShapeSharedPtr& rShape )
306 ImpShapeEventMap::iterator aIter;
307 if( (aIter=maShapeEventMap.find( rShape )) == maShapeEventMap.end() )
309 // no entry for this shape -> create one
310 aIter = maShapeEventMap.insert(
311 ImpShapeEventMap::value_type( rShape,
312 ImpEventQueue() ) ).first;
315 // add new event to queue
316 aIter->second.push( rEvent );
319 protected:
320 bool hitTest( const awt::MouseEvent& e,
321 ImpShapeEventMap::reverse_iterator& o_rHitShape )
323 // find hit shape in map
324 const basegfx::B2DPoint aPosition( e.X, e.Y );
326 // find matching shape (scan reversely, to coarsely match
327 // paint order)
328 ImpShapeEventMap::reverse_iterator aCurrShape(maShapeEventMap.rbegin());
329 const ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.rend() );
330 while( aCurrShape != aEndShape )
332 // TODO(F2): Get proper geometry polygon from the
333 // shape, to avoid having areas outside the shape
334 // react on the mouse
335 if( aCurrShape->first->getBounds().isInside( aPosition ) &&
336 aCurrShape->first->isVisible() )
338 // shape hit, and shape is visible - report a
339 // hit
340 o_rHitShape = aCurrShape;
341 return true;
344 ++aCurrShape;
347 return false; // nothing hit
350 bool sendEvent( ImpShapeEventMap::reverse_iterator& io_rHitShape )
352 // take next event from queue
353 const bool bRet( fireSingleEvent( io_rHitShape->second,
354 mrEventQueue ) );
356 // clear shape entry, if its queue is
357 // empty. This is important, since the shapes
358 // are held by shared ptr, and might otherwise
359 // not get released, even after their owning
360 // slide is long gone.
361 if( io_rHitShape->second.empty() )
363 // this looks funny, since ::std::map does
364 // provide an erase( iterator )
365 // method. Unfortunately, C++ does not
366 // declare the obvious erase(
367 // reverse_iterator ) needed here (missing
368 // orthogonality, eh?)
369 maShapeEventMap.erase( io_rHitShape->first );
372 return bRet;
375 bool processEvent( const awt::MouseEvent& e )
377 ImpShapeEventMap::reverse_iterator aCurrShape;
379 if( hitTest( e, aCurrShape ) )
380 return sendEvent( aCurrShape );
382 return false; // did not handle the event
385 private:
386 EventQueue& mrEventQueue;
387 ImpShapeEventMap maShapeEventMap;
390 class ShapeClickEventHandler : public MouseHandlerBase
392 public:
393 ShapeClickEventHandler( CursorManager& rCursorManager,
394 EventQueue& rEventQueue ) :
395 MouseHandlerBase( rEventQueue ),
396 mrCursorManager( rCursorManager )
399 virtual bool handleMouseReleased( const awt::MouseEvent& e ) SAL_OVERRIDE
401 if(e.Buttons != awt::MouseButton::LEFT)
402 return false;
403 return processEvent( e );
406 virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
408 // TODO(P2): Maybe buffer last shape touched
410 // if we have a shape click event, and the mouse
411 // hovers over this shape, change cursor to hand
412 ImpShapeEventMap::reverse_iterator aDummy;
413 if( hitTest( e, aDummy ) )
414 mrCursorManager.requestCursor( awt::SystemPointer::REFHAND );
416 return false; // we don't /eat/ this event. Lower prio
417 // handler should see it, too.
420 private:
421 CursorManager& mrCursorManager;
424 class MouseEnterHandler : public MouseHandlerBase
426 public:
427 MouseEnterHandler( EventQueue& rEventQueue )
428 : MouseHandlerBase( rEventQueue ),
429 mpLastShape() {}
431 virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
433 // TODO(P2): Maybe buffer last shape touched, and
434 // check against that _first_
436 ImpShapeEventMap::reverse_iterator aCurr;
437 if( hitTest( e, aCurr ) )
439 if( aCurr->first != mpLastShape )
441 // we actually hit a shape, and it's different
442 // from the previous one - thus we just
443 // entered it, raise event
444 sendEvent( aCurr );
445 mpLastShape = aCurr->first;
448 else
450 // don't hit no shape - thus, last shape is NULL
451 mpLastShape.reset();
454 return false; // we don't /eat/ this event. Lower prio
455 // handler should see it, too.
458 private:
459 ShapeSharedPtr mpLastShape;
462 class MouseLeaveHandler : public MouseHandlerBase
464 public:
465 MouseLeaveHandler( EventQueue& rEventQueue )
466 : MouseHandlerBase( rEventQueue ),
467 maLastIter() {}
469 virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
471 // TODO(P2): Maybe buffer last shape touched, and
472 // check against that _first_
474 ImpShapeEventMap::reverse_iterator aCurr;
475 if( hitTest( e, aCurr ) )
477 maLastIter = aCurr;
479 else
481 if( maLastIter->first )
483 // last time, we were over a shape, now we're
484 // not - we thus just left that shape, raise
485 // event
486 sendEvent( maLastIter );
489 // in any case, when we hit this else-branch: no
490 // shape hit, thus have to clear maLastIter
491 maLastIter = ImpShapeEventMap::reverse_iterator();
494 return false; // we don't /eat/ this event. Lower prio
495 // handler should see it, too.
498 private:
499 ImpShapeEventMap::reverse_iterator maLastIter;
502 template< typename Handler, typename Functor >
503 void UserEventQueue::registerEvent(
504 boost::shared_ptr< Handler >& rHandler,
505 const EventSharedPtr& rEvent,
506 const Functor& rRegistrationFunctor )
508 ENSURE_OR_THROW( rEvent,
509 "UserEventQueue::registerEvent(): Invalid event" );
511 if( !rHandler ) {
512 // create handler
513 rHandler.reset( new Handler( mrEventQueue ) );
514 // register handler on EventMultiplexer
515 rRegistrationFunctor( rHandler );
518 rHandler->addEvent( rEvent );
521 template< typename Handler, typename Arg, typename Functor >
522 void UserEventQueue::registerEvent(
523 boost::shared_ptr< Handler >& rHandler,
524 const EventSharedPtr& rEvent,
525 const Arg& rArg,
526 const Functor& rRegistrationFunctor )
528 ENSURE_OR_THROW( rEvent,
529 "UserEventQueue::registerEvent(): Invalid event" );
531 if( !rHandler ) {
532 // create handler
533 rHandler.reset( new Handler( mrEventQueue ) );
535 // register handler on EventMultiplexer
536 rRegistrationFunctor( rHandler );
539 rHandler->addEvent( rEvent, rArg );
544 UserEventQueue::UserEventQueue( EventMultiplexer& rMultiplexer,
545 EventQueue& rEventQueue,
546 CursorManager& rCursorManager )
547 : mrMultiplexer( rMultiplexer ),
548 mrEventQueue( rEventQueue ),
549 mrCursorManager( rCursorManager ),
550 mpAnimationStartEventHandler(),
551 mpAnimationEndEventHandler(),
552 mpAudioStoppedEventHandler(),
553 mpClickEventHandler(),
554 mpSkipEffectEventHandler(),
555 mpDoubleClickEventHandler(),
556 mpMouseEnterHandler(),
557 mpMouseLeaveHandler(),
558 mbAdvanceOnClick( true )
562 UserEventQueue::~UserEventQueue()
566 // unregister all handlers
567 clear();
569 catch (uno::Exception &) {
570 OSL_FAIL( OUStringToOString(
571 comphelper::anyToString(
572 cppu::getCaughtException() ),
573 RTL_TEXTENCODING_UTF8 ).getStr() );
577 void UserEventQueue::clear()
579 // unregister and delete all handlers
580 if( mpAnimationStartEventHandler ) {
581 mrMultiplexer.removeAnimationStartHandler(
582 mpAnimationStartEventHandler );
583 mpAnimationStartEventHandler.reset();
585 if( mpAnimationEndEventHandler ) {
586 mrMultiplexer.removeAnimationEndHandler( mpAnimationEndEventHandler );
587 mpAnimationEndEventHandler.reset();
589 if( mpAudioStoppedEventHandler ) {
590 mrMultiplexer.removeAudioStoppedHandler( mpAudioStoppedEventHandler );
591 mpAudioStoppedEventHandler.reset();
593 if( mpShapeClickEventHandler ) {
594 mrMultiplexer.removeClickHandler( mpShapeClickEventHandler );
595 mrMultiplexer.removeMouseMoveHandler( mpShapeClickEventHandler );
596 mpShapeClickEventHandler.reset();
598 if( mpClickEventHandler ) {
599 mrMultiplexer.removeClickHandler( mpClickEventHandler );
600 mrMultiplexer.removeNextEffectHandler( mpClickEventHandler );
601 mpClickEventHandler.reset();
603 if(mpSkipEffectEventHandler) {
604 mrMultiplexer.removeClickHandler( mpSkipEffectEventHandler );
605 mrMultiplexer.removeNextEffectHandler( mpSkipEffectEventHandler );
606 mpSkipEffectEventHandler.reset();
608 if( mpShapeDoubleClickEventHandler ) {
609 mrMultiplexer.removeDoubleClickHandler( mpShapeDoubleClickEventHandler );
610 mrMultiplexer.removeMouseMoveHandler( mpShapeDoubleClickEventHandler );
611 mpShapeDoubleClickEventHandler.reset();
613 if( mpDoubleClickEventHandler ) {
614 mrMultiplexer.removeDoubleClickHandler( mpDoubleClickEventHandler );
615 mpDoubleClickEventHandler.reset();
617 if( mpMouseEnterHandler ) {
618 mrMultiplexer.removeMouseMoveHandler( mpMouseEnterHandler );
619 mpMouseEnterHandler.reset();
621 if( mpMouseLeaveHandler ) {
622 mrMultiplexer.removeMouseMoveHandler( mpMouseLeaveHandler );
623 mpMouseLeaveHandler.reset();
627 void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick )
629 mbAdvanceOnClick = bAdvanceOnClick;
631 // forward to handler, if existing. Otherwise, the handler
632 // creation will do the forwarding.
633 if( mpClickEventHandler )
634 mpClickEventHandler->setAdvanceOnClick( bAdvanceOnClick );
637 void UserEventQueue::registerAnimationStartEvent(
638 const EventSharedPtr& rEvent,
639 const uno::Reference< animations::XAnimationNode>& xNode )
641 registerEvent( mpAnimationStartEventHandler,
642 rEvent,
643 xNode,
644 boost::bind( &EventMultiplexer::addAnimationStartHandler,
645 boost::ref( mrMultiplexer ), _1 ) );
648 void UserEventQueue::registerAnimationEndEvent(
649 const EventSharedPtr& rEvent,
650 const uno::Reference<animations::XAnimationNode>& xNode )
652 registerEvent( mpAnimationEndEventHandler,
653 rEvent,
654 xNode,
655 boost::bind( &EventMultiplexer::addAnimationEndHandler,
656 boost::ref( mrMultiplexer ), _1 ) );
659 void UserEventQueue::registerAudioStoppedEvent(
660 const EventSharedPtr& rEvent,
661 const uno::Reference<animations::XAnimationNode>& xNode )
663 registerEvent( mpAudioStoppedEventHandler,
664 rEvent,
665 xNode,
666 boost::bind( &EventMultiplexer::addAudioStoppedHandler,
667 boost::ref( mrMultiplexer ), _1 ) );
670 void UserEventQueue::registerShapeClickEvent( const EventSharedPtr& rEvent,
671 const ShapeSharedPtr& rShape )
673 ENSURE_OR_THROW(
674 rEvent,
675 "UserEventQueue::registerShapeClickEvent(): Invalid event" );
677 if( !mpShapeClickEventHandler )
679 // create handler
680 mpShapeClickEventHandler.reset(
681 new ShapeClickEventHandler(mrCursorManager,
682 mrEventQueue) );
684 // register handler on EventMultiplexer
685 mrMultiplexer.addClickHandler( mpShapeClickEventHandler, 1.0 );
686 mrMultiplexer.addMouseMoveHandler( mpShapeClickEventHandler, 1.0 );
689 mpShapeClickEventHandler->addEvent( rEvent, rShape );
692 namespace {
693 class ClickEventRegistrationFunctor
695 public:
696 ClickEventRegistrationFunctor( EventMultiplexer& rMultiplexer,
697 double nPrio,
698 bool bAdvanceOnClick )
699 : mrMultiplexer( rMultiplexer ),
700 mnPrio(nPrio),
701 mbAdvanceOnClick( bAdvanceOnClick ) {}
703 void operator()( const boost::shared_ptr<ClickEventHandler>& rHandler )const
705 // register the handler on _two_ sources: we want the
706 // nextEffect events, e.g. space bar, to trigger clicks, as well!
707 mrMultiplexer.addClickHandler( rHandler, mnPrio );
708 mrMultiplexer.addNextEffectHandler( rHandler, mnPrio );
710 // forward advance-on-click state to newly
711 // generated handler (that's the only reason why
712 // we're called here)
713 rHandler->setAdvanceOnClick( mbAdvanceOnClick );
716 private:
717 EventMultiplexer& mrMultiplexer;
718 double const mnPrio;
719 bool const mbAdvanceOnClick;
721 } // anon namespace
723 void UserEventQueue::registerNextEffectEvent( const EventSharedPtr& rEvent )
725 // TODO: better name may be mpNextEffectEventHandler? then we have
726 // next effect (=> waiting to be started)
727 // skip effect (skipping the currently running one)
728 // rewind effect (rewinding back running one and waiting (again)
729 // to be started)
730 registerEvent( mpClickEventHandler,
731 rEvent,
732 ClickEventRegistrationFunctor( mrMultiplexer,
733 0.0 /* default prio */,
734 mbAdvanceOnClick ) );
737 void UserEventQueue::registerSkipEffectEvent(
738 EventSharedPtr const & pEvent,
739 const bool bSkipTriggersNextEffect)
741 if(!mpSkipEffectEventHandler)
743 mpSkipEffectEventHandler.reset(
744 new SkipEffectEventHandler( mrEventQueue, mrMultiplexer ) );
745 // register the handler on _two_ sources: we want the
746 // nextEffect events, e.g. space bar, to trigger clicks, as well!
747 mrMultiplexer.addClickHandler( mpSkipEffectEventHandler,
748 -1.0 /* prio below default */ );
749 mrMultiplexer.addNextEffectHandler( mpSkipEffectEventHandler,
750 -1.0 /* prio below default */ );
751 // forward advance-on-click state to newly
752 // generated handler (that's the only reason why
753 // we're called here)
754 mpSkipEffectEventHandler->setAdvanceOnClick( mbAdvanceOnClick );
756 mpSkipEffectEventHandler->setSkipTriggersNextEffect(bSkipTriggersNextEffect);
757 mpSkipEffectEventHandler->addEvent( pEvent );
760 void UserEventQueue::registerShapeDoubleClickEvent(
761 const EventSharedPtr& rEvent,
762 const ShapeSharedPtr& rShape )
764 ENSURE_OR_THROW(
765 rEvent,
766 "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );
768 if( !mpShapeDoubleClickEventHandler )
770 // create handler
771 mpShapeDoubleClickEventHandler.reset(
772 new ShapeClickEventHandler(mrCursorManager,
773 mrEventQueue) );
775 // register handler on EventMultiplexer
776 mrMultiplexer.addDoubleClickHandler( mpShapeDoubleClickEventHandler,
777 1.0 );
778 mrMultiplexer.addMouseMoveHandler( mpShapeDoubleClickEventHandler,
779 1.0 );
782 mpShapeDoubleClickEventHandler->addEvent( rEvent, rShape );
785 void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr& rEvent,
786 const ShapeSharedPtr& rShape )
788 registerEvent( mpMouseEnterHandler,
789 rEvent,
790 rShape,
791 boost::bind( &EventMultiplexer::addMouseMoveHandler,
792 boost::ref( mrMultiplexer ), _1,
793 0.0 /* default prio */ ) );
796 void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr& rEvent,
797 const ShapeSharedPtr& rShape )
799 registerEvent( mpMouseLeaveHandler,
800 rEvent,
801 rShape,
802 boost::bind( &EventMultiplexer::addMouseMoveHandler,
803 boost::ref( mrMultiplexer ), _1,
804 0.0 /* default prio */ ) );
807 void UserEventQueue::callSkipEffectEventHandler()
809 ::boost::shared_ptr<SkipEffectEventHandler> pHandler (
810 ::boost::dynamic_pointer_cast<SkipEffectEventHandler>(mpSkipEffectEventHandler));
811 if (pHandler)
812 pHandler->skipEffect();
815 } // namespace internal
816 } // namespace presentation
818 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */