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