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