LCOV - code coverage report
Current view: top level - slideshow/source/engine - usereventqueue.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 19 265 7.2 %
Date: 2015-06-13 12:38:46 Functions: 5 75 6.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : 
      21             : // must be first
      22             : #include <canvas/debug.hxx>
      23             : #include <tools/diagnose_ex.h>
      24             : 
      25             : #include <comphelper/anytostring.hxx>
      26             : #include <cppuhelper/exc_hlp.hxx>
      27             : 
      28             : #include <com/sun/star/awt/SystemPointer.hpp>
      29             : #include <com/sun/star/awt/MouseButton.hpp>
      30             : #include <com/sun/star/awt/MouseEvent.hpp>
      31             : 
      32             : #include <boost/bind.hpp>
      33             : 
      34             : #include "delayevent.hxx"
      35             : #include "usereventqueue.hxx"
      36             : #include "cursormanager.hxx"
      37             : #include "slideshowexceptions.hxx"
      38             : 
      39             : #include <vector>
      40             : #include <queue>
      41             : #include <map>
      42             : #include <functional>
      43             : #include <algorithm>
      44             : 
      45             : 
      46             : using namespace com::sun::star;
      47             : 
      48             : /* Implementation of UserEventQueue class */
      49             : 
      50             : namespace slideshow {
      51             : namespace internal {
      52             : 
      53             : namespace {
      54             : 
      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;
      61             : 
      62             : // MouseEventHandler base class, not consuming any event:
      63           0 : class MouseEventHandler_ : public MouseEventHandler
      64             : {
      65             : public:
      66           0 :     virtual bool handleMousePressed( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false;}
      67           0 :     virtual bool handleMouseReleased( awt::MouseEvent const& /*e*/) SAL_OVERRIDE { return false;}
      68           0 :     virtual bool handleMouseEntered( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false;}
      69           0 :     virtual bool handleMouseExited( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false; }
      70           0 :     virtual bool handleMouseDragged( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false;}
      71           0 :     virtual bool handleMouseMoved( awt::MouseEvent const& /*e*/ ) SAL_OVERRIDE { return false; }
      72             : };
      73             : 
      74             : /** @return one event has been posted
      75             :  */
      76             : template <typename ContainerT>
      77           0 : bool fireSingleEvent( ContainerT & rQueue, EventQueue & rEventQueue )
      78             : {
      79             :     // post next event in given queue:
      80           0 :     while (! rQueue.empty())
      81             :     {
      82           0 :         EventSharedPtr const pEvent(rQueue.front());
      83           0 :         rQueue.pop();
      84             : 
      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           0 :         if(pEvent->isCharged())
      91           0 :             return rEventQueue.addEvent( pEvent );
      92             :     }
      93           0 :     return false; // no more (active) events in queue
      94             : }
      95             : 
      96             : /** @return at least one event has been posted
      97             :  */
      98             : template <typename ContainerT>
      99           0 : bool fireAllEvents( ContainerT & rQueue, EventQueue & rEventQueue )
     100             : {
     101           0 :     bool bFiredAny = false;
     102           0 :     while (fireSingleEvent( rQueue, rEventQueue ))
     103           0 :         bFiredAny = true;
     104           0 :     return bFiredAny;
     105             : }
     106             : 
     107           0 : class EventContainer
     108             : {
     109             : public:
     110           0 :     EventContainer() :
     111           0 :         maEvents()
     112           0 :     {}
     113             : 
     114           0 :     void addEvent( const EventSharedPtr& rEvent )
     115             :     {
     116           0 :         maEvents.push( rEvent );
     117           0 :     }
     118             : 
     119             : protected:
     120             :     ImpEventQueue maEvents;
     121             : };
     122             : 
     123             : } // anon namespace
     124             : 
     125           0 : class AllAnimationEventHandler : public AnimationEventHandler
     126             : {
     127             : public:
     128           0 :     AllAnimationEventHandler( EventQueue& rEventQueue ) :
     129             :         mrEventQueue( rEventQueue ),
     130           0 :         maAnimationEventMap()
     131           0 :     {}
     132             : 
     133           0 :     virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) SAL_OVERRIDE
     134             :     {
     135           0 :         ENSURE_OR_RETURN_FALSE(
     136             :             rNode,
     137             :             "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );
     138             : 
     139           0 :         bool bRet( false );
     140             : 
     141           0 :         ImpAnimationEventMap::iterator aIter;
     142           0 :         if( (aIter=maAnimationEventMap.find(
     143           0 :                  rNode->getXAnimationNode() )) != maAnimationEventMap.end() )
     144             :         {
     145           0 :             ImpEventVector& rVec( aIter->second );
     146             : 
     147           0 :             bRet = !rVec.empty();
     148             : 
     149             :             // registered node found -> fire all events in the vector
     150             :             std::for_each( rVec.begin(), rVec.end(),
     151             :                            boost::bind( &EventQueue::addEvent,
     152           0 :                                         boost::ref( mrEventQueue ), _1 ) );
     153             : 
     154           0 :             rVec.clear();
     155             :         }
     156             : 
     157           0 :         return bRet;
     158             :     }
     159             : 
     160           0 :     void addEvent( const EventSharedPtr&                                rEvent,
     161             :                    const uno::Reference< animations::XAnimationNode >&  xNode )
     162             :     {
     163           0 :         ImpAnimationEventMap::iterator aIter;
     164           0 :         if( (aIter=maAnimationEventMap.find( xNode )) ==
     165           0 :             maAnimationEventMap.end() )
     166             :         {
     167             :             // no entry for this animation -> create one
     168             :             aIter = maAnimationEventMap.insert(
     169             :                 ImpAnimationEventMap::value_type( xNode,
     170           0 :                                                   ImpEventVector() ) ).first;
     171             :         }
     172             : 
     173             :         // add new event to queue
     174           0 :         aIter->second.push_back( rEvent );
     175           0 :     }
     176             : 
     177             : private:
     178             :     EventQueue&             mrEventQueue;
     179             :     ImpAnimationEventMap    maAnimationEventMap;
     180             : };
     181             : 
     182           0 : class ClickEventHandler : public MouseEventHandler_,
     183             :                           public EventHandler,
     184             :                           public EventContainer
     185             : {
     186             : public:
     187           0 :     ClickEventHandler( EventQueue& rEventQueue ) :
     188             :         EventContainer(),
     189             :         mrEventQueue( rEventQueue ),
     190           0 :         mbAdvanceOnClick( true )
     191           0 :     {}
     192             : 
     193           0 :     void setAdvanceOnClick( bool bAdvanceOnClick )
     194             :     {
     195           0 :         mbAdvanceOnClick = bAdvanceOnClick;
     196           0 :     }
     197             : 
     198             : private:
     199             : 
     200             :     // triggered by API calls, e.g. space bar
     201           0 :     virtual bool handleEvent() SAL_OVERRIDE
     202             :     {
     203           0 :         return handleEvent_impl();
     204             :     }
     205             : 
     206             :     // triggered by mouse release:
     207           0 :     virtual bool handleMouseReleased( const awt::MouseEvent& evt ) SAL_OVERRIDE
     208             :     {
     209           0 :         if(evt.Buttons != awt::MouseButton::LEFT)
     210           0 :             return false;
     211             : 
     212           0 :         if( mbAdvanceOnClick ) {
     213             :             // fire next event
     214           0 :             return handleEvent_impl();
     215             :         }
     216             :         else {
     217           0 :             return false; // advance-on-click disabled
     218             :         }
     219             :     }
     220             : 
     221             :     // triggered by both:
     222           0 :     virtual bool handleEvent_impl()
     223             :     {
     224             :         // fire next event:
     225           0 :         return fireSingleEvent( maEvents, mrEventQueue );
     226             :     }
     227             : 
     228             : private:
     229             :     EventQueue& mrEventQueue;
     230             :     bool        mbAdvanceOnClick;
     231             : };
     232             : 
     233           0 : class SkipEffectEventHandler : public ClickEventHandler
     234             : {
     235             : public:
     236           0 :     SkipEffectEventHandler( EventQueue & rEventQueue,
     237             :                             EventMultiplexer & rEventMultiplexer )
     238             :         : ClickEventHandler(rEventQueue),
     239             :           mrEventQueue(rEventQueue),
     240             :           mrEventMultiplexer(rEventMultiplexer),
     241           0 :           mbSkipTriggersNextEffect(true) {}
     242             : 
     243             :     /** Remember to trigger (or not to trigger) the next effect after the
     244             :         current effect is skipped.
     245             :     */
     246           0 :     void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect)
     247           0 :     { mbSkipTriggersNextEffect = bSkipTriggersNextEffect; }
     248             : 
     249             :     ///  Skip the current effect but do not trigger the next effect.
     250           0 :     void skipEffect() { handleEvent_impl(false); }
     251             : 
     252             : private:
     253           0 :     virtual bool handleEvent_impl() SAL_OVERRIDE
     254             :     {
     255           0 :         return handleEvent_impl(true);
     256             :     }
     257             : 
     258           0 :     bool handleEvent_impl (bool bNotifyNextEffect)
     259             :     {
     260             :         // fire all events, so animation nodes can register their
     261             :         // next effect listeners:
     262           0 :         if(fireAllEvents( maEvents, mrEventQueue ))
     263             :         {
     264           0 :             if (mbSkipTriggersNextEffect && bNotifyNextEffect)
     265             :             {
     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           0 :                     makeEvent( boost::bind( &EventMultiplexer::notifyNextEffect,
     274             :                                             boost::ref(mrEventMultiplexer) ),
     275           0 :                                "EventMultiplexer::notifyNextEffect") );
     276             :             }
     277             :             else
     278           0 :                 return true;
     279             :         }
     280           0 :         return false;
     281             :     }
     282             : 
     283             : private:
     284             :     EventQueue & mrEventQueue;
     285             :     EventMultiplexer & mrEventMultiplexer;
     286             :     bool mbSkipTriggersNextEffect;
     287             : };
     288             : 
     289             : /** Base class to share some common code between
     290             :     ShapeClickEventHandler and MouseMoveHandler
     291             : 
     292             :     @derive override necessary MouseEventHandler interface methods,
     293             :     call sendEvent() method to actually process the event.
     294             : */
     295           0 : class MouseHandlerBase : public MouseEventHandler_
     296             : {
     297             : public:
     298           0 :     MouseHandlerBase( EventQueue& rEventQueue ) :
     299             :         mrEventQueue( rEventQueue ),
     300           0 :         maShapeEventMap()
     301           0 :     {}
     302             : 
     303           0 :     void addEvent( const EventSharedPtr& rEvent,
     304             :                    const ShapeSharedPtr& rShape )
     305             :     {
     306           0 :         ImpShapeEventMap::iterator aIter;
     307           0 :         if( (aIter=maShapeEventMap.find( rShape )) == maShapeEventMap.end() )
     308             :         {
     309             :             // no entry for this shape -> create one
     310             :             aIter = maShapeEventMap.insert(
     311             :                 ImpShapeEventMap::value_type( rShape,
     312           0 :                                               ImpEventQueue() ) ).first;
     313             :         }
     314             : 
     315             :         // add new event to queue
     316           0 :         aIter->second.push( rEvent );
     317           0 :     }
     318             : 
     319             : protected:
     320           0 :     bool hitTest( const awt::MouseEvent&                e,
     321             :                   ImpShapeEventMap::reverse_iterator&   o_rHitShape )
     322             :     {
     323             :         // find hit shape in map
     324           0 :         const basegfx::B2DPoint aPosition( e.X, e.Y );
     325             : 
     326             :         // find matching shape (scan reversely, to coarsely match
     327             :         // paint order)
     328           0 :         ImpShapeEventMap::reverse_iterator       aCurrShape(maShapeEventMap.rbegin());
     329           0 :         const ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.rend() );
     330           0 :         while( aCurrShape != aEndShape )
     331             :         {
     332             :             // TODO(F2): Get proper geometry polygon from the
     333             :             // shape, to avoid having areas outside the shape
     334             :             // react on the mouse
     335           0 :             if( aCurrShape->first->getBounds().isInside( aPosition ) &&
     336           0 :                 aCurrShape->first->isVisible() )
     337             :             {
     338             :                 // shape hit, and shape is visible - report a
     339             :                 // hit
     340           0 :                 o_rHitShape = aCurrShape;
     341           0 :                 return true;
     342             :             }
     343             : 
     344           0 :             ++aCurrShape;
     345             :         }
     346             : 
     347           0 :         return false; // nothing hit
     348             :     }
     349             : 
     350           0 :     bool sendEvent( ImpShapeEventMap::reverse_iterator& io_rHitShape )
     351             :     {
     352             :         // take next event from queue
     353           0 :         const bool bRet( fireSingleEvent( io_rHitShape->second,
     354           0 :                                           mrEventQueue ) );
     355             : 
     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           0 :         if( io_rHitShape->second.empty() )
     362             :         {
     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           0 :             maShapeEventMap.erase( io_rHitShape->first );
     370             :         }
     371             : 
     372           0 :         return bRet;
     373             :     }
     374             : 
     375           0 :     bool processEvent( const awt::MouseEvent& e )
     376             :     {
     377           0 :         ImpShapeEventMap::reverse_iterator aCurrShape;
     378             : 
     379           0 :         if( hitTest( e, aCurrShape ) )
     380           0 :             return sendEvent( aCurrShape );
     381             : 
     382           0 :         return false; // did not handle the event
     383             :     }
     384             : 
     385             : private:
     386             :     EventQueue&         mrEventQueue;
     387             :     ImpShapeEventMap    maShapeEventMap;
     388             : };
     389             : 
     390           0 : class ShapeClickEventHandler : public MouseHandlerBase
     391             : {
     392             : public:
     393           0 :     ShapeClickEventHandler( CursorManager& rCursorManager,
     394             :                             EventQueue&    rEventQueue ) :
     395             :         MouseHandlerBase( rEventQueue ),
     396           0 :         mrCursorManager( rCursorManager )
     397           0 :     {}
     398             : 
     399           0 :     virtual bool handleMouseReleased( const awt::MouseEvent& e ) SAL_OVERRIDE
     400             :     {
     401           0 :         if(e.Buttons != awt::MouseButton::LEFT)
     402           0 :             return false;
     403           0 :         return processEvent( e );
     404             :     }
     405             : 
     406           0 :     virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
     407             :     {
     408             :         // TODO(P2): Maybe buffer last shape touched
     409             : 
     410             :         // if we have a shape click event, and the mouse
     411             :         // hovers over this shape, change cursor to hand
     412           0 :         ImpShapeEventMap::reverse_iterator aDummy;
     413           0 :         if( hitTest( e, aDummy ) )
     414           0 :             mrCursorManager.requestCursor( awt::SystemPointer::REFHAND );
     415             : 
     416           0 :         return false; // we don't /eat/ this event. Lower prio
     417             :         // handler should see it, too.
     418             :     }
     419             : 
     420             : private:
     421             :     CursorManager& mrCursorManager;
     422             : };
     423             : 
     424           0 : class MouseEnterHandler : public MouseHandlerBase
     425             : {
     426             : public:
     427           0 :     MouseEnterHandler( EventQueue& rEventQueue )
     428             :         : MouseHandlerBase( rEventQueue ),
     429           0 :           mpLastShape() {}
     430             : 
     431           0 :     virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
     432             :     {
     433             :         // TODO(P2): Maybe buffer last shape touched, and
     434             :         // check against that _first_
     435             : 
     436           0 :         ImpShapeEventMap::reverse_iterator aCurr;
     437           0 :         if( hitTest( e, aCurr ) )
     438             :         {
     439           0 :             if( aCurr->first != mpLastShape )
     440             :             {
     441             :                 // we actually hit a shape, and it's different
     442             :                 // from the previous one - thus we just
     443             :                 // entered it, raise event
     444           0 :                 sendEvent( aCurr );
     445           0 :                 mpLastShape = aCurr->first;
     446             :             }
     447             :         }
     448             :         else
     449             :         {
     450             :             // don't hit no shape - thus, last shape is NULL
     451           0 :             mpLastShape.reset();
     452             :         }
     453             : 
     454           0 :         return false; // we don't /eat/ this event. Lower prio
     455             :         // handler should see it, too.
     456             :     }
     457             : 
     458             : private:
     459             :     ShapeSharedPtr mpLastShape;
     460             : };
     461             : 
     462           0 : class MouseLeaveHandler : public MouseHandlerBase
     463             : {
     464             : public:
     465           0 :     MouseLeaveHandler( EventQueue& rEventQueue )
     466             :         : MouseHandlerBase( rEventQueue ),
     467           0 :           maLastIter() {}
     468             : 
     469           0 :     virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
     470             :     {
     471             :         // TODO(P2): Maybe buffer last shape touched, and
     472             :         // check against that _first_
     473             : 
     474           0 :         ImpShapeEventMap::reverse_iterator aCurr;
     475           0 :         if( hitTest( e, aCurr ) )
     476             :         {
     477           0 :             maLastIter = aCurr;
     478             :         }
     479             :         else
     480             :         {
     481           0 :             if( maLastIter->first )
     482             :             {
     483             :                 // last time, we were over a shape, now we're
     484             :                 // not - we thus just left that shape, raise
     485             :                 // event
     486           0 :                 sendEvent( maLastIter );
     487             :             }
     488             : 
     489             :             // in any case, when we hit this else-branch: no
     490             :             // shape hit, thus have to clear maLastIter
     491           0 :             maLastIter = ImpShapeEventMap::reverse_iterator();
     492             :         }
     493             : 
     494           0 :         return false; // we don't /eat/ this event. Lower prio
     495             :         // handler should see it, too.
     496             :     }
     497             : 
     498             : private:
     499             :     ImpShapeEventMap::reverse_iterator maLastIter;
     500             : };
     501             : 
     502             : template< typename Handler, typename Functor >
     503           0 : void UserEventQueue::registerEvent(
     504             :     boost::shared_ptr< Handler >& rHandler,
     505             :     const EventSharedPtr&         rEvent,
     506             :     const Functor&                rRegistrationFunctor )
     507             : {
     508           0 :     ENSURE_OR_THROW( rEvent,
     509             :                       "UserEventQueue::registerEvent(): Invalid event" );
     510             : 
     511           0 :     if( !rHandler ) {
     512             :         // create handler
     513           0 :         rHandler.reset( new Handler( mrEventQueue ) );
     514             :         // register handler on EventMultiplexer
     515           0 :         rRegistrationFunctor( rHandler );
     516             :     }
     517             : 
     518           0 :     rHandler->addEvent( rEvent );
     519           0 : }
     520             : 
     521             : template< typename Handler, typename Arg, typename Functor >
     522           0 : void UserEventQueue::registerEvent(
     523             :     boost::shared_ptr< Handler >& rHandler,
     524             :     const EventSharedPtr&         rEvent,
     525             :     const Arg&                    rArg,
     526             :     const Functor&                rRegistrationFunctor )
     527             : {
     528           0 :     ENSURE_OR_THROW( rEvent,
     529             :                       "UserEventQueue::registerEvent(): Invalid event" );
     530             : 
     531           0 :     if( !rHandler ) {
     532             :         // create handler
     533           0 :         rHandler.reset( new Handler( mrEventQueue ) );
     534             : 
     535             :         // register handler on EventMultiplexer
     536           0 :         rRegistrationFunctor( rHandler );
     537             :     }
     538             : 
     539           0 :     rHandler->addEvent( rEvent, rArg );
     540           0 : }
     541             : 
     542             : 
     543             : 
     544           1 : 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           1 :       mbAdvanceOnClick( true )
     559             : {
     560           1 : }
     561             : 
     562           2 : UserEventQueue::~UserEventQueue()
     563             : {
     564             :     try
     565             :     {
     566             :         // unregister all handlers
     567           1 :         clear();
     568             :     }
     569           0 :     catch (uno::Exception &) {
     570             :         OSL_FAIL( OUStringToOString(
     571             :                         comphelper::anyToString(
     572             :                             cppu::getCaughtException() ),
     573             :                         RTL_TEXTENCODING_UTF8 ).getStr() );
     574             :     }
     575           1 : }
     576             : 
     577           2 : void UserEventQueue::clear()
     578             : {
     579             :     // unregister and delete all handlers
     580           2 :     if( mpAnimationStartEventHandler ) {
     581             :         mrMultiplexer.removeAnimationStartHandler(
     582           0 :             mpAnimationStartEventHandler );
     583           0 :         mpAnimationStartEventHandler.reset();
     584             :     }
     585           2 :     if( mpAnimationEndEventHandler ) {
     586           0 :         mrMultiplexer.removeAnimationEndHandler( mpAnimationEndEventHandler );
     587           0 :         mpAnimationEndEventHandler.reset();
     588             :     }
     589           2 :     if( mpAudioStoppedEventHandler ) {
     590           0 :         mrMultiplexer.removeAudioStoppedHandler( mpAudioStoppedEventHandler );
     591           0 :         mpAudioStoppedEventHandler.reset();
     592             :     }
     593           2 :     if( mpShapeClickEventHandler ) {
     594           0 :         mrMultiplexer.removeClickHandler( mpShapeClickEventHandler );
     595           0 :         mrMultiplexer.removeMouseMoveHandler( mpShapeClickEventHandler );
     596           0 :         mpShapeClickEventHandler.reset();
     597             :     }
     598           2 :     if( mpClickEventHandler ) {
     599           0 :         mrMultiplexer.removeClickHandler( mpClickEventHandler );
     600           0 :         mrMultiplexer.removeNextEffectHandler( mpClickEventHandler );
     601           0 :         mpClickEventHandler.reset();
     602             :     }
     603           2 :     if(mpSkipEffectEventHandler) {
     604           0 :         mrMultiplexer.removeClickHandler( mpSkipEffectEventHandler );
     605           0 :         mrMultiplexer.removeNextEffectHandler( mpSkipEffectEventHandler );
     606           0 :         mpSkipEffectEventHandler.reset();
     607             :     }
     608           2 :     if( mpShapeDoubleClickEventHandler ) {
     609           0 :         mrMultiplexer.removeDoubleClickHandler( mpShapeDoubleClickEventHandler );
     610           0 :         mrMultiplexer.removeMouseMoveHandler( mpShapeDoubleClickEventHandler );
     611           0 :         mpShapeDoubleClickEventHandler.reset();
     612             :     }
     613           2 :     if( mpDoubleClickEventHandler ) {
     614           0 :         mrMultiplexer.removeDoubleClickHandler( mpDoubleClickEventHandler );
     615           0 :         mpDoubleClickEventHandler.reset();
     616             :     }
     617           2 :     if( mpMouseEnterHandler ) {
     618           0 :         mrMultiplexer.removeMouseMoveHandler( mpMouseEnterHandler );
     619           0 :         mpMouseEnterHandler.reset();
     620             :     }
     621           2 :     if( mpMouseLeaveHandler ) {
     622           0 :         mrMultiplexer.removeMouseMoveHandler( mpMouseLeaveHandler );
     623           0 :         mpMouseLeaveHandler.reset();
     624             :     }
     625           2 : }
     626             : 
     627           0 : void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick )
     628             : {
     629           0 :     mbAdvanceOnClick = bAdvanceOnClick;
     630             : 
     631             :     // forward to handler, if existing. Otherwise, the handler
     632             :     // creation will do the forwarding.
     633           0 :     if( mpClickEventHandler )
     634           0 :         mpClickEventHandler->setAdvanceOnClick( bAdvanceOnClick );
     635           0 : }
     636             : 
     637           0 : void UserEventQueue::registerAnimationStartEvent(
     638             :     const EventSharedPtr&                                 rEvent,
     639             :     const uno::Reference< animations::XAnimationNode>&    xNode )
     640             : {
     641             :     registerEvent( mpAnimationStartEventHandler,
     642             :                    rEvent,
     643             :                    xNode,
     644             :                    boost::bind( &EventMultiplexer::addAnimationStartHandler,
     645           0 :                                 boost::ref( mrMultiplexer ), _1 ) );
     646           0 : }
     647             : 
     648           0 : void UserEventQueue::registerAnimationEndEvent(
     649             :     const EventSharedPtr&                               rEvent,
     650             :     const uno::Reference<animations::XAnimationNode>&   xNode )
     651             : {
     652             :     registerEvent( mpAnimationEndEventHandler,
     653             :                    rEvent,
     654             :                    xNode,
     655             :                    boost::bind( &EventMultiplexer::addAnimationEndHandler,
     656           0 :                                 boost::ref( mrMultiplexer ), _1 ) );
     657           0 : }
     658             : 
     659           0 : void UserEventQueue::registerAudioStoppedEvent(
     660             :     const EventSharedPtr&                               rEvent,
     661             :     const uno::Reference<animations::XAnimationNode>&   xNode )
     662             : {
     663             :     registerEvent( mpAudioStoppedEventHandler,
     664             :                    rEvent,
     665             :                    xNode,
     666             :                    boost::bind( &EventMultiplexer::addAudioStoppedHandler,
     667           0 :                                 boost::ref( mrMultiplexer ), _1 ) );
     668           0 : }
     669             : 
     670           0 : void UserEventQueue::registerShapeClickEvent( const EventSharedPtr& rEvent,
     671             :                                               const ShapeSharedPtr& rShape )
     672             : {
     673           0 :     ENSURE_OR_THROW(
     674             :         rEvent,
     675             :         "UserEventQueue::registerShapeClickEvent(): Invalid event" );
     676             : 
     677           0 :     if( !mpShapeClickEventHandler )
     678             :     {
     679             :         // create handler
     680             :         mpShapeClickEventHandler.reset(
     681             :             new ShapeClickEventHandler(mrCursorManager,
     682           0 :                                        mrEventQueue) );
     683             : 
     684             :         // register handler on EventMultiplexer
     685           0 :         mrMultiplexer.addClickHandler( mpShapeClickEventHandler, 1.0 );
     686           0 :         mrMultiplexer.addMouseMoveHandler( mpShapeClickEventHandler, 1.0 );
     687             :     }
     688             : 
     689           0 :     mpShapeClickEventHandler->addEvent( rEvent, rShape );
     690           0 : }
     691             : 
     692             : namespace {
     693             : class ClickEventRegistrationFunctor
     694             : {
     695             : public:
     696           0 :     ClickEventRegistrationFunctor( EventMultiplexer& rMultiplexer,
     697             :                                    double            nPrio,
     698             :                                    bool              bAdvanceOnClick )
     699             :         : mrMultiplexer( rMultiplexer ),
     700             :           mnPrio(nPrio),
     701           0 :           mbAdvanceOnClick( bAdvanceOnClick ) {}
     702             : 
     703           0 :     void operator()( const boost::shared_ptr<ClickEventHandler>& rHandler )const
     704             :     {
     705             :         // register the handler on _two_ sources: we want the
     706             :         // nextEffect events, e.g. space bar, to trigger clicks, as well!
     707           0 :         mrMultiplexer.addClickHandler( rHandler, mnPrio );
     708           0 :         mrMultiplexer.addNextEffectHandler( rHandler, mnPrio );
     709             : 
     710             :         // forward advance-on-click state to newly
     711             :         // generated handler (that's the only reason why
     712             :         // we're called here)
     713           0 :         rHandler->setAdvanceOnClick( mbAdvanceOnClick );
     714           0 :     }
     715             : 
     716             : private:
     717             :     EventMultiplexer&   mrMultiplexer;
     718             :     double const        mnPrio;
     719             :     bool const          mbAdvanceOnClick;
     720             : };
     721             : } // anon namespace
     722             : 
     723           0 : void UserEventQueue::registerNextEffectEvent( const EventSharedPtr& rEvent )
     724             : {
     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           0 :                                                   mbAdvanceOnClick ) );
     735           0 : }
     736             : 
     737           0 : void UserEventQueue::registerSkipEffectEvent(
     738             :     EventSharedPtr const & pEvent,
     739             :     const bool bSkipTriggersNextEffect)
     740             : {
     741           0 :     if(!mpSkipEffectEventHandler)
     742             :     {
     743             :         mpSkipEffectEventHandler.reset(
     744           0 :             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           0 :                                        -1.0 /* prio below default */ );
     749             :         mrMultiplexer.addNextEffectHandler( mpSkipEffectEventHandler,
     750           0 :                                             -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           0 :         mpSkipEffectEventHandler->setAdvanceOnClick( mbAdvanceOnClick );
     755             :     }
     756           0 :     mpSkipEffectEventHandler->setSkipTriggersNextEffect(bSkipTriggersNextEffect);
     757           0 :     mpSkipEffectEventHandler->addEvent( pEvent );
     758           0 : }
     759             : 
     760           0 : void UserEventQueue::registerShapeDoubleClickEvent(
     761             :     const EventSharedPtr& rEvent,
     762             :     const ShapeSharedPtr& rShape )
     763             : {
     764           0 :     ENSURE_OR_THROW(
     765             :         rEvent,
     766             :         "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );
     767             : 
     768           0 :     if( !mpShapeDoubleClickEventHandler )
     769             :     {
     770             :         // create handler
     771             :         mpShapeDoubleClickEventHandler.reset(
     772             :             new ShapeClickEventHandler(mrCursorManager,
     773           0 :                                        mrEventQueue) );
     774             : 
     775             :         // register handler on EventMultiplexer
     776             :         mrMultiplexer.addDoubleClickHandler( mpShapeDoubleClickEventHandler,
     777           0 :                                              1.0 );
     778             :         mrMultiplexer.addMouseMoveHandler( mpShapeDoubleClickEventHandler,
     779           0 :                                            1.0 );
     780             :     }
     781             : 
     782           0 :     mpShapeDoubleClickEventHandler->addEvent( rEvent, rShape );
     783           0 : }
     784             : 
     785           0 : void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr& rEvent,
     786             :                                               const ShapeSharedPtr& rShape )
     787             : {
     788             :     registerEvent( mpMouseEnterHandler,
     789             :                    rEvent,
     790             :                    rShape,
     791             :                    boost::bind( &EventMultiplexer::addMouseMoveHandler,
     792             :                                 boost::ref( mrMultiplexer ), _1,
     793           0 :                                 0.0 /* default prio */ ) );
     794           0 : }
     795             : 
     796           0 : void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr& rEvent,
     797             :                                               const ShapeSharedPtr& rShape )
     798             : {
     799             :     registerEvent( mpMouseLeaveHandler,
     800             :                    rEvent,
     801             :                    rShape,
     802             :                    boost::bind( &EventMultiplexer::addMouseMoveHandler,
     803             :                                 boost::ref( mrMultiplexer ), _1,
     804           0 :                                 0.0 /* default prio */ ) );
     805           0 : }
     806             : 
     807           0 : void UserEventQueue::callSkipEffectEventHandler()
     808             : {
     809             :     ::boost::shared_ptr<SkipEffectEventHandler> pHandler (
     810           0 :         ::boost::dynamic_pointer_cast<SkipEffectEventHandler>(mpSkipEffectEventHandler));
     811           0 :     if (pHandler)
     812           0 :         pHandler->skipEffect();
     813           0 : }
     814             : 
     815             : } // namespace internal
     816           3 : } // namespace presentation
     817             : 
     818             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11