LCOV - code coverage report
Current view: top level - slideshow/source/engine - usereventqueue.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 299 0.0 %
Date: 2014-04-14 Functions: 0 86 0.0 %
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 clearContainer()
     115             :     {
     116           0 :         maEvents = ImpEventQueue();
     117           0 :     }
     118             : 
     119           0 :     void addEvent( const EventSharedPtr& rEvent )
     120             :     {
     121           0 :         maEvents.push( rEvent );
     122           0 :     }
     123             : 
     124             : protected:
     125             :     ImpEventQueue maEvents;
     126             : };
     127             : 
     128             : } // anon namespace
     129             : 
     130             : class PlainEventHandler : public EventHandler,
     131             :                           public EventContainer
     132             : {
     133             : public:
     134             :     PlainEventHandler( EventQueue & rEventQueue )
     135             :         : EventContainer(), mrEventQueue(rEventQueue) {}
     136             : 
     137             :     virtual void dispose()
     138             :     {
     139             :         clearContainer();
     140             :     }
     141             : 
     142             :     virtual bool handleEvent() SAL_OVERRIDE
     143             :     {
     144             :         return fireAllEvents( maEvents, mrEventQueue );
     145             :     }
     146             : 
     147             : private:
     148             :     EventQueue & mrEventQueue;
     149             : };
     150             : 
     151           0 : class AllAnimationEventHandler : public AnimationEventHandler
     152             : {
     153             : public:
     154           0 :     AllAnimationEventHandler( EventQueue& rEventQueue ) :
     155             :         mrEventQueue( rEventQueue ),
     156           0 :         maAnimationEventMap()
     157           0 :     {}
     158             : 
     159           0 :     virtual void dispose()
     160             :     {
     161           0 :         maAnimationEventMap.clear();
     162           0 :     }
     163             : 
     164           0 :     virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) SAL_OVERRIDE
     165             :     {
     166           0 :         ENSURE_OR_RETURN_FALSE(
     167             :             rNode,
     168             :             "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" );
     169             : 
     170           0 :         bool bRet( false );
     171             : 
     172           0 :         ImpAnimationEventMap::iterator aIter;
     173           0 :         if( (aIter=maAnimationEventMap.find(
     174           0 :                  rNode->getXAnimationNode() )) != maAnimationEventMap.end() )
     175             :         {
     176           0 :             ImpEventVector& rVec( aIter->second );
     177             : 
     178           0 :             bRet = !rVec.empty();
     179             : 
     180             :             // registered node found -> fire all events in the vector
     181             :             std::for_each( rVec.begin(), rVec.end(),
     182             :                            boost::bind( &EventQueue::addEvent,
     183           0 :                                         boost::ref( mrEventQueue ), _1 ) );
     184             : 
     185           0 :             rVec.clear();
     186             :         }
     187             : 
     188           0 :         return bRet;
     189             :     }
     190             : 
     191           0 :     void addEvent( const EventSharedPtr&                                rEvent,
     192             :                    const uno::Reference< animations::XAnimationNode >&  xNode )
     193             :     {
     194           0 :         ImpAnimationEventMap::iterator aIter;
     195           0 :         if( (aIter=maAnimationEventMap.find( xNode )) ==
     196           0 :             maAnimationEventMap.end() )
     197             :         {
     198             :             // no entry for this animation -> create one
     199             :             aIter = maAnimationEventMap.insert(
     200             :                 ImpAnimationEventMap::value_type( xNode,
     201           0 :                                                   ImpEventVector() ) ).first;
     202             :         }
     203             : 
     204             :         // add new event to queue
     205           0 :         aIter->second.push_back( rEvent );
     206           0 :     }
     207             : 
     208             :     bool isEmpty()
     209             :     {
     210             :         // find at least one animation with a non-empty vector
     211             :         ImpAnimationEventMap::const_iterator aCurr( maAnimationEventMap.begin() );
     212             :         const ImpAnimationEventMap::const_iterator aEnd( maAnimationEventMap.end() );
     213             :         while( aCurr != aEnd )
     214             :         {
     215             :             if( !aCurr->second.empty() )
     216             :                 return false; // at least one non-empty entry found
     217             : 
     218             :             ++aCurr;
     219             :         }
     220             : 
     221             :         return true; // not a single non-empty entry found
     222             :     }
     223             : 
     224             : private:
     225             :     EventQueue&             mrEventQueue;
     226             :     ImpAnimationEventMap    maAnimationEventMap;
     227             : };
     228             : 
     229           0 : class ClickEventHandler : public MouseEventHandler_,
     230             :                           public EventHandler,
     231             :                           public EventContainer
     232             : {
     233             : public:
     234           0 :     ClickEventHandler( EventQueue& rEventQueue ) :
     235             :         EventContainer(),
     236             :         mrEventQueue( rEventQueue ),
     237           0 :         mbAdvanceOnClick( true )
     238           0 :     {}
     239             : 
     240           0 :     void setAdvanceOnClick( bool bAdvanceOnClick )
     241             :     {
     242           0 :         mbAdvanceOnClick = bAdvanceOnClick;
     243           0 :     }
     244             : 
     245             : private:
     246           0 :     virtual void dispose()
     247             :     {
     248           0 :         clearContainer();
     249           0 :     }
     250             : 
     251             :     // triggered by API calls, e.g. space bar
     252           0 :     virtual bool handleEvent() SAL_OVERRIDE
     253             :     {
     254           0 :         return handleEvent_impl();
     255             :     }
     256             : 
     257             :     // triggered by mouse release:
     258           0 :     virtual bool handleMouseReleased( const awt::MouseEvent& evt ) SAL_OVERRIDE
     259             :     {
     260           0 :         if(evt.Buttons != awt::MouseButton::LEFT)
     261           0 :             return false;
     262             : 
     263           0 :         if( mbAdvanceOnClick ) {
     264             :             // fire next event
     265           0 :             return handleEvent_impl();
     266             :         }
     267             :         else {
     268           0 :             return false; // advance-on-click disabled
     269             :         }
     270             :     }
     271             : 
     272             :     // triggered by both:
     273           0 :     virtual bool handleEvent_impl()
     274             :     {
     275             :         // fire next event:
     276           0 :         return fireSingleEvent( maEvents, mrEventQueue );
     277             :     }
     278             : 
     279             : private:
     280             :     EventQueue& mrEventQueue;
     281             :     bool        mbAdvanceOnClick;
     282             : };
     283             : 
     284           0 : class SkipEffectEventHandler : public ClickEventHandler
     285             : {
     286             : public:
     287           0 :     SkipEffectEventHandler( EventQueue & rEventQueue,
     288             :                             EventMultiplexer & rEventMultiplexer )
     289             :         : ClickEventHandler(rEventQueue),
     290             :           mrEventQueue(rEventQueue),
     291             :           mrEventMultiplexer(rEventMultiplexer),
     292           0 :           mbSkipTriggersNextEffect(true) {}
     293             : 
     294             :     /** Remember to trigger (or not to trigger) the next effect after the
     295             :         current effect is skiped.
     296             :     */
     297           0 :     void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect)
     298           0 :     { mbSkipTriggersNextEffect = bSkipTriggersNextEffect; }
     299             : 
     300             :     ///  Skip the current effect but do not triggere the next effect.
     301           0 :     void skipEffect (void) { handleEvent_impl(false); }
     302             : 
     303             : private:
     304           0 :     virtual bool handleEvent_impl() SAL_OVERRIDE
     305             :     {
     306           0 :         return handleEvent_impl(true);
     307             :     }
     308             : 
     309           0 :     bool handleEvent_impl (bool bNotifyNextEffect)
     310             :     {
     311             :         // fire all events, so animation nodes can register their
     312             :         // next effect listeners:
     313           0 :         if(fireAllEvents( maEvents, mrEventQueue ))
     314             :         {
     315           0 :             if (mbSkipTriggersNextEffect && bNotifyNextEffect)
     316             :             {
     317             :                 // then simulate a next effect event: this skip effect
     318             :                 // handler is triggered upon next effect events (multiplexer
     319             :                 // prio=-1)!  Posting a notifyNextEffect() here is only safe
     320             :                 // (we don't run into busy loop), because we assume that
     321             :                 // someone has registerered above for next effects
     322             :                 // (multiplexer prio=0) at the user event queue.
     323             :                 return mrEventQueue.addEventWhenQueueIsEmpty(
     324           0 :                     makeEvent( boost::bind( &EventMultiplexer::notifyNextEffect,
     325             :                                             boost::ref(mrEventMultiplexer) ),
     326           0 :                                "EventMultiplexer::notifyNextEffect") );
     327             :             }
     328             :             else
     329           0 :                 return true;
     330             :         }
     331           0 :         return false;
     332             :     }
     333             : 
     334             : private:
     335             :     EventQueue & mrEventQueue;
     336             :     EventMultiplexer & mrEventMultiplexer;
     337             :     bool mbSkipTriggersNextEffect;
     338             : };
     339             : 
     340           0 : class RewindEffectEventHandler : public MouseEventHandler_,
     341             :                                  public EventContainer
     342             : {
     343             : public:
     344           0 :     RewindEffectEventHandler( EventQueue & rEventQueue )
     345           0 :         : EventContainer(), mrEventQueue(rEventQueue) {}
     346             : 
     347             : private:
     348           0 :     virtual void dispose()
     349             :     {
     350           0 :         clearContainer();
     351           0 :     }
     352             : 
     353           0 :     virtual bool handleMouseReleased( awt::MouseEvent const& evt ) SAL_OVERRIDE
     354             :     {
     355           0 :         if(evt.Buttons != awt::MouseButton::RIGHT)
     356           0 :             return false;
     357             : 
     358           0 :         return fireAllEvents( maEvents, mrEventQueue );
     359             :     }
     360             : 
     361             : private:
     362             :     EventQueue & mrEventQueue;
     363             : };
     364             : 
     365             : /** Base class to share some common code between
     366             :     ShapeClickEventHandler and MouseMoveHandler
     367             : 
     368             :     @derive override necessary MouseEventHandler interface methods,
     369             :     call sendEvent() method to actually process the event.
     370             : */
     371           0 : class MouseHandlerBase : public MouseEventHandler_
     372             : {
     373             : public:
     374           0 :     MouseHandlerBase( EventQueue& rEventQueue ) :
     375             :         mrEventQueue( rEventQueue ),
     376           0 :         maShapeEventMap()
     377           0 :     {}
     378             : 
     379           0 :     virtual void dispose()
     380             :     {
     381             :         // TODO(Q1): Check whether plain vector with swap idiom is
     382             :         // okay here
     383           0 :         maShapeEventMap = ImpShapeEventMap();
     384           0 :     }
     385             : 
     386           0 :     void addEvent( const EventSharedPtr& rEvent,
     387             :                    const ShapeSharedPtr& rShape )
     388             :     {
     389           0 :         ImpShapeEventMap::iterator aIter;
     390           0 :         if( (aIter=maShapeEventMap.find( rShape )) == maShapeEventMap.end() )
     391             :         {
     392             :             // no entry for this shape -> create one
     393             :             aIter = maShapeEventMap.insert(
     394             :                 ImpShapeEventMap::value_type( rShape,
     395           0 :                                               ImpEventQueue() ) ).first;
     396             :         }
     397             : 
     398             :         // add new event to queue
     399           0 :         aIter->second.push( rEvent );
     400           0 :     }
     401             : 
     402             :     bool isEmpty()
     403             :     {
     404             :         // find at least one shape with a non-empty queue
     405             :         ImpShapeEventMap::reverse_iterator aCurrShape( maShapeEventMap.begin());
     406             :         ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.end() );
     407             :         while( aCurrShape != aEndShape )
     408             :         {
     409             :             if( !aCurrShape->second.empty() )
     410             :                 return false; // at least one non-empty entry found
     411             : 
     412             :             ++aCurrShape;
     413             :         }
     414             : 
     415             :         return true; // not a single non-empty entry found
     416             :     }
     417             : 
     418             : protected:
     419           0 :     bool hitTest( const awt::MouseEvent&                e,
     420             :                   ImpShapeEventMap::reverse_iterator&   o_rHitShape )
     421             :     {
     422             :         // find hit shape in map
     423           0 :         const basegfx::B2DPoint aPosition( e.X, e.Y );
     424             : 
     425             :         // find matching shape (scan reversely, to coarsely match
     426             :         // paint order)
     427           0 :         ImpShapeEventMap::reverse_iterator       aCurrShape(maShapeEventMap.rbegin());
     428           0 :         const ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.rend() );
     429           0 :         while( aCurrShape != aEndShape )
     430             :         {
     431             :             // TODO(F2): Get proper geometry polygon from the
     432             :             // shape, to avoid having areas outside the shape
     433             :             // react on the mouse
     434           0 :             if( aCurrShape->first->getBounds().isInside( aPosition ) &&
     435           0 :                 aCurrShape->first->isVisible() )
     436             :             {
     437             :                 // shape hit, and shape is visible - report a
     438             :                 // hit
     439           0 :                 o_rHitShape = aCurrShape;
     440           0 :                 return true;
     441             :             }
     442             : 
     443           0 :             ++aCurrShape;
     444             :         }
     445             : 
     446           0 :         return false; // nothing hit
     447             :     }
     448             : 
     449           0 :     bool sendEvent( ImpShapeEventMap::reverse_iterator& io_rHitShape )
     450             :     {
     451             :         // take next event from queue
     452           0 :         const bool bRet( fireSingleEvent( io_rHitShape->second,
     453           0 :                                           mrEventQueue ) );
     454             : 
     455             :         // clear shape entry, if its queue is
     456             :         // empty. This is important, since the shapes
     457             :         // are held by shared ptr, and might otherwise
     458             :         // not get released, even after their owning
     459             :         // slide is long gone.
     460           0 :         if( io_rHitShape->second.empty() )
     461             :         {
     462             :             // this looks funny, since ::std::map does
     463             :             // provide an erase( iterator )
     464             :             // method. Unfortunately, C++ does not
     465             :             // declare the obvious erase(
     466             :             // reverse_iterator ) needed here (missing
     467             :             // orthogonality, eh?)
     468           0 :             maShapeEventMap.erase( io_rHitShape->first );
     469             :         }
     470             : 
     471           0 :         return bRet;
     472             :     }
     473             : 
     474           0 :     bool processEvent( const awt::MouseEvent& e )
     475             :     {
     476           0 :         ImpShapeEventMap::reverse_iterator aCurrShape;
     477             : 
     478           0 :         if( hitTest( e, aCurrShape ) )
     479           0 :             return sendEvent( aCurrShape );
     480             : 
     481           0 :         return false; // did not handle the event
     482             :     }
     483             : 
     484             : private:
     485             :     EventQueue&         mrEventQueue;
     486             :     ImpShapeEventMap    maShapeEventMap;
     487             : };
     488             : 
     489           0 : class ShapeClickEventHandler : public MouseHandlerBase
     490             : {
     491             : public:
     492           0 :     ShapeClickEventHandler( CursorManager& rCursorManager,
     493             :                             EventQueue&    rEventQueue ) :
     494             :         MouseHandlerBase( rEventQueue ),
     495           0 :         mrCursorManager( rCursorManager )
     496           0 :     {}
     497             : 
     498           0 :     virtual bool handleMouseReleased( const awt::MouseEvent& e ) SAL_OVERRIDE
     499             :     {
     500           0 :         if(e.Buttons != awt::MouseButton::LEFT)
     501           0 :             return false;
     502           0 :         return processEvent( e );
     503             :     }
     504             : 
     505           0 :     virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
     506             :     {
     507             :         // TODO(P2): Maybe buffer last shape touched
     508             : 
     509             :         // if we have a shape click event, and the mouse
     510             :         // hovers over this shape, change cursor to hand
     511           0 :         ImpShapeEventMap::reverse_iterator aDummy;
     512           0 :         if( hitTest( e, aDummy ) )
     513           0 :             mrCursorManager.requestCursor( awt::SystemPointer::REFHAND );
     514             : 
     515           0 :         return false; // we don't /eat/ this event. Lower prio
     516             :         // handler should see it, too.
     517             :     }
     518             : 
     519             : private:
     520             :     CursorManager& mrCursorManager;
     521             : };
     522             : 
     523           0 : class MouseEnterHandler : public MouseHandlerBase
     524             : {
     525             : public:
     526           0 :     MouseEnterHandler( EventQueue& rEventQueue )
     527             :         : MouseHandlerBase( rEventQueue ),
     528           0 :           mpLastShape() {}
     529             : 
     530           0 :     virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
     531             :     {
     532             :         // TODO(P2): Maybe buffer last shape touched, and
     533             :         // check against that _first_
     534             : 
     535           0 :         ImpShapeEventMap::reverse_iterator aCurr;
     536           0 :         if( hitTest( e, aCurr ) )
     537             :         {
     538           0 :             if( aCurr->first != mpLastShape )
     539             :             {
     540             :                 // we actually hit a shape, and it's different
     541             :                 // from the previous one - thus we just
     542             :                 // entered it, raise event
     543           0 :                 sendEvent( aCurr );
     544           0 :                 mpLastShape = aCurr->first;
     545             :             }
     546             :         }
     547             :         else
     548             :         {
     549             :             // don't hit no shape - thus, last shape is NULL
     550           0 :             mpLastShape.reset();
     551             :         }
     552             : 
     553           0 :         return false; // we don't /eat/ this event. Lower prio
     554             :         // handler should see it, too.
     555             :     }
     556             : 
     557             : private:
     558             :     ShapeSharedPtr mpLastShape;
     559             : };
     560             : 
     561           0 : class MouseLeaveHandler : public MouseHandlerBase
     562             : {
     563             : public:
     564           0 :     MouseLeaveHandler( EventQueue& rEventQueue )
     565             :         : MouseHandlerBase( rEventQueue ),
     566           0 :           maLastIter() {}
     567             : 
     568           0 :     virtual bool handleMouseMoved( const awt::MouseEvent& e ) SAL_OVERRIDE
     569             :     {
     570             :         // TODO(P2): Maybe buffer last shape touched, and
     571             :         // check against that _first_
     572             : 
     573           0 :         ImpShapeEventMap::reverse_iterator aCurr;
     574           0 :         if( hitTest( e, aCurr ) )
     575             :         {
     576           0 :             maLastIter = aCurr;
     577             :         }
     578             :         else
     579             :         {
     580           0 :             if( maLastIter->first )
     581             :             {
     582             :                 // last time, we were over a shape, now we're
     583             :                 // not - we thus just left that shape, raise
     584             :                 // event
     585           0 :                 sendEvent( maLastIter );
     586             :             }
     587             : 
     588             :             // in any case, when we hit this else-branch: no
     589             :             // shape hit, thus have to clear maLastIter
     590           0 :             maLastIter = ImpShapeEventMap::reverse_iterator();
     591             :         }
     592             : 
     593           0 :         return false; // we don't /eat/ this event. Lower prio
     594             :         // handler should see it, too.
     595             :     }
     596             : 
     597             : private:
     598             :     ImpShapeEventMap::reverse_iterator maLastIter;
     599             : };
     600             : 
     601             : template< typename Handler, typename Functor >
     602           0 : void UserEventQueue::registerEvent(
     603             :     boost::shared_ptr< Handler >& rHandler,
     604             :     const EventSharedPtr&         rEvent,
     605             :     const Functor&                rRegistrationFunctor )
     606             : {
     607           0 :     ENSURE_OR_THROW( rEvent,
     608             :                       "UserEventQueue::registerEvent(): Invalid event" );
     609             : 
     610           0 :     if( !rHandler ) {
     611             :         // create handler
     612           0 :         rHandler.reset( new Handler( mrEventQueue ) );
     613             :         // register handler on EventMultiplexer
     614           0 :         rRegistrationFunctor( rHandler );
     615             :     }
     616             : 
     617           0 :     rHandler->addEvent( rEvent );
     618           0 : }
     619             : 
     620             : template< typename Handler, typename Arg, typename Functor >
     621           0 : void UserEventQueue::registerEvent(
     622             :     boost::shared_ptr< Handler >& rHandler,
     623             :     const EventSharedPtr&         rEvent,
     624             :     const Arg&                    rArg,
     625             :     const Functor&                rRegistrationFunctor )
     626             : {
     627           0 :     ENSURE_OR_THROW( rEvent,
     628             :                       "UserEventQueue::registerEvent(): Invalid event" );
     629             : 
     630           0 :     if( !rHandler ) {
     631             :         // create handler
     632           0 :         rHandler.reset( new Handler( mrEventQueue ) );
     633             : 
     634             :         // register handler on EventMultiplexer
     635           0 :         rRegistrationFunctor( rHandler );
     636             :     }
     637             : 
     638           0 :     rHandler->addEvent( rEvent, rArg );
     639           0 : }
     640             : 
     641             : 
     642             : 
     643           0 : UserEventQueue::UserEventQueue( EventMultiplexer&   rMultiplexer,
     644             :                                 EventQueue&         rEventQueue,
     645             :                                 CursorManager&      rCursorManager )
     646             :     : mrMultiplexer( rMultiplexer ),
     647             :       mrEventQueue( rEventQueue ),
     648             :       mrCursorManager( rCursorManager ),
     649             :       mpStartEventHandler(),
     650             :       mpEndEventHandler(),
     651             :       mpAnimationStartEventHandler(),
     652             :       mpAnimationEndEventHandler(),
     653             :       mpAudioStoppedEventHandler(),
     654             :       mpClickEventHandler(),
     655             :       mpSkipEffectEventHandler(),
     656             :       mpRewindEffectEventHandler(),
     657             :       mpDoubleClickEventHandler(),
     658             :       mpMouseEnterHandler(),
     659             :       mpMouseLeaveHandler(),
     660           0 :       mbAdvanceOnClick( true )
     661             : {
     662           0 : }
     663             : 
     664           0 : UserEventQueue::~UserEventQueue()
     665             : {
     666             :     try
     667             :     {
     668             :         // unregister all handlers
     669           0 :         clear();
     670             :     }
     671           0 :     catch (uno::Exception &) {
     672             :         OSL_FAIL( OUStringToOString(
     673             :                         comphelper::anyToString(
     674             :                             cppu::getCaughtException() ),
     675             :                         RTL_TEXTENCODING_UTF8 ).getStr() );
     676             :     }
     677           0 : }
     678             : 
     679           0 : void UserEventQueue::clear()
     680             : {
     681             :     // unregister and delete all handlers
     682           0 :     if( mpStartEventHandler ) {
     683           0 :         mrMultiplexer.removeSlideStartHandler( mpStartEventHandler );
     684           0 :         mpStartEventHandler.reset();
     685             :     }
     686           0 :     if( mpEndEventHandler ) {
     687           0 :         mrMultiplexer.removeSlideEndHandler( mpEndEventHandler );
     688           0 :         mpEndEventHandler.reset();
     689             :     }
     690           0 :     if( mpAnimationStartEventHandler ) {
     691             :         mrMultiplexer.removeAnimationStartHandler(
     692           0 :             mpAnimationStartEventHandler );
     693           0 :         mpAnimationStartEventHandler.reset();
     694             :     }
     695           0 :     if( mpAnimationEndEventHandler ) {
     696           0 :         mrMultiplexer.removeAnimationEndHandler( mpAnimationEndEventHandler );
     697           0 :         mpAnimationEndEventHandler.reset();
     698             :     }
     699           0 :     if( mpAudioStoppedEventHandler ) {
     700           0 :         mrMultiplexer.removeAudioStoppedHandler( mpAudioStoppedEventHandler );
     701           0 :         mpAudioStoppedEventHandler.reset();
     702             :     }
     703           0 :     if( mpShapeClickEventHandler ) {
     704           0 :         mrMultiplexer.removeClickHandler( mpShapeClickEventHandler );
     705           0 :         mrMultiplexer.removeMouseMoveHandler( mpShapeClickEventHandler );
     706           0 :         mpShapeClickEventHandler.reset();
     707             :     }
     708           0 :     if( mpClickEventHandler ) {
     709           0 :         mrMultiplexer.removeClickHandler( mpClickEventHandler );
     710           0 :         mrMultiplexer.removeNextEffectHandler( mpClickEventHandler );
     711           0 :         mpClickEventHandler.reset();
     712             :     }
     713           0 :     if(mpSkipEffectEventHandler) {
     714           0 :         mrMultiplexer.removeClickHandler( mpSkipEffectEventHandler );
     715           0 :         mrMultiplexer.removeNextEffectHandler( mpSkipEffectEventHandler );
     716           0 :         mpSkipEffectEventHandler.reset();
     717             :     }
     718           0 :     if(mpRewindEffectEventHandler) {
     719           0 :         mrMultiplexer.removeClickHandler( mpRewindEffectEventHandler );
     720           0 :         mpRewindEffectEventHandler.reset();
     721             :     }
     722           0 :     if( mpShapeDoubleClickEventHandler ) {
     723           0 :         mrMultiplexer.removeDoubleClickHandler( mpShapeDoubleClickEventHandler );
     724           0 :         mrMultiplexer.removeMouseMoveHandler( mpShapeDoubleClickEventHandler );
     725           0 :         mpShapeDoubleClickEventHandler.reset();
     726             :     }
     727           0 :     if( mpDoubleClickEventHandler ) {
     728           0 :         mrMultiplexer.removeDoubleClickHandler( mpDoubleClickEventHandler );
     729           0 :         mpDoubleClickEventHandler.reset();
     730             :     }
     731           0 :     if( mpMouseEnterHandler ) {
     732           0 :         mrMultiplexer.removeMouseMoveHandler( mpMouseEnterHandler );
     733           0 :         mpMouseEnterHandler.reset();
     734             :     }
     735           0 :     if( mpMouseLeaveHandler ) {
     736           0 :         mrMultiplexer.removeMouseMoveHandler( mpMouseLeaveHandler );
     737           0 :         mpMouseLeaveHandler.reset();
     738             :     }
     739           0 : }
     740             : 
     741           0 : void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick )
     742             : {
     743           0 :     mbAdvanceOnClick = bAdvanceOnClick;
     744             : 
     745             :     // forward to handler, if existing. Otherwise, the handler
     746             :     // creation will do the forwarding.
     747           0 :     if( mpClickEventHandler )
     748           0 :         mpClickEventHandler->setAdvanceOnClick( bAdvanceOnClick );
     749           0 : }
     750             : 
     751           0 : void UserEventQueue::registerAnimationStartEvent(
     752             :     const EventSharedPtr&                                 rEvent,
     753             :     const uno::Reference< animations::XAnimationNode>&    xNode )
     754             : {
     755             :     registerEvent( mpAnimationStartEventHandler,
     756             :                    rEvent,
     757             :                    xNode,
     758             :                    boost::bind( &EventMultiplexer::addAnimationStartHandler,
     759           0 :                                 boost::ref( mrMultiplexer ), _1 ) );
     760           0 : }
     761             : 
     762           0 : void UserEventQueue::registerAnimationEndEvent(
     763             :     const EventSharedPtr&                               rEvent,
     764             :     const uno::Reference<animations::XAnimationNode>&   xNode )
     765             : {
     766             :     registerEvent( mpAnimationEndEventHandler,
     767             :                    rEvent,
     768             :                    xNode,
     769             :                    boost::bind( &EventMultiplexer::addAnimationEndHandler,
     770           0 :                                 boost::ref( mrMultiplexer ), _1 ) );
     771           0 : }
     772             : 
     773           0 : void UserEventQueue::registerAudioStoppedEvent(
     774             :     const EventSharedPtr&                               rEvent,
     775             :     const uno::Reference<animations::XAnimationNode>&   xNode )
     776             : {
     777             :     registerEvent( mpAudioStoppedEventHandler,
     778             :                    rEvent,
     779             :                    xNode,
     780             :                    boost::bind( &EventMultiplexer::addAudioStoppedHandler,
     781           0 :                                 boost::ref( mrMultiplexer ), _1 ) );
     782           0 : }
     783             : 
     784           0 : void UserEventQueue::registerShapeClickEvent( const EventSharedPtr& rEvent,
     785             :                                               const ShapeSharedPtr& rShape )
     786             : {
     787           0 :     ENSURE_OR_THROW(
     788             :         rEvent,
     789             :         "UserEventQueue::registerShapeClickEvent(): Invalid event" );
     790             : 
     791           0 :     if( !mpShapeClickEventHandler )
     792             :     {
     793             :         // create handler
     794             :         mpShapeClickEventHandler.reset(
     795             :             new ShapeClickEventHandler(mrCursorManager,
     796           0 :                                        mrEventQueue) );
     797             : 
     798             :         // register handler on EventMultiplexer
     799           0 :         mrMultiplexer.addClickHandler( mpShapeClickEventHandler, 1.0 );
     800           0 :         mrMultiplexer.addMouseMoveHandler( mpShapeClickEventHandler, 1.0 );
     801             :     }
     802             : 
     803           0 :     mpShapeClickEventHandler->addEvent( rEvent, rShape );
     804           0 : }
     805             : 
     806             : namespace {
     807             : class ClickEventRegistrationFunctor
     808             : {
     809             : public:
     810           0 :     ClickEventRegistrationFunctor( EventMultiplexer& rMultiplexer,
     811             :                                    double            nPrio,
     812             :                                    bool              bAdvanceOnClick )
     813             :         : mrMultiplexer( rMultiplexer ),
     814             :           mnPrio(nPrio),
     815           0 :           mbAdvanceOnClick( bAdvanceOnClick ) {}
     816             : 
     817           0 :     void operator()( const boost::shared_ptr<ClickEventHandler>& rHandler )const
     818             :     {
     819             :         // register the handler on _two_ sources: we want the
     820             :         // nextEffect events, e.g. space bar, to trigger clicks, as well!
     821           0 :         mrMultiplexer.addClickHandler( rHandler, mnPrio );
     822           0 :         mrMultiplexer.addNextEffectHandler( rHandler, mnPrio );
     823             : 
     824             :         // forward advance-on-click state to newly
     825             :         // generated handler (that's the only reason why
     826             :         // we're called here)
     827           0 :         rHandler->setAdvanceOnClick( mbAdvanceOnClick );
     828           0 :     }
     829             : 
     830             : private:
     831             :     EventMultiplexer&   mrMultiplexer;
     832             :     double const        mnPrio;
     833             :     bool const          mbAdvanceOnClick;
     834             : };
     835             : } // anon namespace
     836             : 
     837           0 : void UserEventQueue::registerNextEffectEvent( const EventSharedPtr& rEvent )
     838             : {
     839             :     // TODO: better name may be mpNextEffectEventHandler?  then we have
     840             :     //       next effect (=> waiting to be started)
     841             :     //       skip effect (skipping the currently running one)
     842             :     //       rewind effect (rewinding back running one and waiting (again)
     843             :     //                      to be started)
     844             :     registerEvent( mpClickEventHandler,
     845             :                    rEvent,
     846             :                    ClickEventRegistrationFunctor( mrMultiplexer,
     847             :                                                   0.0 /* default prio */,
     848           0 :                                                   mbAdvanceOnClick ) );
     849           0 : }
     850             : 
     851           0 : void UserEventQueue::registerSkipEffectEvent(
     852             :     EventSharedPtr const & pEvent,
     853             :     const bool bSkipTriggersNextEffect)
     854             : {
     855           0 :     if(!mpSkipEffectEventHandler)
     856             :     {
     857             :         mpSkipEffectEventHandler.reset(
     858           0 :             new SkipEffectEventHandler( mrEventQueue, mrMultiplexer ) );
     859             :         // register the handler on _two_ sources: we want the
     860             :         // nextEffect events, e.g. space bar, to trigger clicks, as well!
     861             :         mrMultiplexer.addClickHandler( mpSkipEffectEventHandler,
     862           0 :                                        -1.0 /* prio below default */ );
     863             :         mrMultiplexer.addNextEffectHandler( mpSkipEffectEventHandler,
     864           0 :                                             -1.0 /* prio below default */ );
     865             :         // forward advance-on-click state to newly
     866             :         // generated handler (that's the only reason why
     867             :         // we're called here)
     868           0 :         mpSkipEffectEventHandler->setAdvanceOnClick( mbAdvanceOnClick );
     869             :     }
     870           0 :     mpSkipEffectEventHandler->setSkipTriggersNextEffect(bSkipTriggersNextEffect);
     871           0 :     mpSkipEffectEventHandler->addEvent( pEvent );
     872           0 : }
     873             : 
     874           0 : void UserEventQueue::registerRewindEffectEvent( EventSharedPtr const& pEvent )
     875             : {
     876             :     registerEvent( mpRewindEffectEventHandler,
     877             :                    pEvent,
     878             :                    boost::bind( &EventMultiplexer::addClickHandler,
     879             :                                 boost::ref(mrMultiplexer), _1,
     880           0 :                                 -1.0 /* prio below default */ ) );
     881           0 : }
     882             : 
     883           0 : void UserEventQueue::registerShapeDoubleClickEvent(
     884             :     const EventSharedPtr& rEvent,
     885             :     const ShapeSharedPtr& rShape )
     886             : {
     887           0 :     ENSURE_OR_THROW(
     888             :         rEvent,
     889             :         "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" );
     890             : 
     891           0 :     if( !mpShapeDoubleClickEventHandler )
     892             :     {
     893             :         // create handler
     894             :         mpShapeDoubleClickEventHandler.reset(
     895             :             new ShapeClickEventHandler(mrCursorManager,
     896           0 :                                        mrEventQueue) );
     897             : 
     898             :         // register handler on EventMultiplexer
     899             :         mrMultiplexer.addDoubleClickHandler( mpShapeDoubleClickEventHandler,
     900           0 :                                              1.0 );
     901             :         mrMultiplexer.addMouseMoveHandler( mpShapeDoubleClickEventHandler,
     902           0 :                                            1.0 );
     903             :     }
     904             : 
     905           0 :     mpShapeDoubleClickEventHandler->addEvent( rEvent, rShape );
     906           0 : }
     907             : 
     908           0 : void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr& rEvent,
     909             :                                               const ShapeSharedPtr& rShape )
     910             : {
     911             :     registerEvent( mpMouseEnterHandler,
     912             :                    rEvent,
     913             :                    rShape,
     914             :                    boost::bind( &EventMultiplexer::addMouseMoveHandler,
     915             :                                 boost::ref( mrMultiplexer ), _1,
     916           0 :                                 0.0 /* default prio */ ) );
     917           0 : }
     918             : 
     919           0 : void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr& rEvent,
     920             :                                               const ShapeSharedPtr& rShape )
     921             : {
     922             :     registerEvent( mpMouseLeaveHandler,
     923             :                    rEvent,
     924             :                    rShape,
     925             :                    boost::bind( &EventMultiplexer::addMouseMoveHandler,
     926             :                                 boost::ref( mrMultiplexer ), _1,
     927           0 :                                 0.0 /* default prio */ ) );
     928           0 : }
     929             : 
     930           0 : void UserEventQueue::callSkipEffectEventHandler (void)
     931             : {
     932             :     ::boost::shared_ptr<SkipEffectEventHandler> pHandler (
     933           0 :         ::boost::dynamic_pointer_cast<SkipEffectEventHandler>(mpSkipEffectEventHandler));
     934           0 :     if (pHandler)
     935           0 :         pHandler->skipEffect();
     936           0 : }
     937             : 
     938             : } // namespace internal
     939           0 : } // namespace presentation
     940             : 
     941             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10