1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_slideshow.hxx" 30 31 // must be first 32 #include <canvas/debug.hxx> 33 #include <tools/diagnose_ex.h> 34 35 #include <rtl/ref.hxx> 36 #include <cppuhelper/compbase2.hxx> 37 #include <cppuhelper/basemutex.hxx> 38 39 #include <com/sun/star/awt/XMouseListener.hpp> 40 #include <com/sun/star/awt/XMouseMotionListener.hpp> 41 #include <com/sun/star/awt/SystemPointer.hpp> 42 #include <com/sun/star/awt/XWindow.hpp> 43 #include <com/sun/star/awt/MouseButton.hpp> 44 #include <com/sun/star/presentation/XSlideShowView.hpp> 45 46 #include <basegfx/matrix/b2dhommatrix.hxx> 47 #include <basegfx/numeric/ftools.hxx> 48 49 #include "tools.hxx" 50 #include "eventqueue.hxx" 51 #include "eventmultiplexer.hxx" 52 #include "listenercontainer.hxx" 53 #include "delayevent.hxx" 54 #include "unoview.hxx" 55 #include "unoviewcontainer.hxx" 56 57 #include <boost/shared_ptr.hpp> 58 #include <boost/weak_ptr.hpp> 59 #include <boost/function.hpp> 60 #include <boost/noncopyable.hpp> 61 #include <boost/bind.hpp> 62 63 #include <vector> 64 #include <hash_map> 65 #include <algorithm> 66 67 using namespace ::com::sun::star; 68 69 namespace boost 70 { 71 // add operator== for weak_ptr 72 template<typename T> bool operator==( weak_ptr<T> const& rLHS, 73 weak_ptr<T> const& rRHS ) 74 { 75 return !(rLHS<rRHS) && !(rRHS<rLHS); 76 } 77 } 78 79 namespace slideshow { 80 namespace internal { 81 82 template <typename HandlerT> 83 class PrioritizedHandlerEntry 84 { 85 typedef boost::shared_ptr<HandlerT> HandlerSharedPtrT; 86 HandlerSharedPtrT mpHandler; 87 double mnPrio; 88 89 public: 90 PrioritizedHandlerEntry( HandlerSharedPtrT const& pHandler, 91 double nPrio ) : 92 mpHandler(pHandler), 93 mnPrio(nPrio) 94 {} 95 96 HandlerSharedPtrT const& getHandler() const { return mpHandler; } 97 98 /// To sort according to priority 99 bool operator<( PrioritizedHandlerEntry const& rRHS ) const 100 { 101 // reversed order - high prioritized entries 102 // should be at the beginning of the queue 103 return mnPrio > rRHS.mnPrio; 104 } 105 106 /// To permit std::remove in removeHandler template 107 bool operator==( PrioritizedHandlerEntry const& rRHS ) const 108 { 109 // ignore prio, for removal, only the handler ptr matters 110 return mpHandler == rRHS.mpHandler; 111 } 112 }; 113 114 template<typename T> inline T* get_pointer(PrioritizedHandlerEntry<T> const& handler) 115 { 116 return handler.getHandler().get(); 117 } 118 119 120 121 //////////////////////////////////////////////////////////////////////////// 122 123 124 typedef cppu::WeakComponentImplHelper2< 125 awt::XMouseListener, 126 awt::XMouseMotionListener > Listener_UnoBase; 127 128 /** Listener class, to decouple UNO lifetime from EventMultiplexer 129 130 This class gets registered as the XMouse(Motion)Listener on the 131 XSlideViews, and passes on the events to the EventMultiplexer (via 132 EventQueue indirection, to force the events into the main thread) 133 */ 134 class EventMultiplexerListener : private cppu::BaseMutex, 135 public Listener_UnoBase, 136 private ::boost::noncopyable 137 { 138 public: 139 EventMultiplexerListener( EventQueue& rEventQueue, 140 EventMultiplexerImpl& rEventMultiplexer ) : 141 Listener_UnoBase( m_aMutex ), 142 mpEventQueue( &rEventQueue ), 143 mpEventMultiplexer( &rEventMultiplexer ) 144 { 145 } 146 147 // WeakComponentImplHelperBase::disposing 148 virtual void SAL_CALL disposing(); 149 150 private: 151 virtual void SAL_CALL disposing( const lang::EventObject& Source ) 152 throw (uno::RuntimeException); 153 154 // XMouseListener implementation 155 virtual void SAL_CALL mousePressed( const awt::MouseEvent& e ) 156 throw (uno::RuntimeException); 157 virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e ) 158 throw (uno::RuntimeException); 159 virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e ) 160 throw (uno::RuntimeException); 161 virtual void SAL_CALL mouseExited( const awt::MouseEvent& e ) 162 throw (uno::RuntimeException); 163 164 // XMouseMotionListener implementation 165 virtual void SAL_CALL mouseDragged( const awt::MouseEvent& e ) 166 throw (uno::RuntimeException); 167 virtual void SAL_CALL mouseMoved( const awt::MouseEvent& e ) 168 throw (uno::RuntimeException); 169 170 171 EventQueue* mpEventQueue; 172 EventMultiplexerImpl* mpEventMultiplexer; 173 }; 174 175 176 //////////////////////////////////////////////////////////////////////////// 177 178 179 struct EventMultiplexerImpl 180 { 181 EventMultiplexerImpl( EventQueue& rEventQueue, 182 UnoViewContainer const& rViewContainer ) : 183 mrEventQueue(rEventQueue), 184 mrViewContainer(rViewContainer), 185 mxListener( new EventMultiplexerListener(rEventQueue, 186 *this) ), 187 maNextEffectHandlers(), 188 maSlideStartHandlers(), 189 maSlideEndHandlers(), 190 maAnimationStartHandlers(), 191 maAnimationEndHandlers(), 192 maSlideAnimationsEndHandlers(), 193 maAudioStoppedHandlers(), 194 maCommandStopAudioHandlers(), 195 maPauseHandlers(), 196 maViewHandlers(), 197 maViewRepaintHandlers(), 198 maShapeListenerHandlers(), 199 maUserPaintEventHandlers(), 200 maShapeCursorHandlers(), 201 maMouseClickHandlers(), 202 maMouseDoubleClickHandlers(), 203 maMouseMoveHandlers(), 204 maHyperlinkHandlers(), 205 mnTimeout(0.0), 206 mpTickEvent(), 207 mbIsAutoMode(false) 208 {} 209 210 ~EventMultiplexerImpl() 211 { 212 if( mxListener.is() ) 213 mxListener->dispose(); 214 } 215 216 /// Remove all handlers 217 void clear(); 218 219 // actual handler callbacks (get called from the UNO interface 220 // listeners via event queue) 221 void mousePressed( const awt::MouseEvent& e ); 222 void mouseReleased( const awt::MouseEvent& e ); 223 void mouseDragged( const awt::MouseEvent& e ); 224 void mouseMoved( const awt::MouseEvent& e ); 225 226 bool isMouseListenerRegistered() const; 227 228 typedef ThreadUnsafeListenerContainer< 229 PrioritizedHandlerEntry<EventHandler>, 230 std::vector< 231 PrioritizedHandlerEntry<EventHandler> > > ImplNextEffectHandlers; 232 typedef PrioritizedHandlerEntry<MouseEventHandler> ImplMouseHandlerEntry; 233 typedef ThreadUnsafeListenerContainer< 234 ImplMouseHandlerEntry, 235 std::vector<ImplMouseHandlerEntry> > ImplMouseHandlers; 236 typedef ThreadUnsafeListenerContainer< 237 EventHandlerSharedPtr, 238 std::vector<EventHandlerSharedPtr> > ImplEventHandlers; 239 typedef ThreadUnsafeListenerContainer< 240 AnimationEventHandlerSharedPtr, 241 std::vector<AnimationEventHandlerSharedPtr> > ImplAnimationHandlers; 242 typedef ThreadUnsafeListenerContainer< 243 PauseEventHandlerSharedPtr, 244 std::vector<PauseEventHandlerSharedPtr> > ImplPauseHandlers; 245 typedef ThreadUnsafeListenerContainer< 246 ViewEventHandlerWeakPtr, 247 std::vector<ViewEventHandlerWeakPtr> > ImplViewHandlers; 248 typedef ThreadUnsafeListenerContainer< 249 ViewRepaintHandlerSharedPtr, 250 std::vector<ViewRepaintHandlerSharedPtr> > ImplRepaintHandlers; 251 typedef ThreadUnsafeListenerContainer< 252 ShapeListenerEventHandlerSharedPtr, 253 std::vector<ShapeListenerEventHandlerSharedPtr> > ImplShapeListenerHandlers; 254 typedef ThreadUnsafeListenerContainer< 255 UserPaintEventHandlerSharedPtr, 256 std::vector<UserPaintEventHandlerSharedPtr> > ImplUserPaintEventHandlers; 257 typedef ThreadUnsafeListenerContainer< 258 ShapeCursorEventHandlerSharedPtr, 259 std::vector<ShapeCursorEventHandlerSharedPtr> > ImplShapeCursorHandlers; 260 typedef ThreadUnsafeListenerContainer< 261 PrioritizedHandlerEntry<HyperlinkHandler>, 262 std::vector<PrioritizedHandlerEntry<HyperlinkHandler> > > ImplHyperLinkHandlers; 263 264 template <typename XSlideShowViewFunc> 265 void forEachView( XSlideShowViewFunc pViewMethod ); 266 267 UnoViewSharedPtr findUnoView(const uno::Reference< 268 presentation::XSlideShowView>& xView) const; 269 270 template< typename RegisterFunction > 271 void addMouseHandler( ImplMouseHandlers& rHandlerContainer, 272 const MouseEventHandlerSharedPtr& rHandler, 273 double nPriority, 274 RegisterFunction pRegisterListener ); 275 276 bool notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer, 277 AnimationNodeSharedPtr const& rNode ); 278 279 bool notifyMouseHandlers( 280 const ImplMouseHandlers& rQueue, 281 bool (MouseEventHandler::*pHandlerMethod)( 282 const awt::MouseEvent& ), 283 const awt::MouseEvent& e ); 284 285 bool notifyNextEffect(); 286 287 /// Called for automatic nextEffect 288 void tick(); 289 290 /// Schedules a tick event 291 void scheduleTick(); 292 293 /// Schedules tick events, if mbIsAutoMode is true 294 void handleTicks(); 295 296 297 EventQueue& mrEventQueue; 298 UnoViewContainer const& mrViewContainer; 299 ::rtl::Reference< 300 EventMultiplexerListener> mxListener; 301 302 ImplNextEffectHandlers maNextEffectHandlers; 303 ImplEventHandlers maSlideStartHandlers; 304 ImplEventHandlers maSlideEndHandlers; 305 ImplAnimationHandlers maAnimationStartHandlers; 306 ImplAnimationHandlers maAnimationEndHandlers; 307 ImplEventHandlers maSlideAnimationsEndHandlers; 308 ImplAnimationHandlers maAudioStoppedHandlers; 309 ImplAnimationHandlers maCommandStopAudioHandlers; 310 ImplPauseHandlers maPauseHandlers; 311 ImplViewHandlers maViewHandlers; 312 ImplRepaintHandlers maViewRepaintHandlers; 313 ImplShapeListenerHandlers maShapeListenerHandlers; 314 ImplUserPaintEventHandlers maUserPaintEventHandlers; 315 ImplShapeCursorHandlers maShapeCursorHandlers; 316 ImplMouseHandlers maMouseClickHandlers; 317 ImplMouseHandlers maMouseDoubleClickHandlers; 318 ImplMouseHandlers maMouseMoveHandlers; 319 ImplHyperLinkHandlers maHyperlinkHandlers; 320 321 /// automatic next effect mode timeout 322 double mnTimeout; 323 324 /** Holds ptr to optional tick event weakly 325 326 When event queue is cleansed, the next 327 setAutomaticMode(true) call is then able to 328 regenerate the event. 329 */ 330 ::boost::weak_ptr< Event > mpTickEvent; 331 bool mbIsAutoMode; 332 }; 333 334 335 /////////////////////////////////////////////////////////////////////////// 336 337 338 void SAL_CALL EventMultiplexerListener::disposing() 339 { 340 osl::MutexGuard const guard( m_aMutex ); 341 mpEventQueue = NULL; 342 mpEventMultiplexer = NULL; 343 } 344 345 void SAL_CALL EventMultiplexerListener::disposing( 346 const lang::EventObject& /*rSource*/ ) throw (uno::RuntimeException) 347 { 348 // there's no real point in acting on this message - after all, 349 // the event sources are the XSlideShowViews, which must be 350 // explicitely removed from the slideshow via 351 // XSlideShow::removeView(). thus, if a XSlideShowView has 352 // properly removed itself from the slideshow, it will not be 353 // found here. and if it hasn't, there'll be other references at 354 // other places within the slideshow, anyway... 355 } 356 357 void SAL_CALL EventMultiplexerListener::mousePressed( 358 const awt::MouseEvent& e ) throw (uno::RuntimeException) 359 { 360 osl::MutexGuard const guard( m_aMutex ); 361 362 // notify mouse press. Don't call handlers directly, this 363 // might not be the main thread! 364 if( mpEventQueue ) 365 mpEventQueue->addEvent( 366 makeEvent( boost::bind( &EventMultiplexerImpl::mousePressed, 367 mpEventMultiplexer, 368 e ), 369 "EventMultiplexerImpl::mousePressed") ); 370 } 371 372 void SAL_CALL EventMultiplexerListener::mouseReleased( 373 const awt::MouseEvent& e ) throw (uno::RuntimeException) 374 { 375 osl::MutexGuard const guard( m_aMutex ); 376 377 // notify mouse release. Don't call handlers directly, 378 // this might not be the main thread! 379 if( mpEventQueue ) 380 mpEventQueue->addEvent( 381 makeEvent( boost::bind( &EventMultiplexerImpl::mouseReleased, 382 mpEventMultiplexer, 383 e ), 384 "EventMultiplexerImpl::mouseReleased") ); 385 } 386 387 void SAL_CALL EventMultiplexerListener::mouseEntered( 388 const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException) 389 { 390 // not used here 391 } 392 393 void SAL_CALL EventMultiplexerListener::mouseExited( 394 const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException) 395 { 396 // not used here 397 } 398 399 // XMouseMotionListener implementation 400 void SAL_CALL EventMultiplexerListener::mouseDragged( 401 const awt::MouseEvent& e ) throw (uno::RuntimeException) 402 { 403 osl::MutexGuard const guard( m_aMutex ); 404 405 // notify mouse drag. Don't call handlers directly, this 406 // might not be the main thread! 407 if( mpEventQueue ) 408 mpEventQueue->addEvent( 409 makeEvent( boost::bind( &EventMultiplexerImpl::mouseDragged, 410 mpEventMultiplexer, 411 e ), 412 "EventMultiplexerImpl::mouseDragged") ); 413 } 414 415 void SAL_CALL EventMultiplexerListener::mouseMoved( 416 const awt::MouseEvent& e ) throw (uno::RuntimeException) 417 { 418 osl::MutexGuard const guard( m_aMutex ); 419 420 // notify mouse move. Don't call handlers directly, this 421 // might not be the main thread! 422 if( mpEventQueue ) 423 mpEventQueue->addEvent( 424 makeEvent( boost::bind( &EventMultiplexerImpl::mouseMoved, 425 mpEventMultiplexer, 426 e ), 427 "EventMultiplexerImpl::mouseMoved") ); 428 } 429 430 431 /////////////////////////////////////////////////////////////////////////// 432 433 434 bool EventMultiplexerImpl::notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer, 435 AnimationNodeSharedPtr const& rNode ) 436 { 437 return rContainer.applyAll( 438 boost::bind( &AnimationEventHandler::handleAnimationEvent, 439 _1, boost::cref(rNode) ) ); 440 } 441 442 template <typename XSlideShowViewFunc> 443 void EventMultiplexerImpl::forEachView( XSlideShowViewFunc pViewMethod ) 444 { 445 if( pViewMethod ) 446 { 447 // (un)register mouse listener on all views 448 for( UnoViewVector::const_iterator aIter( mrViewContainer.begin() ), 449 aEnd( mrViewContainer.end() ); aIter != aEnd; ++aIter ) 450 { 451 uno::Reference<presentation::XSlideShowView> xView ((*aIter)->getUnoView()); 452 if (xView.is()) 453 { 454 (xView.get()->*pViewMethod)( mxListener.get() ); 455 } 456 else 457 { 458 OSL_ASSERT(xView.is()); 459 } 460 } 461 } 462 } 463 464 UnoViewSharedPtr EventMultiplexerImpl::findUnoView( 465 const uno::Reference<presentation::XSlideShowView>& xView) const 466 { 467 // find view from which the change originated 468 UnoViewVector::const_iterator aIter; 469 const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() ); 470 if( (aIter=std::find_if( mrViewContainer.begin(), 471 aEnd, 472 boost::bind( 473 std::equal_to<uno::Reference<presentation::XSlideShowView> >(), 474 boost::cref( xView ), 475 boost::bind( &UnoView::getUnoView, _1 )))) == aEnd ) 476 { 477 OSL_ENSURE(false, "EventMultiplexer::findUnoView(): unexpected message source" ); 478 return UnoViewSharedPtr(); 479 } 480 481 return *aIter; 482 } 483 484 template< typename RegisterFunction > 485 void EventMultiplexerImpl::addMouseHandler( 486 ImplMouseHandlers& rHandlerContainer, 487 const MouseEventHandlerSharedPtr& rHandler, 488 double nPriority, 489 RegisterFunction pRegisterListener ) 490 { 491 ENSURE_OR_THROW( 492 rHandler, 493 "EventMultiplexer::addMouseHandler(): Invalid handler" ); 494 495 // register mouse listener on all views 496 forEachView( pRegisterListener ); 497 498 // add into sorted container: 499 rHandlerContainer.addSorted( 500 typename ImplMouseHandlers::container_type::value_type( 501 rHandler, 502 nPriority )); 503 } 504 505 bool EventMultiplexerImpl::isMouseListenerRegistered() const 506 { 507 return !(maMouseClickHandlers.isEmpty() && 508 maMouseDoubleClickHandlers.isEmpty()); 509 } 510 511 void EventMultiplexerImpl::tick() 512 { 513 if( !mbIsAutoMode ) 514 return; // this event is just a left-over, ignore 515 516 notifyNextEffect(); 517 518 if( !maNextEffectHandlers.isEmpty() ) 519 { 520 // still handlers left, schedule next timeout 521 // event. Will also set mbIsTickEventOn back to true 522 scheduleTick(); 523 } 524 } 525 526 void EventMultiplexerImpl::scheduleTick() 527 { 528 EventSharedPtr pEvent( 529 makeDelay( boost::bind( &EventMultiplexerImpl::tick, 530 this ), 531 mnTimeout, 532 "EventMultiplexerImpl::tick with delay")); 533 534 // store weak reference to generated event, to notice when 535 // the event queue gets cleansed (we then have to 536 // regenerate the tick event!) 537 mpTickEvent = pEvent; 538 539 // enabled auto mode: simply schedule a timeout event, 540 // which will eventually call our tick() method 541 mrEventQueue.addEventForNextRound( pEvent ); 542 } 543 544 void EventMultiplexerImpl::handleTicks() 545 { 546 if( !mbIsAutoMode ) 547 return; // nothing to do, don't need no ticks 548 549 EventSharedPtr pTickEvent( mpTickEvent.lock() ); 550 if( pTickEvent ) 551 return; // nothing to do, there's already a tick 552 // pending 553 554 // schedule initial tick (which reschedules itself 555 // after that, all by itself) 556 scheduleTick(); 557 } 558 559 560 void EventMultiplexerImpl::clear() 561 { 562 // deregister from all views. 563 if( isMouseListenerRegistered() ) 564 { 565 for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(), 566 aEnd=mrViewContainer.end(); 567 aIter!=aEnd; 568 ++aIter ) 569 { 570 if( (*aIter)->getUnoView().is() ) 571 (*aIter)->getUnoView()->removeMouseListener( mxListener.get() ); 572 } 573 } 574 575 if( !maMouseMoveHandlers.isEmpty() ) 576 { 577 for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(), 578 aEnd=mrViewContainer.end(); 579 aIter!=aEnd; 580 ++aIter ) 581 { 582 if( (*aIter)->getUnoView().is() ) 583 (*aIter)->getUnoView()->removeMouseMotionListener( mxListener.get() ); 584 } 585 } 586 587 // clear all handlers (releases all references) 588 maNextEffectHandlers.clear(); 589 maSlideStartHandlers.clear(); 590 maSlideEndHandlers.clear(); 591 maAnimationStartHandlers.clear(); 592 maAnimationEndHandlers.clear(); 593 maSlideAnimationsEndHandlers.clear(); 594 maAudioStoppedHandlers.clear(); 595 maCommandStopAudioHandlers.clear(); 596 maPauseHandlers.clear(); 597 maViewHandlers.clear(); 598 maViewRepaintHandlers.clear(); 599 maMouseClickHandlers.clear(); 600 maMouseDoubleClickHandlers.clear(); 601 maMouseMoveHandlers.clear(); 602 maHyperlinkHandlers.clear(); 603 mpTickEvent.reset(); 604 } 605 606 // XMouseListener implementation 607 bool EventMultiplexerImpl::notifyMouseHandlers( 608 const ImplMouseHandlers& rQueue, 609 bool (MouseEventHandler::*pHandlerMethod)( const awt::MouseEvent& ), 610 const awt::MouseEvent& e ) 611 { 612 uno::Reference<presentation::XSlideShowView> xView( 613 e.Source, uno::UNO_QUERY ); 614 615 ENSURE_OR_RETURN_FALSE( xView.is(), "EventMultiplexer::notifyHandlers(): " 616 "event source is not an XSlideShowView" ); 617 618 // find corresponding view (to map mouse position into user 619 // coordinate space) 620 UnoViewVector::const_iterator aIter; 621 const UnoViewVector::const_iterator aBegin( mrViewContainer.begin() ); 622 const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() ); 623 if( (aIter=::std::find_if( 624 aBegin, aEnd, 625 boost::bind( std::equal_to< uno::Reference< 626 presentation::XSlideShowView > >(), 627 boost::cref( xView ), 628 boost::bind( &UnoView::getUnoView, _1 ) ) ) ) == aEnd) 629 { 630 ENSURE_OR_RETURN_FALSE( 631 false, "EventMultiplexer::notifyHandlers(): " 632 "event source not found under registered views" ); 633 } 634 635 // convert mouse position to user coordinate space 636 ::basegfx::B2DPoint aPosition( e.X, e.Y ); 637 ::basegfx::B2DHomMatrix aMatrix( (*aIter)->getTransformation() ); 638 if( !aMatrix.invert() ) 639 ENSURE_OR_THROW( false, "EventMultiplexer::notifyHandlers():" 640 " view matrix singular" ); 641 aPosition *= aMatrix; 642 643 awt::MouseEvent aEvent( e ); 644 aEvent.X = ::basegfx::fround( aPosition.getX() ); 645 aEvent.Y = ::basegfx::fround( aPosition.getY() ); 646 647 // fire event on handlers, try in order of precedence. If 648 // one high-priority handler rejects the event 649 // (i.e. returns false), try next handler. 650 return rQueue.apply( 651 boost::bind( 652 pHandlerMethod, 653 boost::bind( 654 &ImplMouseHandlers::container_type::value_type::getHandler, 655 _1 ), 656 aEvent )); 657 } 658 659 void EventMultiplexerImpl::mousePressed( const awt::MouseEvent& e ) 660 { 661 // fire double-click events for every second click 662 sal_Int32 nCurrClickCount = e.ClickCount; 663 while( nCurrClickCount > 1 && 664 notifyMouseHandlers( maMouseDoubleClickHandlers, 665 &MouseEventHandler::handleMousePressed, 666 e )) 667 { 668 nCurrClickCount -= 2; 669 } 670 671 // fire single-click events for all remaining clicks 672 while( nCurrClickCount > 0 && 673 notifyMouseHandlers( maMouseClickHandlers, 674 &MouseEventHandler::handleMousePressed, 675 e )) 676 { 677 --nCurrClickCount; 678 } 679 } 680 681 void EventMultiplexerImpl::mouseReleased( const awt::MouseEvent& e ) 682 { 683 // fire double-click events for every second click 684 sal_Int32 nCurrClickCount = e.ClickCount; 685 while( nCurrClickCount > 1 && 686 notifyMouseHandlers( maMouseDoubleClickHandlers, 687 &MouseEventHandler::handleMouseReleased, 688 e )) 689 { 690 nCurrClickCount -= 2; 691 } 692 693 // fire single-click events for all remaining clicks 694 while( nCurrClickCount > 0 && 695 notifyMouseHandlers( maMouseClickHandlers, 696 &MouseEventHandler::handleMouseReleased, 697 e )) 698 { 699 --nCurrClickCount; 700 } 701 } 702 703 void EventMultiplexerImpl::mouseDragged( const awt::MouseEvent& e ) 704 { 705 notifyMouseHandlers( maMouseMoveHandlers, 706 &MouseEventHandler::handleMouseDragged, 707 e ); 708 } 709 710 void EventMultiplexerImpl::mouseMoved( const awt::MouseEvent& e ) 711 { 712 notifyMouseHandlers( maMouseMoveHandlers, 713 &MouseEventHandler::handleMouseMoved, 714 e ); 715 } 716 717 bool EventMultiplexerImpl::notifyNextEffect() 718 { 719 // fire event on handlers, try in order of precedence. If one 720 // high-priority handler rejects the event (i.e. returns false), 721 // try next handler. 722 return maNextEffectHandlers.apply( 723 boost::bind( 724 &EventHandler::handleEvent, 725 boost::bind( 726 &ImplNextEffectHandlers::container_type::value_type::getHandler, 727 _1 )) ); 728 } 729 730 ////////////////////////////////////////////////////////////////////////// 731 732 733 EventMultiplexer::EventMultiplexer( EventQueue& rEventQueue, 734 UnoViewContainer const& rViewContainer ) : 735 mpImpl( new EventMultiplexerImpl(rEventQueue, rViewContainer) ) 736 { 737 } 738 739 EventMultiplexer::~EventMultiplexer() 740 { 741 // outline because of EventMultiplexerImpl's incomplete type 742 } 743 744 void EventMultiplexer::clear() 745 { 746 mpImpl->clear(); 747 } 748 749 void EventMultiplexer::setAutomaticMode( bool bIsAuto ) 750 { 751 if( bIsAuto == mpImpl->mbIsAutoMode ) 752 return; // no change, nothing to do 753 754 mpImpl->mbIsAutoMode = bIsAuto; 755 756 mpImpl->handleTicks(); 757 } 758 759 bool EventMultiplexer::getAutomaticMode() const 760 { 761 return mpImpl->mbIsAutoMode; 762 } 763 764 void EventMultiplexer::setAutomaticTimeout( double nTimeout ) 765 { 766 mpImpl->mnTimeout = nTimeout; 767 } 768 769 double EventMultiplexer::getAutomaticTimeout() const 770 { 771 return mpImpl->mnTimeout; 772 } 773 774 void EventMultiplexer::addNextEffectHandler( 775 EventHandlerSharedPtr const& rHandler, 776 double nPriority ) 777 { 778 mpImpl->maNextEffectHandlers.addSorted( 779 EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type( 780 rHandler, 781 nPriority) ); 782 783 // Enable tick events, if not done already 784 mpImpl->handleTicks(); 785 } 786 787 void EventMultiplexer::removeNextEffectHandler( 788 const EventHandlerSharedPtr& rHandler ) 789 { 790 mpImpl->maNextEffectHandlers.remove( 791 EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type( 792 rHandler, 793 0.0) ); 794 } 795 796 void EventMultiplexer::addSlideStartHandler( 797 const EventHandlerSharedPtr& rHandler ) 798 { 799 mpImpl->maSlideStartHandlers.add( rHandler ); 800 } 801 802 void EventMultiplexer::removeSlideStartHandler( 803 const EventHandlerSharedPtr& rHandler ) 804 { 805 mpImpl->maSlideStartHandlers.remove( rHandler ); 806 } 807 808 void EventMultiplexer::addSlideEndHandler( 809 const EventHandlerSharedPtr& rHandler ) 810 { 811 mpImpl->maSlideEndHandlers.add( rHandler ); 812 } 813 814 void EventMultiplexer::removeSlideEndHandler( 815 const EventHandlerSharedPtr& rHandler ) 816 { 817 mpImpl->maSlideEndHandlers.remove( rHandler ); 818 } 819 820 void EventMultiplexer::addAnimationStartHandler( 821 const AnimationEventHandlerSharedPtr& rHandler ) 822 { 823 mpImpl->maAnimationStartHandlers.add( rHandler ); 824 } 825 826 void EventMultiplexer::removeAnimationStartHandler( 827 const AnimationEventHandlerSharedPtr& rHandler ) 828 { 829 mpImpl->maAnimationStartHandlers.remove( rHandler ); 830 } 831 832 void EventMultiplexer::addAnimationEndHandler( 833 const AnimationEventHandlerSharedPtr& rHandler ) 834 { 835 mpImpl->maAnimationEndHandlers.add( rHandler ); 836 } 837 838 void EventMultiplexer::removeAnimationEndHandler( 839 const AnimationEventHandlerSharedPtr& rHandler ) 840 { 841 mpImpl->maAnimationEndHandlers.remove( rHandler ); 842 } 843 844 void EventMultiplexer::addSlideAnimationsEndHandler( 845 const EventHandlerSharedPtr& rHandler ) 846 { 847 mpImpl->maSlideAnimationsEndHandlers.add( rHandler ); 848 } 849 850 void EventMultiplexer::removeSlideAnimationsEndHandler( 851 const EventHandlerSharedPtr& rHandler ) 852 { 853 mpImpl->maSlideAnimationsEndHandlers.remove( rHandler ); 854 } 855 856 void EventMultiplexer::addAudioStoppedHandler( 857 const AnimationEventHandlerSharedPtr& rHandler ) 858 { 859 mpImpl->maAudioStoppedHandlers.add( rHandler ); 860 } 861 862 void EventMultiplexer::removeAudioStoppedHandler( 863 const AnimationEventHandlerSharedPtr& rHandler ) 864 { 865 mpImpl->maAudioStoppedHandlers.remove( rHandler ); 866 } 867 868 void EventMultiplexer::addCommandStopAudioHandler( 869 const AnimationEventHandlerSharedPtr& rHandler ) 870 { 871 mpImpl->maCommandStopAudioHandlers.add( rHandler ); 872 } 873 874 void EventMultiplexer::removeCommandStopAudioHandler( 875 const AnimationEventHandlerSharedPtr& rHandler ) 876 { 877 mpImpl->maCommandStopAudioHandlers.remove( rHandler ); 878 } 879 880 void EventMultiplexer::addPauseHandler( 881 const PauseEventHandlerSharedPtr& rHandler ) 882 { 883 mpImpl->maPauseHandlers.add( rHandler ); 884 } 885 886 void EventMultiplexer::removePauseHandler( 887 const PauseEventHandlerSharedPtr& rHandler ) 888 { 889 mpImpl->maPauseHandlers.remove( rHandler ); 890 } 891 892 void EventMultiplexer::addViewHandler( 893 const ViewEventHandlerWeakPtr& rHandler ) 894 { 895 mpImpl->maViewHandlers.add( rHandler ); 896 } 897 898 void EventMultiplexer::removeViewHandler( const ViewEventHandlerWeakPtr& rHandler ) 899 { 900 mpImpl->maViewHandlers.remove( rHandler ); 901 } 902 903 void EventMultiplexer::addViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler ) 904 { 905 mpImpl->maViewRepaintHandlers.add( rHandler ); 906 } 907 908 void EventMultiplexer::removeViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler ) 909 { 910 mpImpl->maViewRepaintHandlers.remove( rHandler ); 911 } 912 913 void EventMultiplexer::addShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler ) 914 { 915 mpImpl->maShapeListenerHandlers.add( rHandler ); 916 } 917 918 void EventMultiplexer::removeShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler ) 919 { 920 mpImpl->maShapeListenerHandlers.remove( rHandler ); 921 } 922 923 void EventMultiplexer::addUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler ) 924 { 925 mpImpl->maUserPaintEventHandlers.add( rHandler ); 926 } 927 928 void EventMultiplexer::removeUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler ) 929 { 930 mpImpl->maUserPaintEventHandlers.remove( rHandler ); 931 } 932 933 void EventMultiplexer::addShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler ) 934 { 935 mpImpl->maShapeCursorHandlers.add( rHandler ); 936 } 937 938 void EventMultiplexer::removeShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler ) 939 { 940 mpImpl->maShapeCursorHandlers.remove( rHandler ); 941 } 942 943 void EventMultiplexer::addClickHandler( 944 const MouseEventHandlerSharedPtr& rHandler, 945 double nPriority ) 946 { 947 mpImpl->addMouseHandler( 948 mpImpl->maMouseClickHandlers, 949 rHandler, 950 nPriority, 951 mpImpl->isMouseListenerRegistered() 952 ? NULL 953 : &presentation::XSlideShowView::addMouseListener ); 954 } 955 956 void EventMultiplexer::removeClickHandler( 957 const MouseEventHandlerSharedPtr& rHandler ) 958 { 959 mpImpl->maMouseClickHandlers.remove( 960 EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type( 961 rHandler, 962 0.0) ); 963 964 if( !mpImpl->isMouseListenerRegistered() ) 965 mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener ); 966 } 967 968 void EventMultiplexer::addDoubleClickHandler( 969 const MouseEventHandlerSharedPtr& rHandler, 970 double nPriority ) 971 { 972 mpImpl->addMouseHandler( 973 mpImpl->maMouseDoubleClickHandlers, 974 rHandler, 975 nPriority, 976 mpImpl->isMouseListenerRegistered() 977 ? NULL 978 : &presentation::XSlideShowView::addMouseListener ); 979 } 980 981 void EventMultiplexer::removeDoubleClickHandler( 982 const MouseEventHandlerSharedPtr& rHandler ) 983 { 984 mpImpl->maMouseDoubleClickHandlers.remove( 985 EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type( 986 rHandler, 987 0.0) ); 988 989 if( !mpImpl->isMouseListenerRegistered() ) 990 mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener ); 991 } 992 993 void EventMultiplexer::addMouseMoveHandler( 994 const MouseEventHandlerSharedPtr& rHandler, 995 double nPriority ) 996 { 997 mpImpl->addMouseHandler( 998 mpImpl->maMouseMoveHandlers, 999 rHandler, 1000 nPriority, 1001 mpImpl->maMouseMoveHandlers.isEmpty() 1002 ? &presentation::XSlideShowView::addMouseMotionListener 1003 : NULL ); 1004 } 1005 1006 void EventMultiplexer::removeMouseMoveHandler( 1007 const MouseEventHandlerSharedPtr& rHandler ) 1008 { 1009 mpImpl->maMouseMoveHandlers.remove( 1010 EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type( 1011 rHandler, 1012 0.0) ); 1013 1014 if( mpImpl->maMouseMoveHandlers.isEmpty() ) 1015 mpImpl->forEachView( 1016 &presentation::XSlideShowView::removeMouseMotionListener ); 1017 } 1018 1019 void EventMultiplexer::addHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler, 1020 double nPriority ) 1021 { 1022 mpImpl->maHyperlinkHandlers.addSorted( 1023 EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type( 1024 rHandler, 1025 nPriority) ); 1026 } 1027 1028 void EventMultiplexer::removeHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler ) 1029 { 1030 mpImpl->maHyperlinkHandlers.remove( 1031 EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type( 1032 rHandler, 1033 0.0) ); 1034 } 1035 1036 bool EventMultiplexer::notifyShapeListenerAdded( 1037 const uno::Reference<presentation::XShapeEventListener>& xListener, 1038 const uno::Reference<drawing::XShape>& xShape ) 1039 { 1040 return mpImpl->maShapeListenerHandlers.applyAll( 1041 boost::bind(&ShapeListenerEventHandler::listenerAdded, 1042 _1, 1043 boost::cref(xListener), 1044 boost::cref(xShape)) ); 1045 } 1046 1047 bool EventMultiplexer::notifyShapeListenerRemoved( 1048 const uno::Reference<presentation::XShapeEventListener>& xListener, 1049 const uno::Reference<drawing::XShape>& xShape ) 1050 { 1051 return mpImpl->maShapeListenerHandlers.applyAll( 1052 boost::bind(&ShapeListenerEventHandler::listenerRemoved, 1053 _1, 1054 boost::cref(xListener), 1055 boost::cref(xShape)) ); 1056 } 1057 1058 bool EventMultiplexer::notifyShapeCursorChange( 1059 const uno::Reference<drawing::XShape>& xShape, 1060 sal_Int16 nPointerShape ) 1061 { 1062 return mpImpl->maShapeCursorHandlers.applyAll( 1063 boost::bind(&ShapeCursorEventHandler::cursorChanged, 1064 _1, 1065 boost::cref(xShape), 1066 nPointerShape)); 1067 } 1068 1069 bool EventMultiplexer::notifyUserPaintColor( RGBColor const& rUserColor ) 1070 { 1071 return mpImpl->maUserPaintEventHandlers.applyAll( 1072 boost::bind(&UserPaintEventHandler::colorChanged, 1073 _1, 1074 boost::cref(rUserColor))); 1075 } 1076 1077 bool EventMultiplexer::notifyUserPaintStrokeWidth( double rUserStrokeWidth ) 1078 { 1079 return mpImpl->maUserPaintEventHandlers.applyAll( 1080 boost::bind(&UserPaintEventHandler::widthChanged, 1081 _1, 1082 rUserStrokeWidth)); 1083 } 1084 1085 bool EventMultiplexer::notifyUserPaintDisabled() 1086 { 1087 return mpImpl->maUserPaintEventHandlers.applyAll( 1088 boost::mem_fn(&UserPaintEventHandler::disable)); 1089 } 1090 1091 bool EventMultiplexer::notifySwitchPenMode(){ 1092 return mpImpl->maUserPaintEventHandlers.applyAll( 1093 boost::mem_fn(&UserPaintEventHandler::switchPenMode)); 1094 } 1095 1096 bool EventMultiplexer::notifySwitchEraserMode(){ 1097 return mpImpl->maUserPaintEventHandlers.applyAll( 1098 boost::mem_fn(&UserPaintEventHandler::switchEraserMode)); 1099 } 1100 1101 //adding erasing all ink features with UserPaintOverlay 1102 bool EventMultiplexer::notifyEraseAllInk( bool const& rEraseAllInk ) 1103 { 1104 return mpImpl->maUserPaintEventHandlers.applyAll( 1105 boost::bind(&UserPaintEventHandler::eraseAllInkChanged, 1106 _1, 1107 boost::cref(rEraseAllInk))); 1108 } 1109 1110 //adding erasing features with UserPaintOverlay 1111 bool EventMultiplexer::notifyEraseInkWidth( sal_Int32 rEraseInkSize ) 1112 { 1113 return mpImpl->maUserPaintEventHandlers.applyAll( 1114 boost::bind(&UserPaintEventHandler::eraseInkWidthChanged, 1115 _1, 1116 boost::cref(rEraseInkSize))); 1117 } 1118 1119 bool EventMultiplexer::notifyNextEffect() 1120 { 1121 return mpImpl->notifyNextEffect(); 1122 } 1123 1124 bool EventMultiplexer::notifySlideStartEvent() 1125 { 1126 return mpImpl->maSlideStartHandlers.applyAll( 1127 boost::mem_fn(&EventHandler::handleEvent) ); 1128 } 1129 1130 bool EventMultiplexer::notifySlideEndEvent() 1131 { 1132 return mpImpl->maSlideEndHandlers.applyAll( 1133 boost::mem_fn(&EventHandler::handleEvent) ); 1134 } 1135 1136 bool EventMultiplexer::notifyAnimationStart( 1137 const AnimationNodeSharedPtr& rNode ) 1138 { 1139 return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationStartHandlers, 1140 rNode ); 1141 } 1142 1143 bool EventMultiplexer::notifyAnimationEnd( 1144 const AnimationNodeSharedPtr& rNode ) 1145 { 1146 return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationEndHandlers, 1147 rNode ); 1148 } 1149 1150 bool EventMultiplexer::notifySlideAnimationsEnd() 1151 { 1152 return mpImpl->maSlideAnimationsEndHandlers.applyAll( 1153 boost::mem_fn(&EventHandler::handleEvent)); 1154 } 1155 1156 bool EventMultiplexer::notifyAudioStopped( 1157 const AnimationNodeSharedPtr& rNode ) 1158 { 1159 return mpImpl->notifyAllAnimationHandlers( 1160 mpImpl->maAudioStoppedHandlers, 1161 rNode ); 1162 } 1163 1164 bool EventMultiplexer::notifyCommandStopAudio( 1165 const AnimationNodeSharedPtr& rNode ) 1166 { 1167 return mpImpl->notifyAllAnimationHandlers( 1168 mpImpl->maCommandStopAudioHandlers, 1169 rNode ); 1170 } 1171 1172 bool EventMultiplexer::notifyPauseMode( bool bPauseShow ) 1173 { 1174 return mpImpl->maPauseHandlers.applyAll( 1175 boost::bind( &PauseEventHandler::handlePause, 1176 _1, bPauseShow )); 1177 } 1178 1179 bool EventMultiplexer::notifyViewAdded( const UnoViewSharedPtr& rView ) 1180 { 1181 ENSURE_OR_THROW( rView, "EventMultiplexer::notifyViewAdded(): Invalid view"); 1182 1183 // register event listener 1184 uno::Reference<presentation::XSlideShowView> const rUnoView( 1185 rView->getUnoView() ); 1186 1187 if( mpImpl->isMouseListenerRegistered() ) 1188 rUnoView->addMouseListener( 1189 mpImpl->mxListener.get() ); 1190 1191 if( !mpImpl->maMouseMoveHandlers.isEmpty() ) 1192 rUnoView->addMouseMotionListener( 1193 mpImpl->mxListener.get() ); 1194 1195 return mpImpl->maViewHandlers.applyAll( 1196 boost::bind( &ViewEventHandler::viewAdded, 1197 _1, 1198 boost::cref(rView) )); 1199 } 1200 1201 bool EventMultiplexer::notifyViewRemoved( const UnoViewSharedPtr& rView ) 1202 { 1203 ENSURE_OR_THROW( rView, 1204 "EventMultiplexer::removeView(): Invalid view" ); 1205 1206 // revoke event listeners 1207 uno::Reference<presentation::XSlideShowView> const rUnoView( 1208 rView->getUnoView() ); 1209 1210 if( mpImpl->isMouseListenerRegistered() ) 1211 rUnoView->removeMouseListener( 1212 mpImpl->mxListener.get() ); 1213 1214 if( !mpImpl->maMouseMoveHandlers.isEmpty() ) 1215 rUnoView->removeMouseMotionListener( 1216 mpImpl->mxListener.get() ); 1217 1218 return mpImpl->maViewHandlers.applyAll( 1219 boost::bind( &ViewEventHandler::viewRemoved, 1220 _1, 1221 boost::cref(rView) )); 1222 } 1223 1224 bool EventMultiplexer::notifyViewChanged( const UnoViewSharedPtr& rView ) 1225 { 1226 return mpImpl->maViewHandlers.applyAll( 1227 boost::bind( &ViewEventHandler::viewChanged, 1228 _1, 1229 boost::cref(rView) )); 1230 } 1231 1232 bool EventMultiplexer::notifyViewChanged( const uno::Reference<presentation::XSlideShowView>& xView ) 1233 { 1234 UnoViewSharedPtr pView( mpImpl->findUnoView(xView) ); 1235 1236 if( !pView ) 1237 return false; // view not registered here 1238 1239 return notifyViewChanged( pView ); 1240 } 1241 1242 bool EventMultiplexer::notifyViewsChanged() 1243 { 1244 return mpImpl->maViewHandlers.applyAll( 1245 boost::mem_fn( &ViewEventHandler::viewsChanged )); 1246 } 1247 1248 bool EventMultiplexer::notifyViewClobbered( 1249 const uno::Reference<presentation::XSlideShowView>& xView ) 1250 { 1251 UnoViewSharedPtr pView( mpImpl->findUnoView(xView) ); 1252 1253 if( !pView ) 1254 return false; // view not registered here 1255 1256 return mpImpl->maViewRepaintHandlers.applyAll( 1257 boost::bind( &ViewRepaintHandler::viewClobbered, 1258 _1, 1259 boost::cref(pView) )); 1260 } 1261 1262 bool EventMultiplexer::notifyHyperlinkClicked( 1263 rtl::OUString const& hyperLink ) 1264 { 1265 return mpImpl->maHyperlinkHandlers.apply( 1266 boost::bind(&HyperlinkHandler::handleHyperlink, 1267 _1, 1268 boost::cref(hyperLink)) ); 1269 } 1270 1271 bool EventMultiplexer::notifySlideTransitionStarted() 1272 { 1273 return true; 1274 } 1275 1276 } // namespace internal 1277 } // namespace presentation 1278 1279