1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_slideshow.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir // must be first 32*cdf0e10cSrcweir #include <canvas/debug.hxx> 33*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir #include <comphelper/anytostring.hxx> 36*cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx> 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir #include <com/sun/star/awt/SystemPointer.hpp> 39*cdf0e10cSrcweir #include <com/sun/star/awt/MouseButton.hpp> 40*cdf0e10cSrcweir #include <com/sun/star/awt/MouseEvent.hpp> 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir #include <boost/bind.hpp> 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir #include "delayevent.hxx" 45*cdf0e10cSrcweir #include "usereventqueue.hxx" 46*cdf0e10cSrcweir #include "cursormanager.hxx" 47*cdf0e10cSrcweir #include "slideshowexceptions.hxx" 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir #include <vector> 50*cdf0e10cSrcweir #include <queue> 51*cdf0e10cSrcweir #include <map> 52*cdf0e10cSrcweir #include <functional> 53*cdf0e10cSrcweir #include <algorithm> 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir using namespace com::sun::star; 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir /* Implementation of UserEventQueue class */ 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir namespace slideshow { 61*cdf0e10cSrcweir namespace internal { 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir namespace { 64*cdf0e10cSrcweir 65*cdf0e10cSrcweir typedef std::vector<EventSharedPtr> ImpEventVector; 66*cdf0e10cSrcweir typedef std::queue<EventSharedPtr> ImpEventQueue; 67*cdf0e10cSrcweir typedef std::map<uno::Reference<animations::XAnimationNode>, 68*cdf0e10cSrcweir ImpEventVector> ImpAnimationEventMap; 69*cdf0e10cSrcweir typedef std::map<ShapeSharedPtr, ImpEventQueue, 70*cdf0e10cSrcweir Shape::lessThanShape> ImpShapeEventMap; 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir // MouseEventHandler base class, not consuming any event: 73*cdf0e10cSrcweir class MouseEventHandler_ : public MouseEventHandler 74*cdf0e10cSrcweir { 75*cdf0e10cSrcweir public: 76*cdf0e10cSrcweir virtual bool handleMousePressed( awt::MouseEvent const& /*e*/ ) { return false;} 77*cdf0e10cSrcweir virtual bool handleMouseReleased( awt::MouseEvent const& /*e*/) { return false;} 78*cdf0e10cSrcweir virtual bool handleMouseEntered( awt::MouseEvent const& /*e*/ ) { return false;} 79*cdf0e10cSrcweir virtual bool handleMouseExited( awt::MouseEvent const& /*e*/ ) { return false; } 80*cdf0e10cSrcweir virtual bool handleMouseDragged( awt::MouseEvent const& /*e*/ ) { return false;} 81*cdf0e10cSrcweir virtual bool handleMouseMoved( awt::MouseEvent const& /*e*/ ) { return false; } 82*cdf0e10cSrcweir }; 83*cdf0e10cSrcweir 84*cdf0e10cSrcweir /** @return one event has been posted 85*cdf0e10cSrcweir */ 86*cdf0e10cSrcweir template <typename ContainerT> 87*cdf0e10cSrcweir bool fireSingleEvent( ContainerT & rQueue, EventQueue & rEventQueue ) 88*cdf0e10cSrcweir { 89*cdf0e10cSrcweir // post next event in given queue: 90*cdf0e10cSrcweir while (! rQueue.empty()) 91*cdf0e10cSrcweir { 92*cdf0e10cSrcweir EventSharedPtr const pEvent(rQueue.front()); 93*cdf0e10cSrcweir rQueue.pop(); 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir // skip all inactive events (as the purpose of 96*cdf0e10cSrcweir // nextEventFromQueue() is to activate the next 97*cdf0e10cSrcweir // event, and events which return false on 98*cdf0e10cSrcweir // isCharged() will never be activated by the 99*cdf0e10cSrcweir // EventQueue) 100*cdf0e10cSrcweir if(pEvent->isCharged()) 101*cdf0e10cSrcweir return rEventQueue.addEvent( pEvent ); 102*cdf0e10cSrcweir } 103*cdf0e10cSrcweir return false; // no more (active) events in queue 104*cdf0e10cSrcweir } 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir /** @return at least one event has been posted 107*cdf0e10cSrcweir */ 108*cdf0e10cSrcweir template <typename ContainerT> 109*cdf0e10cSrcweir bool fireAllEvents( ContainerT & rQueue, EventQueue & rEventQueue ) 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir bool bFiredAny = false; 112*cdf0e10cSrcweir while (fireSingleEvent( rQueue, rEventQueue )) 113*cdf0e10cSrcweir bFiredAny = true; 114*cdf0e10cSrcweir return bFiredAny; 115*cdf0e10cSrcweir } 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir class EventContainer 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir public: 120*cdf0e10cSrcweir EventContainer() : 121*cdf0e10cSrcweir maEvents() 122*cdf0e10cSrcweir {} 123*cdf0e10cSrcweir 124*cdf0e10cSrcweir void clearContainer() 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir maEvents = ImpEventQueue(); 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir void addEvent( const EventSharedPtr& rEvent ) 130*cdf0e10cSrcweir { 131*cdf0e10cSrcweir maEvents.push( rEvent ); 132*cdf0e10cSrcweir } 133*cdf0e10cSrcweir 134*cdf0e10cSrcweir bool isEmpty() 135*cdf0e10cSrcweir { 136*cdf0e10cSrcweir return maEvents.empty(); 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir 139*cdf0e10cSrcweir protected: 140*cdf0e10cSrcweir ImpEventQueue maEvents; 141*cdf0e10cSrcweir }; 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir } // anon namespace 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir class PlainEventHandler : public EventHandler, 146*cdf0e10cSrcweir public EventContainer 147*cdf0e10cSrcweir { 148*cdf0e10cSrcweir public: 149*cdf0e10cSrcweir PlainEventHandler( EventQueue & rEventQueue ) 150*cdf0e10cSrcweir : EventContainer(), mrEventQueue(rEventQueue) {} 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir virtual void dispose() 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir clearContainer(); 155*cdf0e10cSrcweir } 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir virtual bool handleEvent() 158*cdf0e10cSrcweir { 159*cdf0e10cSrcweir return fireAllEvents( maEvents, mrEventQueue ); 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir private: 163*cdf0e10cSrcweir EventQueue & mrEventQueue; 164*cdf0e10cSrcweir }; 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir class AllAnimationEventHandler : public AnimationEventHandler 167*cdf0e10cSrcweir { 168*cdf0e10cSrcweir public: 169*cdf0e10cSrcweir AllAnimationEventHandler( EventQueue& rEventQueue ) : 170*cdf0e10cSrcweir mrEventQueue( rEventQueue ), 171*cdf0e10cSrcweir maAnimationEventMap() 172*cdf0e10cSrcweir {} 173*cdf0e10cSrcweir 174*cdf0e10cSrcweir virtual void dispose() 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir maAnimationEventMap.clear(); 177*cdf0e10cSrcweir } 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) 180*cdf0e10cSrcweir { 181*cdf0e10cSrcweir ENSURE_OR_RETURN_FALSE( 182*cdf0e10cSrcweir rNode, 183*cdf0e10cSrcweir "AllAnimationEventHandler::handleAnimationEvent(): Invalid node" ); 184*cdf0e10cSrcweir 185*cdf0e10cSrcweir bool bRet( false ); 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir ImpAnimationEventMap::iterator aIter; 188*cdf0e10cSrcweir if( (aIter=maAnimationEventMap.find( 189*cdf0e10cSrcweir rNode->getXAnimationNode() )) != maAnimationEventMap.end() ) 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir ImpEventVector& rVec( aIter->second ); 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir bRet = !rVec.empty(); 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir // registered node found -> fire all events in the vector 196*cdf0e10cSrcweir std::for_each( rVec.begin(), rVec.end(), 197*cdf0e10cSrcweir boost::bind( &EventQueue::addEvent, 198*cdf0e10cSrcweir boost::ref( mrEventQueue ), _1 ) ); 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir rVec.clear(); 201*cdf0e10cSrcweir } 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir return bRet; 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir void addEvent( const EventSharedPtr& rEvent, 207*cdf0e10cSrcweir const uno::Reference< animations::XAnimationNode >& xNode ) 208*cdf0e10cSrcweir { 209*cdf0e10cSrcweir ImpAnimationEventMap::iterator aIter; 210*cdf0e10cSrcweir if( (aIter=maAnimationEventMap.find( xNode )) == 211*cdf0e10cSrcweir maAnimationEventMap.end() ) 212*cdf0e10cSrcweir { 213*cdf0e10cSrcweir // no entry for this animation -> create one 214*cdf0e10cSrcweir aIter = maAnimationEventMap.insert( 215*cdf0e10cSrcweir ImpAnimationEventMap::value_type( xNode, 216*cdf0e10cSrcweir ImpEventVector() ) ).first; 217*cdf0e10cSrcweir } 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir // add new event to queue 220*cdf0e10cSrcweir aIter->second.push_back( rEvent ); 221*cdf0e10cSrcweir } 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir bool isEmpty() 224*cdf0e10cSrcweir { 225*cdf0e10cSrcweir // find at least one animation with a non-empty vector 226*cdf0e10cSrcweir ImpAnimationEventMap::const_iterator aCurr( maAnimationEventMap.begin() ); 227*cdf0e10cSrcweir const ImpAnimationEventMap::const_iterator aEnd( maAnimationEventMap.end() ); 228*cdf0e10cSrcweir while( aCurr != aEnd ) 229*cdf0e10cSrcweir { 230*cdf0e10cSrcweir if( !aCurr->second.empty() ) 231*cdf0e10cSrcweir return false; // at least one non-empty entry found 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir ++aCurr; 234*cdf0e10cSrcweir } 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir return true; // not a single non-empty entry found 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir private: 240*cdf0e10cSrcweir EventQueue& mrEventQueue; 241*cdf0e10cSrcweir ImpAnimationEventMap maAnimationEventMap; 242*cdf0e10cSrcweir }; 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir class ClickEventHandler : public MouseEventHandler_, 245*cdf0e10cSrcweir public EventHandler, 246*cdf0e10cSrcweir public EventContainer 247*cdf0e10cSrcweir { 248*cdf0e10cSrcweir public: 249*cdf0e10cSrcweir ClickEventHandler( EventQueue& rEventQueue ) : 250*cdf0e10cSrcweir EventContainer(), 251*cdf0e10cSrcweir mrEventQueue( rEventQueue ), 252*cdf0e10cSrcweir mbAdvanceOnClick( true ) 253*cdf0e10cSrcweir {} 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir void setAdvanceOnClick( bool bAdvanceOnClick ) 256*cdf0e10cSrcweir { 257*cdf0e10cSrcweir mbAdvanceOnClick = bAdvanceOnClick; 258*cdf0e10cSrcweir } 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir private: 261*cdf0e10cSrcweir virtual void dispose() 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir clearContainer(); 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir // triggered by API calls, e.g. space bar 267*cdf0e10cSrcweir virtual bool handleEvent() 268*cdf0e10cSrcweir { 269*cdf0e10cSrcweir return handleEvent_impl(); 270*cdf0e10cSrcweir } 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir // triggered by mouse release: 273*cdf0e10cSrcweir virtual bool handleMouseReleased( const awt::MouseEvent& evt ) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir if(evt.Buttons != awt::MouseButton::LEFT) 276*cdf0e10cSrcweir return false; 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir if( mbAdvanceOnClick ) { 279*cdf0e10cSrcweir // fire next event 280*cdf0e10cSrcweir return handleEvent_impl(); 281*cdf0e10cSrcweir } 282*cdf0e10cSrcweir else { 283*cdf0e10cSrcweir return false; // advance-on-click disabled 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir } 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir // triggered by both: 288*cdf0e10cSrcweir virtual bool handleEvent_impl() 289*cdf0e10cSrcweir { 290*cdf0e10cSrcweir // fire next event: 291*cdf0e10cSrcweir return fireSingleEvent( maEvents, mrEventQueue ); 292*cdf0e10cSrcweir } 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir private: 295*cdf0e10cSrcweir EventQueue& mrEventQueue; 296*cdf0e10cSrcweir bool mbAdvanceOnClick; 297*cdf0e10cSrcweir }; 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir class SkipEffectEventHandler : public ClickEventHandler 300*cdf0e10cSrcweir { 301*cdf0e10cSrcweir public: 302*cdf0e10cSrcweir SkipEffectEventHandler( EventQueue & rEventQueue, 303*cdf0e10cSrcweir EventMultiplexer & rEventMultiplexer ) 304*cdf0e10cSrcweir : ClickEventHandler(rEventQueue), 305*cdf0e10cSrcweir mrEventQueue(rEventQueue), 306*cdf0e10cSrcweir mrEventMultiplexer(rEventMultiplexer), 307*cdf0e10cSrcweir mbSkipTriggersNextEffect(true) {} 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir /** Remember to trigger (or not to trigger) the next effect after the 310*cdf0e10cSrcweir current effect is skiped. 311*cdf0e10cSrcweir */ 312*cdf0e10cSrcweir void setSkipTriggersNextEffect (const bool bSkipTriggersNextEffect) 313*cdf0e10cSrcweir { mbSkipTriggersNextEffect = bSkipTriggersNextEffect; } 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir /// Skip the current effect but do not triggere the next effect. 316*cdf0e10cSrcweir void skipEffect (void) { handleEvent_impl(false); } 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir private: 319*cdf0e10cSrcweir virtual bool handleEvent_impl() 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir return handleEvent_impl(true); 322*cdf0e10cSrcweir } 323*cdf0e10cSrcweir 324*cdf0e10cSrcweir bool handleEvent_impl (bool bNotifyNextEffect) 325*cdf0e10cSrcweir { 326*cdf0e10cSrcweir // fire all events, so animation nodes can register their 327*cdf0e10cSrcweir // next effect listeners: 328*cdf0e10cSrcweir if(fireAllEvents( maEvents, mrEventQueue )) 329*cdf0e10cSrcweir { 330*cdf0e10cSrcweir if (mbSkipTriggersNextEffect && bNotifyNextEffect) 331*cdf0e10cSrcweir { 332*cdf0e10cSrcweir // then simulate a next effect event: this skip effect 333*cdf0e10cSrcweir // handler is triggered upon next effect events (multiplexer 334*cdf0e10cSrcweir // prio=-1)! Posting a notifyNextEffect() here is only safe 335*cdf0e10cSrcweir // (we don't run into busy loop), because we assume that 336*cdf0e10cSrcweir // someone has registerered above for next effects 337*cdf0e10cSrcweir // (multiplexer prio=0) at the user event queue. 338*cdf0e10cSrcweir return mrEventQueue.addEventWhenQueueIsEmpty( 339*cdf0e10cSrcweir makeEvent( boost::bind( &EventMultiplexer::notifyNextEffect, 340*cdf0e10cSrcweir boost::ref(mrEventMultiplexer) ), 341*cdf0e10cSrcweir "EventMultiplexer::notifyNextEffect") ); 342*cdf0e10cSrcweir } 343*cdf0e10cSrcweir else 344*cdf0e10cSrcweir return true; 345*cdf0e10cSrcweir } 346*cdf0e10cSrcweir return false; 347*cdf0e10cSrcweir } 348*cdf0e10cSrcweir 349*cdf0e10cSrcweir private: 350*cdf0e10cSrcweir EventQueue & mrEventQueue; 351*cdf0e10cSrcweir EventMultiplexer & mrEventMultiplexer; 352*cdf0e10cSrcweir bool mbSkipTriggersNextEffect; 353*cdf0e10cSrcweir }; 354*cdf0e10cSrcweir 355*cdf0e10cSrcweir class RewindEffectEventHandler : public MouseEventHandler_, 356*cdf0e10cSrcweir public EventContainer 357*cdf0e10cSrcweir { 358*cdf0e10cSrcweir public: 359*cdf0e10cSrcweir RewindEffectEventHandler( EventQueue & rEventQueue ) 360*cdf0e10cSrcweir : EventContainer(), mrEventQueue(rEventQueue) {} 361*cdf0e10cSrcweir 362*cdf0e10cSrcweir private: 363*cdf0e10cSrcweir virtual void dispose() 364*cdf0e10cSrcweir { 365*cdf0e10cSrcweir clearContainer(); 366*cdf0e10cSrcweir } 367*cdf0e10cSrcweir 368*cdf0e10cSrcweir virtual bool handleMouseReleased( awt::MouseEvent const& evt ) 369*cdf0e10cSrcweir { 370*cdf0e10cSrcweir if(evt.Buttons != awt::MouseButton::RIGHT) 371*cdf0e10cSrcweir return false; 372*cdf0e10cSrcweir 373*cdf0e10cSrcweir return fireAllEvents( maEvents, mrEventQueue ); 374*cdf0e10cSrcweir } 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir private: 377*cdf0e10cSrcweir EventQueue & mrEventQueue; 378*cdf0e10cSrcweir }; 379*cdf0e10cSrcweir 380*cdf0e10cSrcweir /** Base class to share some common code between 381*cdf0e10cSrcweir ShapeClickEventHandler and MouseMoveHandler 382*cdf0e10cSrcweir 383*cdf0e10cSrcweir @derive override necessary MouseEventHandler interface methods, 384*cdf0e10cSrcweir call sendEvent() method to actually process the event. 385*cdf0e10cSrcweir */ 386*cdf0e10cSrcweir class MouseHandlerBase : public MouseEventHandler_ 387*cdf0e10cSrcweir { 388*cdf0e10cSrcweir public: 389*cdf0e10cSrcweir MouseHandlerBase( EventQueue& rEventQueue ) : 390*cdf0e10cSrcweir mrEventQueue( rEventQueue ), 391*cdf0e10cSrcweir maShapeEventMap() 392*cdf0e10cSrcweir {} 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir virtual void dispose() 395*cdf0e10cSrcweir { 396*cdf0e10cSrcweir // TODO(Q1): Check whether plain vector with swap idiom is 397*cdf0e10cSrcweir // okay here 398*cdf0e10cSrcweir maShapeEventMap = ImpShapeEventMap(); 399*cdf0e10cSrcweir } 400*cdf0e10cSrcweir 401*cdf0e10cSrcweir void addEvent( const EventSharedPtr& rEvent, 402*cdf0e10cSrcweir const ShapeSharedPtr& rShape ) 403*cdf0e10cSrcweir { 404*cdf0e10cSrcweir ImpShapeEventMap::iterator aIter; 405*cdf0e10cSrcweir if( (aIter=maShapeEventMap.find( rShape )) == maShapeEventMap.end() ) 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir // no entry for this shape -> create one 408*cdf0e10cSrcweir aIter = maShapeEventMap.insert( 409*cdf0e10cSrcweir ImpShapeEventMap::value_type( rShape, 410*cdf0e10cSrcweir ImpEventQueue() ) ).first; 411*cdf0e10cSrcweir } 412*cdf0e10cSrcweir 413*cdf0e10cSrcweir // add new event to queue 414*cdf0e10cSrcweir aIter->second.push( rEvent ); 415*cdf0e10cSrcweir } 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir bool isEmpty() 418*cdf0e10cSrcweir { 419*cdf0e10cSrcweir // find at least one shape with a non-empty queue 420*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator aCurrShape( maShapeEventMap.begin()); 421*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.end() ); 422*cdf0e10cSrcweir while( aCurrShape != aEndShape ) 423*cdf0e10cSrcweir { 424*cdf0e10cSrcweir if( !aCurrShape->second.empty() ) 425*cdf0e10cSrcweir return false; // at least one non-empty entry found 426*cdf0e10cSrcweir 427*cdf0e10cSrcweir ++aCurrShape; 428*cdf0e10cSrcweir } 429*cdf0e10cSrcweir 430*cdf0e10cSrcweir return true; // not a single non-empty entry found 431*cdf0e10cSrcweir } 432*cdf0e10cSrcweir 433*cdf0e10cSrcweir protected: 434*cdf0e10cSrcweir bool hitTest( const awt::MouseEvent& e, 435*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator& o_rHitShape ) 436*cdf0e10cSrcweir { 437*cdf0e10cSrcweir // find hit shape in map 438*cdf0e10cSrcweir const basegfx::B2DPoint aPosition( e.X, e.Y ); 439*cdf0e10cSrcweir 440*cdf0e10cSrcweir // find matching shape (scan reversely, to coarsely match 441*cdf0e10cSrcweir // paint order) 442*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator aCurrShape(maShapeEventMap.rbegin()); 443*cdf0e10cSrcweir const ImpShapeEventMap::reverse_iterator aEndShape( maShapeEventMap.rend() ); 444*cdf0e10cSrcweir while( aCurrShape != aEndShape ) 445*cdf0e10cSrcweir { 446*cdf0e10cSrcweir // TODO(F2): Get proper geometry polygon from the 447*cdf0e10cSrcweir // shape, to avoid having areas outside the shape 448*cdf0e10cSrcweir // react on the mouse 449*cdf0e10cSrcweir if( aCurrShape->first->getBounds().isInside( aPosition ) && 450*cdf0e10cSrcweir aCurrShape->first->isVisible() ) 451*cdf0e10cSrcweir { 452*cdf0e10cSrcweir // shape hit, and shape is visible - report a 453*cdf0e10cSrcweir // hit 454*cdf0e10cSrcweir o_rHitShape = aCurrShape; 455*cdf0e10cSrcweir return true; 456*cdf0e10cSrcweir } 457*cdf0e10cSrcweir 458*cdf0e10cSrcweir ++aCurrShape; 459*cdf0e10cSrcweir } 460*cdf0e10cSrcweir 461*cdf0e10cSrcweir return false; // nothing hit 462*cdf0e10cSrcweir } 463*cdf0e10cSrcweir 464*cdf0e10cSrcweir bool sendEvent( ImpShapeEventMap::reverse_iterator& io_rHitShape ) 465*cdf0e10cSrcweir { 466*cdf0e10cSrcweir // take next event from queue 467*cdf0e10cSrcweir const bool bRet( fireSingleEvent( io_rHitShape->second, 468*cdf0e10cSrcweir mrEventQueue ) ); 469*cdf0e10cSrcweir 470*cdf0e10cSrcweir // clear shape entry, if its queue is 471*cdf0e10cSrcweir // empty. This is important, since the shapes 472*cdf0e10cSrcweir // are held by shared ptr, and might otherwise 473*cdf0e10cSrcweir // not get released, even after their owning 474*cdf0e10cSrcweir // slide is long gone. 475*cdf0e10cSrcweir if( io_rHitShape->second.empty() ) 476*cdf0e10cSrcweir { 477*cdf0e10cSrcweir // this looks funny, since ::std::map does 478*cdf0e10cSrcweir // provide an erase( iterator ) 479*cdf0e10cSrcweir // method. Unfortunately, stlport does not 480*cdf0e10cSrcweir // declare the obvious erase( 481*cdf0e10cSrcweir // reverse_iterator ) needed here (missing 482*cdf0e10cSrcweir // orthogonality, eh?) 483*cdf0e10cSrcweir maShapeEventMap.erase( io_rHitShape->first ); 484*cdf0e10cSrcweir } 485*cdf0e10cSrcweir 486*cdf0e10cSrcweir return bRet; 487*cdf0e10cSrcweir } 488*cdf0e10cSrcweir 489*cdf0e10cSrcweir bool processEvent( const awt::MouseEvent& e ) 490*cdf0e10cSrcweir { 491*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator aCurrShape; 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir if( hitTest( e, aCurrShape ) ) 494*cdf0e10cSrcweir return sendEvent( aCurrShape ); 495*cdf0e10cSrcweir 496*cdf0e10cSrcweir return false; // did not handle the event 497*cdf0e10cSrcweir } 498*cdf0e10cSrcweir 499*cdf0e10cSrcweir private: 500*cdf0e10cSrcweir EventQueue& mrEventQueue; 501*cdf0e10cSrcweir ImpShapeEventMap maShapeEventMap; 502*cdf0e10cSrcweir }; 503*cdf0e10cSrcweir 504*cdf0e10cSrcweir class ShapeClickEventHandler : public MouseHandlerBase 505*cdf0e10cSrcweir { 506*cdf0e10cSrcweir public: 507*cdf0e10cSrcweir ShapeClickEventHandler( CursorManager& rCursorManager, 508*cdf0e10cSrcweir EventQueue& rEventQueue ) : 509*cdf0e10cSrcweir MouseHandlerBase( rEventQueue ), 510*cdf0e10cSrcweir mrCursorManager( rCursorManager ) 511*cdf0e10cSrcweir {} 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir virtual bool handleMouseReleased( const awt::MouseEvent& e ) 514*cdf0e10cSrcweir { 515*cdf0e10cSrcweir if(e.Buttons != awt::MouseButton::LEFT) 516*cdf0e10cSrcweir return false; 517*cdf0e10cSrcweir return processEvent( e ); 518*cdf0e10cSrcweir } 519*cdf0e10cSrcweir 520*cdf0e10cSrcweir virtual bool handleMouseMoved( const awt::MouseEvent& e ) 521*cdf0e10cSrcweir { 522*cdf0e10cSrcweir // TODO(P2): Maybe buffer last shape touched 523*cdf0e10cSrcweir 524*cdf0e10cSrcweir // if we have a shape click event, and the mouse 525*cdf0e10cSrcweir // hovers over this shape, change cursor to hand 526*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator aDummy; 527*cdf0e10cSrcweir if( hitTest( e, aDummy ) ) 528*cdf0e10cSrcweir mrCursorManager.requestCursor( awt::SystemPointer::REFHAND ); 529*cdf0e10cSrcweir 530*cdf0e10cSrcweir return false; // we don't /eat/ this event. Lower prio 531*cdf0e10cSrcweir // handler should see it, too. 532*cdf0e10cSrcweir } 533*cdf0e10cSrcweir 534*cdf0e10cSrcweir private: 535*cdf0e10cSrcweir CursorManager& mrCursorManager; 536*cdf0e10cSrcweir }; 537*cdf0e10cSrcweir 538*cdf0e10cSrcweir class MouseEnterHandler : public MouseHandlerBase 539*cdf0e10cSrcweir { 540*cdf0e10cSrcweir public: 541*cdf0e10cSrcweir MouseEnterHandler( EventQueue& rEventQueue ) 542*cdf0e10cSrcweir : MouseHandlerBase( rEventQueue ), 543*cdf0e10cSrcweir mpLastShape() {} 544*cdf0e10cSrcweir 545*cdf0e10cSrcweir virtual bool handleMouseMoved( const awt::MouseEvent& e ) 546*cdf0e10cSrcweir { 547*cdf0e10cSrcweir // TODO(P2): Maybe buffer last shape touched, and 548*cdf0e10cSrcweir // check against that _first_ 549*cdf0e10cSrcweir 550*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator aCurr; 551*cdf0e10cSrcweir if( hitTest( e, aCurr ) ) 552*cdf0e10cSrcweir { 553*cdf0e10cSrcweir if( aCurr->first != mpLastShape ) 554*cdf0e10cSrcweir { 555*cdf0e10cSrcweir // we actually hit a shape, and it's different 556*cdf0e10cSrcweir // from the previous one - thus we just 557*cdf0e10cSrcweir // entered it, raise event 558*cdf0e10cSrcweir sendEvent( aCurr ); 559*cdf0e10cSrcweir mpLastShape = aCurr->first; 560*cdf0e10cSrcweir } 561*cdf0e10cSrcweir } 562*cdf0e10cSrcweir else 563*cdf0e10cSrcweir { 564*cdf0e10cSrcweir // don't hit no shape - thus, last shape is NULL 565*cdf0e10cSrcweir mpLastShape.reset(); 566*cdf0e10cSrcweir } 567*cdf0e10cSrcweir 568*cdf0e10cSrcweir return false; // we don't /eat/ this event. Lower prio 569*cdf0e10cSrcweir // handler should see it, too. 570*cdf0e10cSrcweir } 571*cdf0e10cSrcweir 572*cdf0e10cSrcweir private: 573*cdf0e10cSrcweir ShapeSharedPtr mpLastShape; 574*cdf0e10cSrcweir }; 575*cdf0e10cSrcweir 576*cdf0e10cSrcweir class MouseLeaveHandler : public MouseHandlerBase 577*cdf0e10cSrcweir { 578*cdf0e10cSrcweir public: 579*cdf0e10cSrcweir MouseLeaveHandler( EventQueue& rEventQueue ) 580*cdf0e10cSrcweir : MouseHandlerBase( rEventQueue ), 581*cdf0e10cSrcweir maLastIter() {} 582*cdf0e10cSrcweir 583*cdf0e10cSrcweir virtual bool handleMouseMoved( const awt::MouseEvent& e ) 584*cdf0e10cSrcweir { 585*cdf0e10cSrcweir // TODO(P2): Maybe buffer last shape touched, and 586*cdf0e10cSrcweir // check against that _first_ 587*cdf0e10cSrcweir 588*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator aCurr; 589*cdf0e10cSrcweir if( hitTest( e, aCurr ) ) 590*cdf0e10cSrcweir { 591*cdf0e10cSrcweir maLastIter = aCurr; 592*cdf0e10cSrcweir } 593*cdf0e10cSrcweir else 594*cdf0e10cSrcweir { 595*cdf0e10cSrcweir if( maLastIter->first ) 596*cdf0e10cSrcweir { 597*cdf0e10cSrcweir // last time, we were over a shape, now we're 598*cdf0e10cSrcweir // not - we thus just left that shape, raise 599*cdf0e10cSrcweir // event 600*cdf0e10cSrcweir sendEvent( maLastIter ); 601*cdf0e10cSrcweir } 602*cdf0e10cSrcweir 603*cdf0e10cSrcweir // in any case, when we hit this else-branch: no 604*cdf0e10cSrcweir // shape hit, thus have to clear maLastIter 605*cdf0e10cSrcweir maLastIter = ImpShapeEventMap::reverse_iterator(); 606*cdf0e10cSrcweir } 607*cdf0e10cSrcweir 608*cdf0e10cSrcweir return false; // we don't /eat/ this event. Lower prio 609*cdf0e10cSrcweir // handler should see it, too. 610*cdf0e10cSrcweir } 611*cdf0e10cSrcweir 612*cdf0e10cSrcweir private: 613*cdf0e10cSrcweir ImpShapeEventMap::reverse_iterator maLastIter; 614*cdf0e10cSrcweir }; 615*cdf0e10cSrcweir 616*cdf0e10cSrcweir template< typename Handler, typename Functor > 617*cdf0e10cSrcweir void UserEventQueue::registerEvent( 618*cdf0e10cSrcweir boost::shared_ptr< Handler >& rHandler, 619*cdf0e10cSrcweir const EventSharedPtr& rEvent, 620*cdf0e10cSrcweir const Functor& rRegistrationFunctor ) 621*cdf0e10cSrcweir { 622*cdf0e10cSrcweir ENSURE_OR_THROW( rEvent, 623*cdf0e10cSrcweir "UserEventQueue::registerEvent(): Invalid event" ); 624*cdf0e10cSrcweir 625*cdf0e10cSrcweir if( !rHandler ) { 626*cdf0e10cSrcweir // create handler 627*cdf0e10cSrcweir rHandler.reset( new Handler( mrEventQueue ) ); 628*cdf0e10cSrcweir // register handler on EventMultiplexer 629*cdf0e10cSrcweir rRegistrationFunctor( rHandler ); 630*cdf0e10cSrcweir } 631*cdf0e10cSrcweir 632*cdf0e10cSrcweir rHandler->addEvent( rEvent ); 633*cdf0e10cSrcweir } 634*cdf0e10cSrcweir 635*cdf0e10cSrcweir template< typename Handler, typename Arg, typename Functor > 636*cdf0e10cSrcweir void UserEventQueue::registerEvent( 637*cdf0e10cSrcweir boost::shared_ptr< Handler >& rHandler, 638*cdf0e10cSrcweir const EventSharedPtr& rEvent, 639*cdf0e10cSrcweir const Arg& rArg, 640*cdf0e10cSrcweir const Functor& rRegistrationFunctor ) 641*cdf0e10cSrcweir { 642*cdf0e10cSrcweir ENSURE_OR_THROW( rEvent, 643*cdf0e10cSrcweir "UserEventQueue::registerEvent(): Invalid event" ); 644*cdf0e10cSrcweir 645*cdf0e10cSrcweir if( !rHandler ) { 646*cdf0e10cSrcweir // create handler 647*cdf0e10cSrcweir rHandler.reset( new Handler( mrEventQueue ) ); 648*cdf0e10cSrcweir 649*cdf0e10cSrcweir // register handler on EventMultiplexer 650*cdf0e10cSrcweir rRegistrationFunctor( rHandler ); 651*cdf0e10cSrcweir } 652*cdf0e10cSrcweir 653*cdf0e10cSrcweir rHandler->addEvent( rEvent, rArg ); 654*cdf0e10cSrcweir } 655*cdf0e10cSrcweir 656*cdf0e10cSrcweir 657*cdf0e10cSrcweir // Public methods 658*cdf0e10cSrcweir // ===================================================== 659*cdf0e10cSrcweir 660*cdf0e10cSrcweir UserEventQueue::UserEventQueue( EventMultiplexer& rMultiplexer, 661*cdf0e10cSrcweir EventQueue& rEventQueue, 662*cdf0e10cSrcweir CursorManager& rCursorManager ) 663*cdf0e10cSrcweir : mrMultiplexer( rMultiplexer ), 664*cdf0e10cSrcweir mrEventQueue( rEventQueue ), 665*cdf0e10cSrcweir mrCursorManager( rCursorManager ), 666*cdf0e10cSrcweir mpStartEventHandler(), 667*cdf0e10cSrcweir mpEndEventHandler(), 668*cdf0e10cSrcweir mpAnimationStartEventHandler(), 669*cdf0e10cSrcweir mpAnimationEndEventHandler(), 670*cdf0e10cSrcweir mpAudioStoppedEventHandler(), 671*cdf0e10cSrcweir mpClickEventHandler(), 672*cdf0e10cSrcweir mpSkipEffectEventHandler(), 673*cdf0e10cSrcweir mpRewindEffectEventHandler(), 674*cdf0e10cSrcweir mpDoubleClickEventHandler(), 675*cdf0e10cSrcweir mpMouseEnterHandler(), 676*cdf0e10cSrcweir mpMouseLeaveHandler(), 677*cdf0e10cSrcweir mbAdvanceOnClick( true ) 678*cdf0e10cSrcweir { 679*cdf0e10cSrcweir } 680*cdf0e10cSrcweir 681*cdf0e10cSrcweir UserEventQueue::~UserEventQueue() 682*cdf0e10cSrcweir { 683*cdf0e10cSrcweir try 684*cdf0e10cSrcweir { 685*cdf0e10cSrcweir // unregister all handlers 686*cdf0e10cSrcweir clear(); 687*cdf0e10cSrcweir } 688*cdf0e10cSrcweir catch (uno::Exception &) { 689*cdf0e10cSrcweir OSL_ENSURE( false, rtl::OUStringToOString( 690*cdf0e10cSrcweir comphelper::anyToString( 691*cdf0e10cSrcweir cppu::getCaughtException() ), 692*cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 ).getStr() ); 693*cdf0e10cSrcweir } 694*cdf0e10cSrcweir } 695*cdf0e10cSrcweir 696*cdf0e10cSrcweir bool UserEventQueue::isEmpty() const 697*cdf0e10cSrcweir { 698*cdf0e10cSrcweir // TODO(T2): This is not thread safe, the handlers are all 699*cdf0e10cSrcweir // only separately synchronized. This poses the danger of 700*cdf0e10cSrcweir // generating false empty status on XSlideShow::update(), such 701*cdf0e10cSrcweir // that the last events of a slide are not triggered. 702*cdf0e10cSrcweir 703*cdf0e10cSrcweir // we're empty iff all handler queues are empty 704*cdf0e10cSrcweir return 705*cdf0e10cSrcweir (mpStartEventHandler ? mpStartEventHandler->isEmpty() : true) && 706*cdf0e10cSrcweir (mpEndEventHandler ? mpEndEventHandler->isEmpty() : true) && 707*cdf0e10cSrcweir (mpAnimationStartEventHandler ? mpAnimationStartEventHandler->isEmpty() : true) && 708*cdf0e10cSrcweir (mpAnimationEndEventHandler ? mpAnimationEndEventHandler->isEmpty() : true) && 709*cdf0e10cSrcweir (mpAudioStoppedEventHandler ? mpAudioStoppedEventHandler->isEmpty() : true) && 710*cdf0e10cSrcweir (mpShapeClickEventHandler ? mpShapeClickEventHandler->isEmpty() : true) && 711*cdf0e10cSrcweir (mpClickEventHandler ? mpClickEventHandler->isEmpty() : true) && 712*cdf0e10cSrcweir (mpSkipEffectEventHandler ? mpSkipEffectEventHandler->isEmpty() : true) && 713*cdf0e10cSrcweir (mpRewindEffectEventHandler ? mpRewindEffectEventHandler->isEmpty() : true) && 714*cdf0e10cSrcweir (mpShapeDoubleClickEventHandler ? mpShapeDoubleClickEventHandler->isEmpty() : true) && 715*cdf0e10cSrcweir (mpDoubleClickEventHandler ? mpDoubleClickEventHandler->isEmpty() : true) && 716*cdf0e10cSrcweir (mpMouseEnterHandler ? mpMouseEnterHandler->isEmpty() : true) && 717*cdf0e10cSrcweir (mpMouseLeaveHandler ? mpMouseLeaveHandler->isEmpty() : true); 718*cdf0e10cSrcweir } 719*cdf0e10cSrcweir 720*cdf0e10cSrcweir void UserEventQueue::clear() 721*cdf0e10cSrcweir { 722*cdf0e10cSrcweir // unregister and delete all handlers 723*cdf0e10cSrcweir if( mpStartEventHandler ) { 724*cdf0e10cSrcweir mrMultiplexer.removeSlideStartHandler( mpStartEventHandler ); 725*cdf0e10cSrcweir mpStartEventHandler.reset(); 726*cdf0e10cSrcweir } 727*cdf0e10cSrcweir if( mpEndEventHandler ) { 728*cdf0e10cSrcweir mrMultiplexer.removeSlideEndHandler( mpEndEventHandler ); 729*cdf0e10cSrcweir mpEndEventHandler.reset(); 730*cdf0e10cSrcweir } 731*cdf0e10cSrcweir if( mpAnimationStartEventHandler ) { 732*cdf0e10cSrcweir mrMultiplexer.removeAnimationStartHandler( 733*cdf0e10cSrcweir mpAnimationStartEventHandler ); 734*cdf0e10cSrcweir mpAnimationStartEventHandler.reset(); 735*cdf0e10cSrcweir } 736*cdf0e10cSrcweir if( mpAnimationEndEventHandler ) { 737*cdf0e10cSrcweir mrMultiplexer.removeAnimationEndHandler( mpAnimationEndEventHandler ); 738*cdf0e10cSrcweir mpAnimationEndEventHandler.reset(); 739*cdf0e10cSrcweir } 740*cdf0e10cSrcweir if( mpAudioStoppedEventHandler ) { 741*cdf0e10cSrcweir mrMultiplexer.removeAudioStoppedHandler( mpAudioStoppedEventHandler ); 742*cdf0e10cSrcweir mpAudioStoppedEventHandler.reset(); 743*cdf0e10cSrcweir } 744*cdf0e10cSrcweir if( mpShapeClickEventHandler ) { 745*cdf0e10cSrcweir mrMultiplexer.removeClickHandler( mpShapeClickEventHandler ); 746*cdf0e10cSrcweir mrMultiplexer.removeMouseMoveHandler( mpShapeClickEventHandler ); 747*cdf0e10cSrcweir mpShapeClickEventHandler.reset(); 748*cdf0e10cSrcweir } 749*cdf0e10cSrcweir if( mpClickEventHandler ) { 750*cdf0e10cSrcweir mrMultiplexer.removeClickHandler( mpClickEventHandler ); 751*cdf0e10cSrcweir mrMultiplexer.removeNextEffectHandler( mpClickEventHandler ); 752*cdf0e10cSrcweir mpClickEventHandler.reset(); 753*cdf0e10cSrcweir } 754*cdf0e10cSrcweir if(mpSkipEffectEventHandler) { 755*cdf0e10cSrcweir mrMultiplexer.removeClickHandler( mpSkipEffectEventHandler ); 756*cdf0e10cSrcweir mrMultiplexer.removeNextEffectHandler( mpSkipEffectEventHandler ); 757*cdf0e10cSrcweir mpSkipEffectEventHandler.reset(); 758*cdf0e10cSrcweir } 759*cdf0e10cSrcweir if(mpRewindEffectEventHandler) { 760*cdf0e10cSrcweir mrMultiplexer.removeClickHandler( mpRewindEffectEventHandler ); 761*cdf0e10cSrcweir mpRewindEffectEventHandler.reset(); 762*cdf0e10cSrcweir } 763*cdf0e10cSrcweir if( mpShapeDoubleClickEventHandler ) { 764*cdf0e10cSrcweir mrMultiplexer.removeDoubleClickHandler( mpShapeDoubleClickEventHandler ); 765*cdf0e10cSrcweir mrMultiplexer.removeMouseMoveHandler( mpShapeDoubleClickEventHandler ); 766*cdf0e10cSrcweir mpShapeDoubleClickEventHandler.reset(); 767*cdf0e10cSrcweir } 768*cdf0e10cSrcweir if( mpDoubleClickEventHandler ) { 769*cdf0e10cSrcweir mrMultiplexer.removeDoubleClickHandler( mpDoubleClickEventHandler ); 770*cdf0e10cSrcweir mpDoubleClickEventHandler.reset(); 771*cdf0e10cSrcweir } 772*cdf0e10cSrcweir if( mpMouseEnterHandler ) { 773*cdf0e10cSrcweir mrMultiplexer.removeMouseMoveHandler( mpMouseEnterHandler ); 774*cdf0e10cSrcweir mpMouseEnterHandler.reset(); 775*cdf0e10cSrcweir } 776*cdf0e10cSrcweir if( mpMouseLeaveHandler ) { 777*cdf0e10cSrcweir mrMultiplexer.removeMouseMoveHandler( mpMouseLeaveHandler ); 778*cdf0e10cSrcweir mpMouseLeaveHandler.reset(); 779*cdf0e10cSrcweir } 780*cdf0e10cSrcweir } 781*cdf0e10cSrcweir 782*cdf0e10cSrcweir void UserEventQueue::setAdvanceOnClick( bool bAdvanceOnClick ) 783*cdf0e10cSrcweir { 784*cdf0e10cSrcweir mbAdvanceOnClick = bAdvanceOnClick; 785*cdf0e10cSrcweir 786*cdf0e10cSrcweir // forward to handler, if existing. Otherwise, the handler 787*cdf0e10cSrcweir // creation will do the forwarding. 788*cdf0e10cSrcweir if( mpClickEventHandler ) 789*cdf0e10cSrcweir mpClickEventHandler->setAdvanceOnClick( bAdvanceOnClick ); 790*cdf0e10cSrcweir } 791*cdf0e10cSrcweir 792*cdf0e10cSrcweir 793*cdf0e10cSrcweir void UserEventQueue::registerSlideStartEvent( const EventSharedPtr& rEvent ) 794*cdf0e10cSrcweir { 795*cdf0e10cSrcweir registerEvent( mpStartEventHandler, 796*cdf0e10cSrcweir rEvent, 797*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addSlideStartHandler, 798*cdf0e10cSrcweir boost::ref( mrMultiplexer ), _1 ) ); 799*cdf0e10cSrcweir } 800*cdf0e10cSrcweir 801*cdf0e10cSrcweir void UserEventQueue::registerSlideEndEvent( const EventSharedPtr& rEvent ) 802*cdf0e10cSrcweir { 803*cdf0e10cSrcweir registerEvent( mpEndEventHandler, 804*cdf0e10cSrcweir rEvent, 805*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addSlideEndHandler, 806*cdf0e10cSrcweir boost::ref( mrMultiplexer ), _1 ) ); 807*cdf0e10cSrcweir } 808*cdf0e10cSrcweir 809*cdf0e10cSrcweir void UserEventQueue::registerAnimationStartEvent( 810*cdf0e10cSrcweir const EventSharedPtr& rEvent, 811*cdf0e10cSrcweir const uno::Reference< animations::XAnimationNode>& xNode ) 812*cdf0e10cSrcweir { 813*cdf0e10cSrcweir registerEvent( mpAnimationStartEventHandler, 814*cdf0e10cSrcweir rEvent, 815*cdf0e10cSrcweir xNode, 816*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addAnimationStartHandler, 817*cdf0e10cSrcweir boost::ref( mrMultiplexer ), _1 ) ); 818*cdf0e10cSrcweir } 819*cdf0e10cSrcweir 820*cdf0e10cSrcweir void UserEventQueue::registerAnimationEndEvent( 821*cdf0e10cSrcweir const EventSharedPtr& rEvent, 822*cdf0e10cSrcweir const uno::Reference<animations::XAnimationNode>& xNode ) 823*cdf0e10cSrcweir { 824*cdf0e10cSrcweir registerEvent( mpAnimationEndEventHandler, 825*cdf0e10cSrcweir rEvent, 826*cdf0e10cSrcweir xNode, 827*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addAnimationEndHandler, 828*cdf0e10cSrcweir boost::ref( mrMultiplexer ), _1 ) ); 829*cdf0e10cSrcweir } 830*cdf0e10cSrcweir 831*cdf0e10cSrcweir void UserEventQueue::registerAudioStoppedEvent( 832*cdf0e10cSrcweir const EventSharedPtr& rEvent, 833*cdf0e10cSrcweir const uno::Reference<animations::XAnimationNode>& xNode ) 834*cdf0e10cSrcweir { 835*cdf0e10cSrcweir registerEvent( mpAudioStoppedEventHandler, 836*cdf0e10cSrcweir rEvent, 837*cdf0e10cSrcweir xNode, 838*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addAudioStoppedHandler, 839*cdf0e10cSrcweir boost::ref( mrMultiplexer ), _1 ) ); 840*cdf0e10cSrcweir } 841*cdf0e10cSrcweir 842*cdf0e10cSrcweir void UserEventQueue::registerShapeClickEvent( const EventSharedPtr& rEvent, 843*cdf0e10cSrcweir const ShapeSharedPtr& rShape ) 844*cdf0e10cSrcweir { 845*cdf0e10cSrcweir ENSURE_OR_THROW( 846*cdf0e10cSrcweir rEvent, 847*cdf0e10cSrcweir "UserEventQueue::registerShapeClickEvent(): Invalid event" ); 848*cdf0e10cSrcweir 849*cdf0e10cSrcweir if( !mpShapeClickEventHandler ) 850*cdf0e10cSrcweir { 851*cdf0e10cSrcweir // create handler 852*cdf0e10cSrcweir mpShapeClickEventHandler.reset( 853*cdf0e10cSrcweir new ShapeClickEventHandler(mrCursorManager, 854*cdf0e10cSrcweir mrEventQueue) ); 855*cdf0e10cSrcweir 856*cdf0e10cSrcweir // register handler on EventMultiplexer 857*cdf0e10cSrcweir mrMultiplexer.addClickHandler( mpShapeClickEventHandler, 1.0 ); 858*cdf0e10cSrcweir mrMultiplexer.addMouseMoveHandler( mpShapeClickEventHandler, 1.0 ); 859*cdf0e10cSrcweir } 860*cdf0e10cSrcweir 861*cdf0e10cSrcweir mpShapeClickEventHandler->addEvent( rEvent, rShape ); 862*cdf0e10cSrcweir } 863*cdf0e10cSrcweir 864*cdf0e10cSrcweir namespace { 865*cdf0e10cSrcweir class ClickEventRegistrationFunctor 866*cdf0e10cSrcweir { 867*cdf0e10cSrcweir public: 868*cdf0e10cSrcweir ClickEventRegistrationFunctor( EventMultiplexer& rMultiplexer, 869*cdf0e10cSrcweir double nPrio, 870*cdf0e10cSrcweir bool bAdvanceOnClick ) 871*cdf0e10cSrcweir : mrMultiplexer( rMultiplexer ), 872*cdf0e10cSrcweir mnPrio(nPrio), 873*cdf0e10cSrcweir mbAdvanceOnClick( bAdvanceOnClick ) {} 874*cdf0e10cSrcweir 875*cdf0e10cSrcweir void operator()( const boost::shared_ptr<ClickEventHandler>& rHandler )const 876*cdf0e10cSrcweir { 877*cdf0e10cSrcweir // register the handler on _two_ sources: we want the 878*cdf0e10cSrcweir // nextEffect events, e.g. space bar, to trigger clicks, as well! 879*cdf0e10cSrcweir mrMultiplexer.addClickHandler( rHandler, mnPrio ); 880*cdf0e10cSrcweir mrMultiplexer.addNextEffectHandler( rHandler, mnPrio ); 881*cdf0e10cSrcweir 882*cdf0e10cSrcweir // forward advance-on-click state to newly 883*cdf0e10cSrcweir // generated handler (that's the only reason why 884*cdf0e10cSrcweir // we're called here) 885*cdf0e10cSrcweir rHandler->setAdvanceOnClick( mbAdvanceOnClick ); 886*cdf0e10cSrcweir } 887*cdf0e10cSrcweir 888*cdf0e10cSrcweir private: 889*cdf0e10cSrcweir EventMultiplexer& mrMultiplexer; 890*cdf0e10cSrcweir double const mnPrio; 891*cdf0e10cSrcweir bool const mbAdvanceOnClick; 892*cdf0e10cSrcweir }; 893*cdf0e10cSrcweir } // anon namespace 894*cdf0e10cSrcweir 895*cdf0e10cSrcweir void UserEventQueue::registerNextEffectEvent( const EventSharedPtr& rEvent ) 896*cdf0e10cSrcweir { 897*cdf0e10cSrcweir // TODO: better name may be mpNextEffectEventHandler? then we have 898*cdf0e10cSrcweir // next effect (=> waiting to be started) 899*cdf0e10cSrcweir // skip effect (skipping the currently running one) 900*cdf0e10cSrcweir // rewind effect (rewinding back running one and waiting (again) 901*cdf0e10cSrcweir // to be started) 902*cdf0e10cSrcweir registerEvent( mpClickEventHandler, 903*cdf0e10cSrcweir rEvent, 904*cdf0e10cSrcweir ClickEventRegistrationFunctor( mrMultiplexer, 905*cdf0e10cSrcweir 0.0 /* default prio */, 906*cdf0e10cSrcweir mbAdvanceOnClick ) ); 907*cdf0e10cSrcweir } 908*cdf0e10cSrcweir 909*cdf0e10cSrcweir void UserEventQueue::registerSkipEffectEvent( 910*cdf0e10cSrcweir EventSharedPtr const & pEvent, 911*cdf0e10cSrcweir const bool bSkipTriggersNextEffect) 912*cdf0e10cSrcweir { 913*cdf0e10cSrcweir if(!mpSkipEffectEventHandler) 914*cdf0e10cSrcweir { 915*cdf0e10cSrcweir mpSkipEffectEventHandler.reset( 916*cdf0e10cSrcweir new SkipEffectEventHandler( mrEventQueue, mrMultiplexer ) ); 917*cdf0e10cSrcweir // register the handler on _two_ sources: we want the 918*cdf0e10cSrcweir // nextEffect events, e.g. space bar, to trigger clicks, as well! 919*cdf0e10cSrcweir mrMultiplexer.addClickHandler( mpSkipEffectEventHandler, 920*cdf0e10cSrcweir -1.0 /* prio below default */ ); 921*cdf0e10cSrcweir mrMultiplexer.addNextEffectHandler( mpSkipEffectEventHandler, 922*cdf0e10cSrcweir -1.0 /* prio below default */ ); 923*cdf0e10cSrcweir // forward advance-on-click state to newly 924*cdf0e10cSrcweir // generated handler (that's the only reason why 925*cdf0e10cSrcweir // we're called here) 926*cdf0e10cSrcweir mpSkipEffectEventHandler->setAdvanceOnClick( mbAdvanceOnClick ); 927*cdf0e10cSrcweir } 928*cdf0e10cSrcweir mpSkipEffectEventHandler->setSkipTriggersNextEffect(bSkipTriggersNextEffect); 929*cdf0e10cSrcweir mpSkipEffectEventHandler->addEvent( pEvent ); 930*cdf0e10cSrcweir } 931*cdf0e10cSrcweir 932*cdf0e10cSrcweir void UserEventQueue::registerRewindEffectEvent( EventSharedPtr const& pEvent ) 933*cdf0e10cSrcweir { 934*cdf0e10cSrcweir registerEvent( mpRewindEffectEventHandler, 935*cdf0e10cSrcweir pEvent, 936*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addClickHandler, 937*cdf0e10cSrcweir boost::ref(mrMultiplexer), _1, 938*cdf0e10cSrcweir -1.0 /* prio below default */ ) ); 939*cdf0e10cSrcweir } 940*cdf0e10cSrcweir 941*cdf0e10cSrcweir void UserEventQueue::registerShapeDoubleClickEvent( 942*cdf0e10cSrcweir const EventSharedPtr& rEvent, 943*cdf0e10cSrcweir const ShapeSharedPtr& rShape ) 944*cdf0e10cSrcweir { 945*cdf0e10cSrcweir ENSURE_OR_THROW( 946*cdf0e10cSrcweir rEvent, 947*cdf0e10cSrcweir "UserEventQueue::registerShapeDoubleClickEvent(): Invalid event" ); 948*cdf0e10cSrcweir 949*cdf0e10cSrcweir if( !mpShapeDoubleClickEventHandler ) 950*cdf0e10cSrcweir { 951*cdf0e10cSrcweir // create handler 952*cdf0e10cSrcweir mpShapeDoubleClickEventHandler.reset( 953*cdf0e10cSrcweir new ShapeClickEventHandler(mrCursorManager, 954*cdf0e10cSrcweir mrEventQueue) ); 955*cdf0e10cSrcweir 956*cdf0e10cSrcweir // register handler on EventMultiplexer 957*cdf0e10cSrcweir mrMultiplexer.addDoubleClickHandler( mpShapeDoubleClickEventHandler, 958*cdf0e10cSrcweir 1.0 ); 959*cdf0e10cSrcweir mrMultiplexer.addMouseMoveHandler( mpShapeDoubleClickEventHandler, 960*cdf0e10cSrcweir 1.0 ); 961*cdf0e10cSrcweir } 962*cdf0e10cSrcweir 963*cdf0e10cSrcweir mpShapeDoubleClickEventHandler->addEvent( rEvent, rShape ); 964*cdf0e10cSrcweir } 965*cdf0e10cSrcweir 966*cdf0e10cSrcweir void UserEventQueue::registerDoubleClickEvent( const EventSharedPtr& rEvent ) 967*cdf0e10cSrcweir { 968*cdf0e10cSrcweir registerEvent( mpDoubleClickEventHandler, 969*cdf0e10cSrcweir rEvent, 970*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addDoubleClickHandler, 971*cdf0e10cSrcweir boost::ref( mrMultiplexer ), _1, 972*cdf0e10cSrcweir 0.0 /* default prio */ ) ); 973*cdf0e10cSrcweir } 974*cdf0e10cSrcweir 975*cdf0e10cSrcweir void UserEventQueue::registerMouseEnterEvent( const EventSharedPtr& rEvent, 976*cdf0e10cSrcweir const ShapeSharedPtr& rShape ) 977*cdf0e10cSrcweir { 978*cdf0e10cSrcweir registerEvent( mpMouseEnterHandler, 979*cdf0e10cSrcweir rEvent, 980*cdf0e10cSrcweir rShape, 981*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addMouseMoveHandler, 982*cdf0e10cSrcweir boost::ref( mrMultiplexer ), _1, 983*cdf0e10cSrcweir 0.0 /* default prio */ ) ); 984*cdf0e10cSrcweir } 985*cdf0e10cSrcweir 986*cdf0e10cSrcweir void UserEventQueue::registerMouseLeaveEvent( const EventSharedPtr& rEvent, 987*cdf0e10cSrcweir const ShapeSharedPtr& rShape ) 988*cdf0e10cSrcweir { 989*cdf0e10cSrcweir registerEvent( mpMouseLeaveHandler, 990*cdf0e10cSrcweir rEvent, 991*cdf0e10cSrcweir rShape, 992*cdf0e10cSrcweir boost::bind( &EventMultiplexer::addMouseMoveHandler, 993*cdf0e10cSrcweir boost::ref( mrMultiplexer ), _1, 994*cdf0e10cSrcweir 0.0 /* default prio */ ) ); 995*cdf0e10cSrcweir } 996*cdf0e10cSrcweir 997*cdf0e10cSrcweir void UserEventQueue::callSkipEffectEventHandler (void) 998*cdf0e10cSrcweir { 999*cdf0e10cSrcweir ::boost::shared_ptr<SkipEffectEventHandler> pHandler ( 1000*cdf0e10cSrcweir ::boost::dynamic_pointer_cast<SkipEffectEventHandler>(mpSkipEffectEventHandler)); 1001*cdf0e10cSrcweir if (pHandler) 1002*cdf0e10cSrcweir pHandler->skipEffect(); 1003*cdf0e10cSrcweir } 1004*cdf0e10cSrcweir 1005*cdf0e10cSrcweir } // namespace internal 1006*cdf0e10cSrcweir } // namespace presentation 1007*cdf0e10cSrcweir 1008