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