diff options
author | Oliver Bolte <obo@openoffice.org> | 2007-07-17 13:35:58 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2007-07-17 13:35:58 +0000 |
commit | 75129de43a211d2c47fb36eb135e25f73f2fb24c (patch) | |
tree | 937835e22a4d80cc13e0d1cda5edcca362cdec3f /slideshow/source/engine/eventmultiplexer.cxx | |
parent | f33f45ba4837631c9b9562bad6198c24494c9af9 (diff) |
INTEGRATION: CWS presfixes12 (1.12.12); FILE MERGED
2007/05/14 00:55:29 thb 1.12.12.2: #i77154# Moved intrinsic animation notification from global EventMultiplexer to ShapeManager (which is local to each slide). This is a temporary workaround, the proper fix would demote the EventMultiplexer to each Slide
2007/01/29 14:01:53 thb 1.12.12.1: Issue number: #i37778#
Larger slideshow refactoring. Wrote design and coding style manifest,
and adapted the code to actually conform to this. In detail:
- cleaned up ownership/disposable/weak_ptr story. removed hacks and
explicit Disposable implementations, where workaround were available
- removed object mutices, where superfluous
- reworked EventMultiplexer (using templatized listener class now), added
more events. EventMultiplexer now serves as a true blackboard
- reworked directory structure: disjunct parts are now physically separated
into directories, instantiation happens via factories & abstract interfaces
- added CursorManager, to make setting mouse cursor less hackish
- reworked DrawShape, to implement SeparateListener pattern
- reworked IntrinsicAnimationActivity, to avoid cyclic references
- modified hyperlink & shape cursor handling to communicate via
EventMultiplexer
- renamed & cleaned up files (presentation.cxx now named slideshowimpl.cxx,
etc.)
- added first version of the z-order fix to layer/layermanager
- cleaned up include guards and include syntax
Diffstat (limited to 'slideshow/source/engine/eventmultiplexer.cxx')
-rw-r--r-- | slideshow/source/engine/eventmultiplexer.cxx | 1494 |
1 files changed, 735 insertions, 759 deletions
diff --git a/slideshow/source/engine/eventmultiplexer.cxx b/slideshow/source/engine/eventmultiplexer.cxx index a9438a19172d..9a0646e69d30 100644 --- a/slideshow/source/engine/eventmultiplexer.cxx +++ b/slideshow/source/engine/eventmultiplexer.cxx @@ -4,9 +4,9 @@ * * $RCSfile: eventmultiplexer.cxx,v $ * - * $Revision: 1.12 $ + * $Revision: 1.13 $ * - * last change: $Author: kz $ $Date: 2006-12-13 16:56:15 $ + * last change: $Author: obo $ $Date: 2007-07-17 14:35:58 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -39,18 +39,32 @@ // must be first #include <canvas/debug.hxx> +#include <rtl/ref.hxx> +#include <cppuhelper/compbase2.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <com/sun/star/awt/XMouseListener.hpp> +#include <com/sun/star/awt/XMouseMotionListener.hpp> #include <com/sun/star/awt/SystemPointer.hpp> #include <com/sun/star/awt/XWindow.hpp> #include <com/sun/star/awt/MouseButton.hpp> #include <com/sun/star/presentation/XSlideShowView.hpp> + +#include <basegfx/matrix/b2dhommatrix.hxx> #include <basegfx/numeric/ftools.hxx> #include "tools.hxx" +#include "eventqueue.hxx" #include "eventmultiplexer.hxx" +#include "listenercontainer.hxx" #include "delayevent.hxx" +#include "unoview.hxx" +#include "unoviewcontainer.hxx" #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> +#include <boost/function.hpp> +#include <boost/noncopyable.hpp> #include <boost/bind.hpp> #include <vector> @@ -59,240 +73,417 @@ using namespace ::com::sun::star; -/* Implementation of EventMultiplexer class */ +namespace boost +{ + // add operator== for weak_ptr + template<typename T> bool operator==( weak_ptr<T> const& rLHS, + weak_ptr<T> const& rRHS ) + { + return !(rLHS<rRHS) && !(rRHS<rLHS); + } +} namespace slideshow { namespace internal { template <typename HandlerT> -class EventMultiplexer::PrioritizedHandlerEntry +class PrioritizedHandlerEntry { - typedef PrioritizedHandlerEntry<HandlerT> thisT; typedef boost::shared_ptr<HandlerT> HandlerSharedPtrT; - HandlerSharedPtrT m_pHandler; - double m_nPrio; + HandlerSharedPtrT mpHandler; + double mnPrio; public: - PrioritizedHandlerEntry( HandlerSharedPtrT const& pHandler, double nPrio ) - : m_pHandler(pHandler), m_nPrio(nPrio) {} + PrioritizedHandlerEntry( HandlerSharedPtrT const& pHandler, + double nPrio ) : + mpHandler(pHandler), + mnPrio(nPrio) + {} - HandlerSharedPtrT const& getHandler() const { return m_pHandler; } + HandlerSharedPtrT const& getHandler() const { return mpHandler; } /// To sort according to priority - bool operator<( thisT const& rRHS ) const { + bool operator<( PrioritizedHandlerEntry const& rRHS ) const + { // reversed order - high prioritized entries // should be at the beginning of the queue - return m_nPrio > rRHS.m_nPrio; + return mnPrio > rRHS.mnPrio; } - /// To permit ::std::remove in removeHandler template - bool operator==( HandlerSharedPtrT const& rRHS ) const { - return m_pHandler == rRHS; + /// To permit std::remove in removeHandler template + bool operator==( PrioritizedHandlerEntry const& rRHS ) const + { + // ignore prio, for removal, only the handler ptr matters + return mpHandler == rRHS.mpHandler; } }; -/** Notify handlers - - @return true, if at least one handler was called. - */ -template <typename T, typename FuncT> -bool EventMultiplexer::notifyAllHandlers( std::vector< boost::shared_ptr<T> > const& rContainer, - FuncT const& func ) +template<typename T> inline T* get_pointer(PrioritizedHandlerEntry<T> const& handler) { - osl::ClearableMutexGuard guard( m_aMutex ); - // generate a local copy of all handlers, since we have to - // release the object mutex before firing. - std::vector< boost::shared_ptr<T> > const local( rContainer ); - guard.clear(); - // true: at least one handler returned true - // false: not a single handler returned true - return (std::count_if( local.begin(), local.end(), func ) > 0); + return handler.getHandler().get(); } -/** Notify weakly held handlers - @return true, if at least one handler was called. + +//////////////////////////////////////////////////////////////////////////// + + +typedef cppu::WeakComponentImplHelper2< + awt::XMouseListener, + awt::XMouseMotionListener > Listener_UnoBase; + +/** Listener class, to decouple UNO lifetime from EventMultiplexer + + This class gets registered as the XMouse(Motion)Listener on the + XSlideViews, and passes on the events to the EventMultiplexer (via + EventQueue indirection, to force the events into the main thread) */ -template <typename FuncT> -bool EventMultiplexer::notifyAllViewHandlers( FuncT const& func ) +class EventMultiplexerListener : private cppu::BaseMutex, + public Listener_UnoBase, + private ::boost::noncopyable { - osl::ResettableMutexGuard guard( m_aMutex ); +public: + EventMultiplexerListener( EventQueue& rEventQueue, + EventMultiplexerImpl& rEventMultiplexer ) : + Listener_UnoBase( m_aMutex ), + mpEventQueue( &rEventQueue ), + mpEventMultiplexer( &rEventMultiplexer ) + { + } - if( maViewHandlers.empty() ) - return false; + // WeakComponentImplHelperBase::disposing + virtual void SAL_CALL disposing(); - // generate a local copy of all handlers, since we have to - // release the object mutex before firing. - ImplViewHandlers local( maViewHandlers ); - guard.clear(); +private: + virtual void SAL_CALL disposing( const lang::EventObject& Source ) + throw (uno::RuntimeException); - // call handler for each alife container entry - unsigned int nStalePtrs(0); - ImplViewHandlers::const_iterator aCurr( local.begin() ); - ImplViewHandlers::const_iterator const aEnd( local.end() ); - while( aCurr != aEnd ) - { - ViewEventHandlerSharedPtr pCurrHandler( aCurr->lock() ); + // XMouseListener implementation + virtual void SAL_CALL mousePressed( const awt::MouseEvent& e ) + throw (uno::RuntimeException); + virtual void SAL_CALL mouseReleased( const awt::MouseEvent& e ) + throw (uno::RuntimeException); + virtual void SAL_CALL mouseEntered( const awt::MouseEvent& e ) + throw (uno::RuntimeException); + virtual void SAL_CALL mouseExited( const awt::MouseEvent& e ) + throw (uno::RuntimeException); - if( pCurrHandler ) - func( pCurrHandler ); - else - ++nStalePtrs; + // XMouseMotionListener implementation + virtual void SAL_CALL mouseDragged( const awt::MouseEvent& e ) + throw (uno::RuntimeException); + virtual void SAL_CALL mouseMoved( const awt::MouseEvent& e ) + throw (uno::RuntimeException); - ++aCurr; - } - // needs to be two-step, because the notification above happens - // with unlocked mutex. - if( nStalePtrs ) + EventQueue* mpEventQueue; + EventMultiplexerImpl* mpEventMultiplexer; +}; + + +//////////////////////////////////////////////////////////////////////////// + + +struct EventMultiplexerImpl +{ + EventMultiplexerImpl( EventQueue& rEventQueue, + UnoViewContainer const& rViewContainer ) : + mrEventQueue(rEventQueue), + mrViewContainer(rViewContainer), + mxListener( new EventMultiplexerListener(rEventQueue, + *this) ), + maNextEffectHandlers(), + maSlideStartHandlers(), + maSlideEndHandlers(), + maAnimationStartHandlers(), + maAnimationEndHandlers(), + maSlideAnimationsEndHandlers(), + maAudioStoppedHandlers(), + maCommandStopAudioHandlers(), + maPauseHandlers(), + maViewHandlers(), + maViewRepaintHandlers(), + maShapeListenerHandlers(), + maUserPaintEventHandlers(), + maShapeCursorHandlers(), + maMouseClickHandlers(), + maMouseDoubleClickHandlers(), + maMouseMoveHandlers(), + maHyperlinkHandlers(), + mnTimeout(0.0), + mpTickEvent(), + mbIsAutoMode(false) + {} + + ~EventMultiplexerImpl() { - // re-acquire lock. - guard.reset(); + if( mxListener.is() ) + mxListener->dispose(); + } - // prune handlers from stale ones - ImplViewHandlers aAliveHandlers; + /// Remove all handlers + void clear(); + + // actual handler callbacks (get called from the UNO interface + // listeners via event queue) + void mousePressed( const awt::MouseEvent& e ); + void mouseReleased( const awt::MouseEvent& e ); + void mouseDragged( const awt::MouseEvent& e ); + void mouseMoved( const awt::MouseEvent& e ); + + bool isMouseListenerRegistered() const; + + typedef ThreadUnsafeListenerContainer< + PrioritizedHandlerEntry<EventHandler>, + std::vector< + PrioritizedHandlerEntry<EventHandler> > > ImplNextEffectHandlers; + typedef PrioritizedHandlerEntry<MouseEventHandler> ImplMouseHandlerEntry; + typedef ThreadUnsafeListenerContainer< + ImplMouseHandlerEntry, + std::vector<ImplMouseHandlerEntry> > ImplMouseHandlers; + typedef ThreadUnsafeListenerContainer< + EventHandlerSharedPtr, + std::vector<EventHandlerSharedPtr> > ImplEventHandlers; + typedef ThreadUnsafeListenerContainer< + AnimationEventHandlerSharedPtr, + std::vector<AnimationEventHandlerSharedPtr> > ImplAnimationHandlers; + typedef ThreadUnsafeListenerContainer< + PauseEventHandlerSharedPtr, + std::vector<PauseEventHandlerSharedPtr> > ImplPauseHandlers; + typedef ThreadUnsafeListenerContainer< + ViewEventHandlerWeakPtr, + std::vector<ViewEventHandlerWeakPtr> > ImplViewHandlers; + typedef ThreadUnsafeListenerContainer< + ViewRepaintHandlerSharedPtr, + std::vector<ViewRepaintHandlerSharedPtr> > ImplRepaintHandlers; + typedef ThreadUnsafeListenerContainer< + ShapeListenerEventHandlerSharedPtr, + std::vector<ShapeListenerEventHandlerSharedPtr> > ImplShapeListenerHandlers; + typedef ThreadUnsafeListenerContainer< + UserPaintEventHandlerSharedPtr, + std::vector<UserPaintEventHandlerSharedPtr> > ImplUserPaintEventHandlers; + typedef ThreadUnsafeListenerContainer< + ShapeCursorEventHandlerSharedPtr, + std::vector<ShapeCursorEventHandlerSharedPtr> > ImplShapeCursorHandlers; + typedef ThreadUnsafeListenerContainer< + PrioritizedHandlerEntry<HyperlinkHandler>, + std::vector< + PrioritizedHandlerEntry<HyperlinkHandler> > > ImplHyperLinkHandlers; + + template <typename XSlideShowViewFunc> + void forEachView( XSlideShowViewFunc pViewMethod ); + + UnoViewSharedPtr findUnoView(const uno::Reference< + presentation::XSlideShowView>& xView) const; + + template< typename RegisterFunction > + void addMouseHandler( ImplMouseHandlers& rHandlerContainer, + const MouseEventHandlerSharedPtr& rHandler, + double nPriority, + RegisterFunction pRegisterListener ); + + bool notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer, + AnimationNodeSharedPtr const& rNode ); + + bool notifyMouseHandlers( + const ImplMouseHandlers& rQueue, + bool (MouseEventHandler::*pHandlerMethod)( + const awt::MouseEvent& ), + const awt::MouseEvent& e ); + + bool notifyNextEffect(); + + /// Called for automatic nextEffect + void tick(); + + /// Schedules a tick event + void scheduleTick(); + + /// Schedules tick events, if mbIsAutoMode is true + void handleTicks(); + + + EventQueue& mrEventQueue; + UnoViewContainer const& mrViewContainer; + ::rtl::Reference< + EventMultiplexerListener> mxListener; + + ImplNextEffectHandlers maNextEffectHandlers; + ImplEventHandlers maSlideStartHandlers; + ImplEventHandlers maSlideEndHandlers; + ImplAnimationHandlers maAnimationStartHandlers; + ImplAnimationHandlers maAnimationEndHandlers; + ImplEventHandlers maSlideAnimationsEndHandlers; + ImplAnimationHandlers maAudioStoppedHandlers; + ImplAnimationHandlers maCommandStopAudioHandlers; + ImplPauseHandlers maPauseHandlers; + ImplViewHandlers maViewHandlers; + ImplRepaintHandlers maViewRepaintHandlers; + ImplShapeListenerHandlers maShapeListenerHandlers; + ImplUserPaintEventHandlers maUserPaintEventHandlers; + ImplShapeCursorHandlers maShapeCursorHandlers; + ImplMouseHandlers maMouseClickHandlers; + ImplMouseHandlers maMouseDoubleClickHandlers; + ImplMouseHandlers maMouseMoveHandlers; + ImplHyperLinkHandlers maHyperlinkHandlers; + + /// automatic next effect mode timeout + double mnTimeout; + + /** Holds ptr to optional tick event weakly + + When event queue is cleansed, the next + setAutomaticMode(true) call is then able to + regenerate the event. + */ + ::boost::weak_ptr< Event > mpTickEvent; + bool mbIsAutoMode; +}; - ImplViewHandlers::const_iterator aCurrHandler( maViewHandlers.begin() ); - ImplViewHandlers::const_iterator const aEndHandler( maViewHandlers.end() ); - while( aCurrHandler != aEndHandler ) - { - ViewEventHandlerSharedPtr pCurrHandler( aCurrHandler->lock() ); - if( pCurrHandler ) - aAliveHandlers.push_back( *aCurrHandler ); +/////////////////////////////////////////////////////////////////////////// - ++aCurrHandler; - } - const bool bRet( maViewHandlers.size() > nStalePtrs ); - std::swap(aAliveHandlers, maViewHandlers); - return bRet; - } +void SAL_CALL EventMultiplexerListener::disposing() +{ + osl::MutexGuard const guard( m_aMutex ); + mpEventQueue = NULL; + mpEventMultiplexer = NULL; +} - // at least one handler was called. - return true; +void SAL_CALL EventMultiplexerListener::disposing( + const lang::EventObject& /*rSource*/ ) throw (uno::RuntimeException) +{ + // there's no real point in acting on this message - after all, + // the event sources are the XSlideShowViews, which must be + // explicitely removed from the slideshow via + // XSlideShow::removeView(). thus, if a XSlideShowView has + // properly removed itself from the slideshow, it will not be + // found here. and if it hasn't, there'll be other references at + // other places within the slideshow, anyway... } -template <typename ContainerT, typename FuncT> -bool EventMultiplexer::notifySingleHandler( ContainerT const& rContainer, - FuncT const& func, - bool bOperateOnCopy ) +void SAL_CALL EventMultiplexerListener::mousePressed( + const awt::MouseEvent& e ) throw (uno::RuntimeException) { - // fire event on handlers, try in order of precedence. If - // one high-priority handler rejects the event - // (i.e. returns false), try next handler. + osl::MutexGuard const guard( m_aMutex ); - if (bOperateOnCopy) { - osl::ClearableMutexGuard guard( m_aMutex ); - // generate a local copy of all handlers, since we have to - // release the object mutex before firing. - ContainerT const localHandlers( rContainer ); - guard.clear(); - typename ContainerT::const_iterator const iEnd( localHandlers.end() ); - // true: a handler in this queue processed the event - // false: no handler in this queue finally processed the event - return (std::find_if( localHandlers.begin(), iEnd, func ) != iEnd); - } - else - { - typename ContainerT::const_iterator const iEnd( rContainer.end() ); - // true: a handler in this queue processed the event - // false: no handler in this queue finally processed the event - return (std::find_if( rContainer.begin(), iEnd, func ) != iEnd); - } + // notify mouse press. Don't call handlers directly, this + // might not be the main thread! + if( mpEventQueue ) + mpEventQueue->addEvent( + makeEvent( boost::bind( &EventMultiplexerImpl::mousePressed, + mpEventMultiplexer, + e ) ) ); } -template <typename ContainerT, typename HandlerT> -void EventMultiplexer::addHandler( ContainerT & rContainer, - boost::shared_ptr<HandlerT> const& pHandler ) +void SAL_CALL EventMultiplexerListener::mouseReleased( + const awt::MouseEvent& e ) throw (uno::RuntimeException) { - ENSURE_AND_THROW( - pHandler, - "EventMultiplexer::addHandler(): Invalid handler" ); - osl::MutexGuard const guard( m_aMutex ); - rContainer.push_back( pHandler ); + + // notify mouse release. Don't call handlers directly, + // this might not be the main thread! + if( mpEventQueue ) + mpEventQueue->addEvent( + makeEvent( boost::bind( &EventMultiplexerImpl::mouseReleased, + mpEventMultiplexer, + e ) ) ); } -template <typename ContainerT, typename HandlerT> -void EventMultiplexer::addHandler( ContainerT & rContainer, - HandlerT const& pHandler ) +void SAL_CALL EventMultiplexerListener::mouseEntered( + const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException) { - osl::MutexGuard const guard( m_aMutex ); - rContainer.push_back( pHandler ); + // not used here } -template <typename ContainerT, typename HandlerT> -void EventMultiplexer::addPrioritizedHandler( - ContainerT & rContainer, - boost::shared_ptr<HandlerT> const& pHandler, - double nPriority ) +void SAL_CALL EventMultiplexerListener::mouseExited( + const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException) { - ENSURE_AND_THROW( - pHandler, - "EventMultiplexer::addHandler(): Invalid handler" ); + // not used here +} +// XMouseMotionListener implementation +void SAL_CALL EventMultiplexerListener::mouseDragged( + const awt::MouseEvent& e ) throw (uno::RuntimeException) +{ osl::MutexGuard const guard( m_aMutex ); - // insert into queue (not sorted yet) - rContainer.push_back( typename ContainerT::value_type( pHandler, - nPriority ) ); - if (rContainer.size() > 1) { - // element was inserted, but now we have to keep the - // entries sorted - std::inplace_merge( - rContainer.begin(), rContainer.end() - 1, rContainer.end() ); - } - // no need to call inplace_merge otherwise, added - // entry is the only one on the heap. + + // notify mouse drag. Don't call handlers directly, this + // might not be the main thread! + if( mpEventQueue ) + mpEventQueue->addEvent( + makeEvent( boost::bind( &EventMultiplexerImpl::mouseDragged, + mpEventMultiplexer, + e )) ); } -template< typename Container, typename Handler > -void EventMultiplexer::removeHandler( - Container & rContainer, - const ::boost::shared_ptr<Handler>& rHandler ) +void SAL_CALL EventMultiplexerListener::mouseMoved( + const awt::MouseEvent& e ) throw (uno::RuntimeException) { - ::osl::MutexGuard aGuard( m_aMutex ); - - ENSURE_AND_THROW( - rHandler, - "EventMultiplexer::removeHandler(): Invalid handler" ); + osl::MutexGuard const guard( m_aMutex ); - const typename Container::iterator aEnd( rContainer.end() ); - rContainer.erase( ::std::remove(rContainer.begin(), aEnd, rHandler), aEnd ); + // notify mouse move. Don't call handlers directly, this + // might not be the main thread! + if( mpEventQueue ) + mpEventQueue->addEvent( + makeEvent( boost::bind( &EventMultiplexerImpl::mouseMoved, + mpEventMultiplexer, + e )) ); } -template< typename Container, typename Handler > -void EventMultiplexer::removeHandler( - Container & rContainer, - const Handler& rHandler ) -{ - ::osl::MutexGuard aGuard( m_aMutex ); - const typename Container::iterator aEnd( rContainer.end() ); - rContainer.erase( ::std::remove(rContainer.begin(), aEnd, rHandler), aEnd ); +/////////////////////////////////////////////////////////////////////////// + + +bool EventMultiplexerImpl::notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer, + AnimationNodeSharedPtr const& rNode ) +{ + return rContainer.applyAll( + boost::bind( &AnimationEventHandler::handleAnimationEvent, + _1, boost::cref(rNode) ) ); } template <typename XSlideShowViewFunc> -void EventMultiplexer::forEachView( XSlideShowViewFunc pViewMethod ) +void EventMultiplexerImpl::forEachView( XSlideShowViewFunc pViewMethod ) { - if (pViewMethod) { + if( pViewMethod ) + { // (un)register mouse listener on all views - for( UnoViewVector::const_iterator aIter( maViewContainer.begin() ), - aEnd( maViewContainer.end() ); aIter != aEnd; ++aIter ) { - ((*aIter)->getUnoView().get()->*pViewMethod)( this ); + for( UnoViewVector::const_iterator aIter( mrViewContainer.begin() ), + aEnd( mrViewContainer.end() ); aIter != aEnd; ++aIter ) + { + ((*aIter)->getUnoView().get()->*pViewMethod)( mxListener.get() ); } } } +UnoViewSharedPtr EventMultiplexerImpl::findUnoView( + const uno::Reference<presentation::XSlideShowView>& xView) const +{ + // find view from which the change originated + UnoViewVector::const_iterator aIter; + const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() ); + if( (aIter=std::find_if( mrViewContainer.begin(), + aEnd, + boost::bind( + std::equal_to<uno::Reference<presentation::XSlideShowView> >(), + boost::cref( xView ), + boost::bind( &UnoView::getUnoView, _1 )))) == aEnd ) + { + OSL_ENSURE(false, "EventMultiplexer::findUnoView(): unexpected message source" ); + return UnoViewSharedPtr(); + } + + return *aIter; +} + template< typename RegisterFunction > -void EventMultiplexer::addMouseHandler( - ImplMouseHandlers& rHandlerContainer, +void EventMultiplexerImpl::addMouseHandler( + ImplMouseHandlers& rHandlerContainer, const MouseEventHandlerSharedPtr& rHandler, - double nPriority, - RegisterFunction pRegisterListener ) + double nPriority, + RegisterFunction pRegisterListener ) { - ::osl::MutexGuard aGuard( m_aMutex ); - ENSURE_AND_THROW( rHandler, "EventMultiplexer::addMouseHandler(): Invalid handler" ); @@ -300,26 +491,27 @@ void EventMultiplexer::addMouseHandler( // register mouse listener on all views forEachView( pRegisterListener ); - // sort into container: - addPrioritizedHandler( rHandlerContainer, rHandler, nPriority ); + // add into sorted container: + rHandlerContainer.addSorted( + typename ImplMouseHandlers::container_type::value_type( + rHandler, + nPriority )); } -bool EventMultiplexer::isMouseListenerRegistered() const +bool EventMultiplexerImpl::isMouseListenerRegistered() const { - return !(maMouseClickHandlers.empty() && - maMouseDoubleClickHandlers.empty()); + return !(maMouseClickHandlers.isEmpty() && + maMouseDoubleClickHandlers.isEmpty()); } -void EventMultiplexer::tick() +void EventMultiplexerImpl::tick() { - ::osl::MutexGuard aGuard( m_aMutex ); - if( !mbIsAutoMode ) return; // this event is just a left-over, ignore notifyNextEffect(); - if( !maNextEffectHandlers.empty() ) + if( !maNextEffectHandlers.isEmpty() ) { // still handlers left, schedule next timeout // event. Will also set mbIsTickEventOn back to true @@ -327,13 +519,12 @@ void EventMultiplexer::tick() } } -void EventMultiplexer::scheduleTick() +void EventMultiplexerImpl::scheduleTick() { - // TODO(Q3): make robust (no boost::ref()) when - // get_pointer(uno::Ref...) is available EventSharedPtr pEvent( - makeDelay( boost::bind( &EventMultiplexer::tick, this ), - mnTimeout ) ); + makeDelay( boost::bind( &EventMultiplexerImpl::tick, + this ), + mnTimeout )); // store weak reference to generated event, to notice when // the event queue gets cleansed (we then have to @@ -345,7 +536,7 @@ void EventMultiplexer::scheduleTick() mrEventQueue.addEventForNextRound( pEvent ); } -void EventMultiplexer::handleTicks() +void EventMultiplexerImpl::handleTicks() { if( !mbIsAutoMode ) return; // nothing to do, don't need no ticks @@ -353,46 +544,42 @@ void EventMultiplexer::handleTicks() EventSharedPtr pTickEvent( mpTickEvent.lock() ); if( pTickEvent ) return; // nothing to do, there's already a tick - // pending + // pending // schedule initial tick (which reschedules itself // after that, all by itself) scheduleTick(); } -void EventMultiplexer::implSetMouseCursor( sal_Int16 nCursor ) const -{ - // change all views to the requested cursor ID - std::for_each( maViewContainer.begin(), maViewContainer.end(), - boost::bind( &View::setMouseCursor, _1, nCursor ) ); -} -void EventMultiplexer::clear() +void EventMultiplexerImpl::clear() { - ::osl::MutexGuard aGuard( m_aMutex ); - // deregister from all views. if( isMouseListenerRegistered() ) { - for( UnoViewVector::const_iterator aIter=maViewContainer.begin(), aEnd=maViewContainer.end(); + for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(), + aEnd=mrViewContainer.end(); aIter!=aEnd; ++aIter ) { - (*aIter)->getUnoView()->removeMouseListener( this ); + (*aIter)->getUnoView()->removeMouseListener( + mxListener.get() ); } } - if( !maMouseMoveHandlers.empty() ) + if( !maMouseMoveHandlers.isEmpty() ) { - for( UnoViewVector::const_iterator aIter=maViewContainer.begin(), aEnd=maViewContainer.end(); + for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(), + aEnd=mrViewContainer.end(); aIter!=aEnd; ++aIter ) { - (*aIter)->getUnoView()->removeMouseMotionListener( this ); + (*aIter)->getUnoView()->removeMouseMotionListener( + mxListener.get() ); } } - // release all references + // clear all handlers (releases all references) maNextEffectHandlers.clear(); maSlideStartHandlers.clear(); maSlideEndHandlers.clear(); @@ -403,299 +590,360 @@ void EventMultiplexer::clear() maCommandStopAudioHandlers.clear(); maPauseHandlers.clear(); maViewHandlers.clear(); + maViewRepaintHandlers.clear(); maMouseClickHandlers.clear(); maMouseDoubleClickHandlers.clear(); maMouseMoveHandlers.clear(); maHyperlinkHandlers.clear(); - mpLayerManager.reset(); + mpTickEvent.reset(); } -void EventMultiplexer::setMouseCursor( sal_Int16 nCursor ) +// XMouseListener implementation +bool EventMultiplexerImpl::notifyMouseHandlers( + const ImplMouseHandlers& rQueue, + bool (MouseEventHandler::*pHandlerMethod)( const awt::MouseEvent& ), + const awt::MouseEvent& e ) { - ::osl::MutexGuard aGuard( m_aMutex ); + uno::Reference<presentation::XSlideShowView> xView( + e.Source, uno::UNO_QUERY ); - mnMouseCursor = nCursor; + ENSURE_AND_RETURN( xView.is(), "EventMultiplexer::notifyHandlers(): " + "event source is not an XSlideShowView" ); - implSetMouseCursor( mnMouseCursor ); -} + // find corresponding view (to map mouse position into user + // coordinate space) + UnoViewVector::const_iterator aIter; + const UnoViewVector::const_iterator aBegin( mrViewContainer.begin() ); + const UnoViewVector::const_iterator aEnd ( mrViewContainer.end() ); + if( (aIter=::std::find_if( + aBegin, aEnd, + boost::bind( std::equal_to< uno::Reference< + presentation::XSlideShowView > >(), + boost::cref( xView ), + boost::bind( &UnoView::getUnoView, _1 ) ) ) ) == aEnd) + { + ENSURE_AND_RETURN( + false, "EventMultiplexer::notifyHandlers(): " + "event source not found under registered views" ); + } -void EventMultiplexer::setVolatileMouseCursor( sal_Int16 nCursor ) -{ - ::osl::MutexGuard aGuard( m_aMutex ); + // convert mouse position to user coordinate space + ::basegfx::B2DPoint aPosition( e.X, e.Y ); + ::basegfx::B2DHomMatrix aMatrix( (*aIter)->getTransformation() ); + if( !aMatrix.invert() ) + ENSURE_AND_THROW( false, "EventMultiplexer::notifyHandlers():" + " view matrix singular" ); + aPosition *= aMatrix; - // only change, if volatile cursor is not already - // set. This effectively prioritizes handlers with the - // highest priority (otherwise, the handler with the - // lowest prio would determine the mouse cursor - - // unwanted). - if( mnVolatileMouseCursor == -1 ) - mnVolatileMouseCursor = nCursor; -} + awt::MouseEvent aEvent( e ); + aEvent.X = ::basegfx::fround( aPosition.getX() ); + aEvent.Y = ::basegfx::fround( aPosition.getY() ); -void EventMultiplexer::setLayerManager( - const LayerManagerSharedPtr& rMgr ) -{ - mpLayerManager = rMgr; + // fire event on handlers, try in order of precedence. If + // one high-priority handler rejects the event + // (i.e. returns false), try next handler. + return rQueue.apply( + boost::bind( + pHandlerMethod, + boost::bind( + &ImplMouseHandlers::container_type::value_type::getHandler, + _1 ), + aEvent )); } -void EventMultiplexer::updateScreenContent( const UnoViewSharedPtr& rView, - bool bForceUpdate ) +void EventMultiplexerImpl::mousePressed( const awt::MouseEvent& e ) { - const bool bLayerUpdate( mpLayerManager && - mpLayerManager->isUpdatePending() ); + // fire double-click events for every second click + sal_Int32 nCurrClickCount = e.ClickCount; + while( nCurrClickCount > 1 && + notifyMouseHandlers( maMouseDoubleClickHandlers, + &MouseEventHandler::handleMousePressed, + e )) + { + nCurrClickCount -= 2; + } - // perform screen update (either if we're forced to do it, - // or if the layer manager signals that it needs one). - if( bForceUpdate || bLayerUpdate ) + // fire single-click events for all remaining clicks + while( nCurrClickCount > 0 && + notifyMouseHandlers( maMouseClickHandlers, + &MouseEventHandler::handleMousePressed, + e )) { - // call update() on the registered - // LayerManager. This will only update the - // backbuffer, not flush anything to screen - if( bLayerUpdate ) - { - mpLayerManager->update(); - - // call updateScreen() on all registered views (which will - // copy the backbuffers to the front). This is because - // LayerManager::update() updated all views. - std::for_each( maViewContainer.begin(), - maViewContainer.end(), - ::boost::mem_fn( &View::updateScreen ) ); - } - else - { - // selectively only update affected view - rView->updateScreen(); - } + --nCurrClickCount; } } -void EventMultiplexer::updateScreenContent( bool bForceUpdate ) +void EventMultiplexerImpl::mouseReleased( const awt::MouseEvent& e ) { - const bool bLayerUpdate( mpLayerManager && - mpLayerManager->isUpdatePending() ); + // fire double-click events for every second click + sal_Int32 nCurrClickCount = e.ClickCount; + while( nCurrClickCount > 1 && + notifyMouseHandlers( maMouseDoubleClickHandlers, + &MouseEventHandler::handleMouseReleased, + e )) + { + nCurrClickCount -= 2; + } - // perform screen update (either if we're forced to do it, - // or if the layer manager signals that it needs one). - if( bForceUpdate || bLayerUpdate ) + // fire single-click events for all remaining clicks + while( nCurrClickCount > 0 && + notifyMouseHandlers( maMouseClickHandlers, + &MouseEventHandler::handleMouseReleased, + e )) { - // call update() on the registered - // LayerManager. This will only update the - // backbuffer, not flush anything to screen - if( bLayerUpdate ) - mpLayerManager->update(); - - // call updateScreen() on all registered views (which - // will copy the backbuffers to the front). Do NOT use - // LayerManager::updateScreen(), we might need screen - // updates independent from a valid LayerManager! - ::std::for_each( maViewContainer.begin(), - maViewContainer.end(), - ::boost::mem_fn( &View::updateScreen ) ); + --nCurrClickCount; } } -void EventMultiplexer::setAutomaticMode( bool bIsAuto ) +void EventMultiplexerImpl::mouseDragged( const awt::MouseEvent& e ) +{ + notifyMouseHandlers( maMouseMoveHandlers, + &MouseEventHandler::handleMouseDragged, + e ); +} + +void EventMultiplexerImpl::mouseMoved( const awt::MouseEvent& e ) +{ + notifyMouseHandlers( maMouseMoveHandlers, + &MouseEventHandler::handleMouseMoved, + e ); +} + +bool EventMultiplexerImpl::notifyNextEffect() +{ + // fire event on handlers, try in order of precedence. If one + // high-priority handler rejects the event (i.e. returns false), + // try next handler. + return maNextEffectHandlers.apply( + boost::bind( + &EventHandler::handleEvent, + boost::bind( + &ImplNextEffectHandlers::container_type::value_type::getHandler, + _1 )) ); +} + +////////////////////////////////////////////////////////////////////////// + + +EventMultiplexer::EventMultiplexer( EventQueue& rEventQueue, + UnoViewContainer const& rViewContainer ) : + mpImpl( new EventMultiplexerImpl(rEventQueue, rViewContainer) ) +{ +} + +EventMultiplexer::~EventMultiplexer() +{ + // outline because of EventMultiplexerImpl's incomplete type +} + +void EventMultiplexer::clear() { - ::osl::MutexGuard aGuard( m_aMutex ); + mpImpl->clear(); +} - if( bIsAuto == mbIsAutoMode ) +void EventMultiplexer::setAutomaticMode( bool bIsAuto ) +{ + if( bIsAuto == mpImpl->mbIsAutoMode ) return; // no change, nothing to do - mbIsAutoMode = bIsAuto; + mpImpl->mbIsAutoMode = bIsAuto; - handleTicks(); + mpImpl->handleTicks(); } bool EventMultiplexer::getAutomaticMode() const { - ::osl::MutexGuard aGuard( m_aMutex ); - - return mbIsAutoMode; + return mpImpl->mbIsAutoMode; } void EventMultiplexer::setAutomaticTimeout( double nTimeout ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - mnTimeout = nTimeout; + mpImpl->mnTimeout = nTimeout; } double EventMultiplexer::getAutomaticTimeout() const { - ::osl::MutexGuard aGuard( m_aMutex ); - - return mnTimeout; + return mpImpl->mnTimeout; } void EventMultiplexer::addNextEffectHandler( EventHandlerSharedPtr const& rHandler, double nPriority ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addPrioritizedHandler( maNextEffectHandlers, rHandler, nPriority ); + mpImpl->maNextEffectHandlers.addSorted( + EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type( + rHandler, + nPriority) ); // Enable tick events, if not done already - handleTicks(); + mpImpl->handleTicks(); } void EventMultiplexer::removeNextEffectHandler( const EventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maNextEffectHandlers, rHandler ); + mpImpl->maNextEffectHandlers.remove( + EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type( + rHandler, + 0.0) ); } void EventMultiplexer::addSlideStartHandler( const EventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addHandler( maSlideStartHandlers, rHandler ); + mpImpl->maSlideStartHandlers.add( rHandler ); } void EventMultiplexer::removeSlideStartHandler( const EventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maSlideStartHandlers, rHandler ); + mpImpl->maSlideStartHandlers.remove( rHandler ); } void EventMultiplexer::addSlideEndHandler( const EventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addHandler( maSlideEndHandlers, rHandler ); + mpImpl->maSlideEndHandlers.add( rHandler ); } void EventMultiplexer::removeSlideEndHandler( const EventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maSlideEndHandlers, rHandler ); + mpImpl->maSlideEndHandlers.remove( rHandler ); } void EventMultiplexer::addAnimationStartHandler( const AnimationEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addHandler( maAnimationStartHandlers, rHandler ); + mpImpl->maAnimationStartHandlers.add( rHandler ); } void EventMultiplexer::removeAnimationStartHandler( const AnimationEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maAnimationStartHandlers, rHandler ); + mpImpl->maAnimationStartHandlers.remove( rHandler ); } void EventMultiplexer::addAnimationEndHandler( const AnimationEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addHandler( maAnimationEndHandlers, rHandler ); + mpImpl->maAnimationEndHandlers.add( rHandler ); } void EventMultiplexer::removeAnimationEndHandler( const AnimationEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maAnimationEndHandlers, rHandler ); + mpImpl->maAnimationEndHandlers.remove( rHandler ); } void EventMultiplexer::addSlideAnimationsEndHandler( const EventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addHandler( maSlideAnimationsEndHandlers, rHandler ); + mpImpl->maSlideAnimationsEndHandlers.add( rHandler ); } void EventMultiplexer::removeSlideAnimationsEndHandler( const EventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maSlideAnimationsEndHandlers, rHandler ); + mpImpl->maSlideAnimationsEndHandlers.remove( rHandler ); } void EventMultiplexer::addAudioStoppedHandler( const AnimationEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addHandler( maAudioStoppedHandlers, rHandler ); + mpImpl->maAudioStoppedHandlers.add( rHandler ); } void EventMultiplexer::removeAudioStoppedHandler( const AnimationEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maAudioStoppedHandlers, rHandler ); + mpImpl->maAudioStoppedHandlers.remove( rHandler ); } void EventMultiplexer::addCommandStopAudioHandler( const AnimationEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addHandler( maCommandStopAudioHandlers, rHandler ); + mpImpl->maCommandStopAudioHandlers.add( rHandler ); } void EventMultiplexer::removeCommandStopAudioHandler( const AnimationEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maCommandStopAudioHandlers, rHandler ); + mpImpl->maCommandStopAudioHandlers.remove( rHandler ); } void EventMultiplexer::addPauseHandler( const PauseEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addHandler( maPauseHandlers, rHandler ); + mpImpl->maPauseHandlers.add( rHandler ); } void EventMultiplexer::removePauseHandler( const PauseEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maPauseHandlers, rHandler ); + mpImpl->maPauseHandlers.remove( rHandler ); } void EventMultiplexer::addViewHandler( const ViewEventHandlerWeakPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); + mpImpl->maViewHandlers.add( rHandler ); +} + +void EventMultiplexer::removeViewHandler( const ViewEventHandlerWeakPtr& rHandler ) +{ + mpImpl->maViewHandlers.remove( rHandler ); +} + +void EventMultiplexer::addViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler ) +{ + mpImpl->maViewRepaintHandlers.add( rHandler ); +} + +void EventMultiplexer::removeViewRepaintHandler( const ViewRepaintHandlerSharedPtr& rHandler ) +{ + mpImpl->maViewRepaintHandlers.remove( rHandler ); +} + +void EventMultiplexer::addShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler ) +{ + mpImpl->maShapeListenerHandlers.add( rHandler ); +} - // TODO(Q1): Maybe prune vector even here, some times... - addHandler( maViewHandlers, rHandler ); +void EventMultiplexer::removeShapeListenerHandler( const ShapeListenerEventHandlerSharedPtr& rHandler ) +{ + mpImpl->maShapeListenerHandlers.remove( rHandler ); +} + +void EventMultiplexer::addUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler ) +{ + mpImpl->maUserPaintEventHandlers.add( rHandler ); +} + +void EventMultiplexer::removeUserPaintHandler( const UserPaintEventHandlerSharedPtr& rHandler ) +{ + mpImpl->maUserPaintEventHandlers.remove( rHandler ); +} + +void EventMultiplexer::addShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler ) +{ + mpImpl->maShapeCursorHandlers.add( rHandler ); +} + +void EventMultiplexer::removeShapeCursorHandler( const ShapeCursorEventHandlerSharedPtr& rHandler ) +{ + mpImpl->maShapeCursorHandlers.remove( rHandler ); } void EventMultiplexer::addClickHandler( const MouseEventHandlerSharedPtr& rHandler, double nPriority ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addMouseHandler( - maMouseClickHandlers, + mpImpl->addMouseHandler( + mpImpl->maMouseClickHandlers, rHandler, nPriority, - isMouseListenerRegistered() + mpImpl->isMouseListenerRegistered() ? NULL : &presentation::XSlideShowView::addMouseListener ); } @@ -703,27 +951,24 @@ void EventMultiplexer::addClickHandler( void EventMultiplexer::removeClickHandler( const MouseEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); + mpImpl->maMouseClickHandlers.remove( + EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type( + rHandler, + 0.0) ); - removeHandler( maMouseClickHandlers, - rHandler ); - - if( !isMouseListenerRegistered() ) { - forEachView( &presentation::XSlideShowView::removeMouseListener ); - } + if( !mpImpl->isMouseListenerRegistered() ) + mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener ); } void EventMultiplexer::addDoubleClickHandler( const MouseEventHandlerSharedPtr& rHandler, double nPriority ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addMouseHandler( - maMouseDoubleClickHandlers, + mpImpl->addMouseHandler( + mpImpl->maMouseDoubleClickHandlers, rHandler, nPriority, - isMouseListenerRegistered() + mpImpl->isMouseListenerRegistered() ? NULL : &presentation::XSlideShowView::addMouseListener ); } @@ -731,27 +976,24 @@ void EventMultiplexer::addDoubleClickHandler( void EventMultiplexer::removeDoubleClickHandler( const MouseEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maMouseDoubleClickHandlers, - rHandler ); + mpImpl->maMouseDoubleClickHandlers.remove( + EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type( + rHandler, + 0.0) ); - if( !isMouseListenerRegistered() ) { - forEachView( &presentation::XSlideShowView::removeMouseListener ); - } + if( !mpImpl->isMouseListenerRegistered() ) + mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener ); } void EventMultiplexer::addMouseMoveHandler( const MouseEventHandlerSharedPtr& rHandler, double nPriority ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - addMouseHandler( - maMouseMoveHandlers, + mpImpl->addMouseHandler( + mpImpl->maMouseMoveHandlers, rHandler, nPriority, - maMouseMoveHandlers.empty() + mpImpl->maMouseMoveHandlers.isEmpty() ? &presentation::XSlideShowView::addMouseMotionListener : NULL ); } @@ -759,112 +1001,160 @@ void EventMultiplexer::addMouseMoveHandler( void EventMultiplexer::removeMouseMoveHandler( const MouseEventHandlerSharedPtr& rHandler ) { - ::osl::MutexGuard aGuard( m_aMutex ); - - removeHandler( maMouseMoveHandlers, - rHandler ); + mpImpl->maMouseMoveHandlers.remove( + EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type( + rHandler, + 0.0) ); - if( maMouseMoveHandlers.empty() ) { - forEachView( + if( mpImpl->maMouseMoveHandlers.isEmpty() ) + mpImpl->forEachView( &presentation::XSlideShowView::removeMouseMotionListener ); - } } -void EventMultiplexer::addHyperlinkHandler( - HyperLinkHandlerFunc const& func, HandlerId id ) +void EventMultiplexer::addHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler, + double nPriority ) +{ + mpImpl->maHyperlinkHandlers.addSorted( + EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type( + rHandler, + nPriority) ); +} + +void EventMultiplexer::removeHyperlinkHandler( const HyperlinkHandlerSharedPtr& rHandler ) +{ + mpImpl->maHyperlinkHandlers.remove( + EventMultiplexerImpl::ImplHyperLinkHandlers::container_type::value_type( + rHandler, + 0.0) ); +} + +bool EventMultiplexer::notifyShapeListenerAdded( + const uno::Reference<presentation::XShapeEventListener>& xListener, + const uno::Reference<drawing::XShape>& xShape ) +{ + return mpImpl->maShapeListenerHandlers.applyAll( + boost::bind(&ShapeListenerEventHandler::listenerAdded, + _1, + boost::cref(xListener), + boost::cref(xShape)) ); +} + +bool EventMultiplexer::notifyShapeListenerRemoved( + const uno::Reference<presentation::XShapeEventListener>& xListener, + const uno::Reference<drawing::XShape>& xShape ) +{ + return mpImpl->maShapeListenerHandlers.applyAll( + boost::bind(&ShapeListenerEventHandler::listenerRemoved, + _1, + boost::cref(xListener), + boost::cref(xShape)) ); +} + +bool EventMultiplexer::notifyShapeCursorChange( + const uno::Reference<drawing::XShape>& xShape, + sal_Int16 nPointerShape ) +{ + return mpImpl->maShapeCursorHandlers.applyAll( + boost::bind(&ShapeCursorEventHandler::cursorChanged, + _1, + boost::cref(xShape), + nPointerShape)); +} + +bool EventMultiplexer::notifyUserPaintColor( RGBColor const& rUserColor ) { - osl::MutexGuard const guard(m_aMutex); - maHyperlinkHandlers[id] = func; // second add will overwrite previous func + return mpImpl->maUserPaintEventHandlers.applyAll( + boost::bind(&UserPaintEventHandler::colorChanged, + _1, + boost::cref(rUserColor))); } -void EventMultiplexer::removeHyperlinkHandler( HandlerId id ) +bool EventMultiplexer::notifyUserPaintDisabled() { - osl::MutexGuard const guard(m_aMutex); - maHyperlinkHandlers.erase(id); + return mpImpl->maUserPaintEventHandlers.applyAll( + boost::mem_fn(&UserPaintEventHandler::disable)); } bool EventMultiplexer::notifyNextEffect() { - // fire event on handlers, try in order of precedence. If - // one high-priority handler rejects the event - // (i.e. returns false), try next handler. - return notifySingleHandler( - maNextEffectHandlers, - boost::bind( - &EventHandler::handleEvent, - boost::bind( &ImplNextEffectHandlers::value_type::getHandler, - _1 ) ) ); + return mpImpl->notifyNextEffect(); } bool EventMultiplexer::notifySlideStartEvent() { - return notifyAllEventHandlers( maSlideStartHandlers ); + return mpImpl->maSlideStartHandlers.applyAll( + boost::mem_fn(&EventHandler::handleEvent) ); } bool EventMultiplexer::notifySlideEndEvent() { - return notifyAllEventHandlers( maSlideEndHandlers ); + return mpImpl->maSlideEndHandlers.applyAll( + boost::mem_fn(&EventHandler::handleEvent) ); } bool EventMultiplexer::notifyAnimationStart( const AnimationNodeSharedPtr& rNode ) { - return notifyAllAnimationHandlers( maAnimationStartHandlers, rNode ); + return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationStartHandlers, + rNode ); } bool EventMultiplexer::notifyAnimationEnd( const AnimationNodeSharedPtr& rNode ) { - return notifyAllAnimationHandlers( maAnimationEndHandlers, rNode ); + return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationEndHandlers, + rNode ); } bool EventMultiplexer::notifySlideAnimationsEnd() { - return notifyAllEventHandlers( maSlideAnimationsEndHandlers ); + return mpImpl->maSlideAnimationsEndHandlers.applyAll( + boost::mem_fn(&EventHandler::handleEvent)); } bool EventMultiplexer::notifyAudioStopped( const AnimationNodeSharedPtr& rNode ) { - return notifyAllAnimationHandlers( maAudioStoppedHandlers, rNode ); + return mpImpl->notifyAllAnimationHandlers( + mpImpl->maAudioStoppedHandlers, + rNode ); } bool EventMultiplexer::notifyCommandStopAudio( const AnimationNodeSharedPtr& rNode ) { - return notifyAllAnimationHandlers( maCommandStopAudioHandlers, rNode ); + return mpImpl->notifyAllAnimationHandlers( + mpImpl->maCommandStopAudioHandlers, + rNode ); } bool EventMultiplexer::notifyPauseMode( bool bPauseShow ) { - return notifyAllHandlers( maPauseHandlers, - boost::bind( &PauseEventHandler::handlePause, - _1, bPauseShow )); + return mpImpl->maPauseHandlers.applyAll( + boost::bind( &PauseEventHandler::handlePause, + _1, bPauseShow )); } bool EventMultiplexer::notifyViewAdded( const UnoViewSharedPtr& rView ) { ENSURE_AND_THROW( rView, "EventMultiplexer::notifyViewAdded(): Invalid view"); - ::osl::ClearableMutexGuard aGuard( m_aMutex ); - - maViewContainer.push_back( rView ); - - // register event listeners + // register event listener uno::Reference<presentation::XSlideShowView> const rUnoView( rView->getUnoView() ); - if( isMouseListenerRegistered() ) - rUnoView->addMouseListener( this ); - - if( !maMouseMoveHandlers.empty() ) - rUnoView->addMouseMotionListener( this ); + if( mpImpl->isMouseListenerRegistered() ) + rUnoView->addMouseListener( + mpImpl->mxListener.get() ); - aGuard.clear(); + if( !mpImpl->maMouseMoveHandlers.isEmpty() ) + rUnoView->addMouseMotionListener( + mpImpl->mxListener.get() ); - return notifyAllViewHandlers( boost::bind( &ViewEventHandler::viewAdded, - _1, - rView )); + return mpImpl->maViewHandlers.applyAll( + boost::bind( &ViewEventHandler::viewAdded, + _1, + boost::cref(rView) )); } bool EventMultiplexer::notifyViewRemoved( const UnoViewSharedPtr& rView ) @@ -872,383 +1162,69 @@ bool EventMultiplexer::notifyViewRemoved( const UnoViewSharedPtr& rView ) ENSURE_AND_THROW( rView, "EventMultiplexer::removeView(): Invalid view" ); - ::osl::ClearableMutexGuard aGuard( m_aMutex ); - // revoke event listeners uno::Reference<presentation::XSlideShowView> const rUnoView( rView->getUnoView() ); - if( isMouseListenerRegistered() ) - rUnoView->removeMouseListener( this ); - - if( !maMouseMoveHandlers.empty() ) - rUnoView->removeMouseMotionListener( this ); + if( mpImpl->isMouseListenerRegistered() ) + rUnoView->removeMouseListener( + mpImpl->mxListener.get() ); - UnoViewVector::iterator aEnd( maViewContainer.end() ); - maViewContainer.erase( ::std::remove(maViewContainer.begin(), aEnd, rView), aEnd ); + if( !mpImpl->maMouseMoveHandlers.isEmpty() ) + rUnoView->removeMouseMotionListener( + mpImpl->mxListener.get() ); - aGuard.clear(); - - return notifyAllViewHandlers( boost::bind( &ViewEventHandler::viewRemoved, - _1, - rView )); + return mpImpl->maViewHandlers.applyAll( + boost::bind( &ViewEventHandler::viewRemoved, + _1, + boost::cref(rView) )); } bool EventMultiplexer::notifyViewChanged( const UnoViewSharedPtr& rView ) { - return notifyAllViewHandlers( boost::bind( &ViewEventHandler::viewChanged, - _1, - rView )); -} - -struct EventMultiplexer::AllViewNotifier -{ - AllViewNotifier( const UnoViewVector& rViews ) : mrViews( rViews ) {} - - void operator()( const ViewEventHandlerWeakPtr& rHandler ) const - { - ViewEventHandlerSharedPtr pHandler( rHandler.lock() ); - - if( pHandler ) - { - std::for_each( mrViews.begin(), - mrViews.end(), - boost::bind( &ViewEventHandler::viewChanged, - boost::cref(pHandler), - _1 )); - } - } - - const UnoViewVector& mrViews; -}; - -bool EventMultiplexer::notifyViewsChanged() -{ - return notifyAllViewHandlers( AllViewNotifier( maViewContainer )); -} - -struct EventMultiplexer::HyperLinkNotifier { - rtl::OUString const& m_rLink; - HyperLinkNotifier( rtl::OUString const& link ) - : m_rLink(link) {} - bool operator()( ImplHyperLinkHandlers::value_type const& v ) const { - return v.second( m_rLink ); - } -}; - -bool EventMultiplexer::notifyHyperlinkClicked( - rtl::OUString const& hyperLink ) -{ - return notifySingleHandler( maHyperlinkHandlers, - HyperLinkNotifier( hyperLink ) ); -} - -void EventMultiplexer::disposing() -{ - // release all references - clear(); - WeakComponentImplHelperBase::disposing(); -} - -// XMouseListener implementation -void SAL_CALL EventMultiplexer::disposing( - const lang::EventObject& /*rSource*/ ) throw (uno::RuntimeException) -{ - // there's no real point in acting on this message - after all, - // the event sources are the XSlideShowViews, which must be - // explicitely removed from the slideshow via - // XSlideShow::removeView(). thus, if a XSlideShowView has - // properly removed itself from the slideshow, it will not be - // found here. and if it hasn't, there'll be other references at - // other places within the slideshow. -} - -bool EventMultiplexer::notifyMouseHandlers( - const ImplMouseHandlers& rQueue, - bool (MouseEventHandler::*pHandlerMethod)( const awt::MouseEvent& ), - const awt::MouseEvent& e ) -{ - uno::Reference<presentation::XSlideShowView> xView( - e.Source, uno::UNO_QUERY ); - - ENSURE_AND_RETURN( xView.is(), "EventMultiplexer::notifyHandlers(): " - "event source is not an XSlideShowView" ); - - // find corresponding view (to mouse position into user coordinate space) - UnoViewVector::const_iterator aIter; - const UnoViewVector::const_iterator aBegin( maViewContainer.begin() ); - const UnoViewVector::const_iterator aEnd ( maViewContainer.end() ); - if( (aIter=::std::find_if( - aBegin, aEnd, - boost::bind( std::equal_to< uno::Reference< - presentation::XSlideShowView > >(), - boost::cref( xView ), - boost::bind( &UnoView::getUnoView, _1 ) ) ) ) == aEnd) - { - ENSURE_AND_RETURN( - false, "EventMultiplexer::notifyHandlers(): " - "event source not found under registered views" ); - } - - // convert mouse position to user coordinate space - ::basegfx::B2DPoint aPosition( e.X, e.Y ); - ::basegfx::B2DHomMatrix aMatrix( (*aIter)->getTransformation() ); - if( !aMatrix.invert() ) - ENSURE_AND_THROW( false, "EventMultiplexer::notifyHandlers():" - " view matrix singular" ); - aPosition *= aMatrix; - - awt::MouseEvent aEvent( e ); - aEvent.X = ::basegfx::fround( aPosition.getX() ); - aEvent.Y = ::basegfx::fround( aPosition.getY() ); - - // fire event on handlers, try in order of precedence. If - // one high-priority handler rejects the event - // (i.e. returns false), try next handler. - return notifySingleHandler( - rQueue, boost::bind( - pHandlerMethod, - boost::bind( &ImplMouseHandlers::value_type::getHandler, _1 ), - aEvent ), - false /* no separate copy: already operating on copy made in - implMouseXXX() */ ); -} - -void EventMultiplexer::implMousePressed( const awt::MouseEvent& e ) -{ - osl::ClearableMutexGuard guard( m_aMutex ); - - // generate a local copy of all handlers, since we have to - // release the object mutex before firing. - ImplMouseHandlers const localDoubleClickHandlers( - maMouseDoubleClickHandlers ); - ImplMouseHandlers const localClickHandlers( - maMouseClickHandlers ); - - guard.clear(); - - // fire double-click events for every second click - sal_Int32 nCurrClickCount = e.ClickCount; - while( nCurrClickCount > 1 && - notifyMouseHandlers( localDoubleClickHandlers, - &MouseEventHandler::handleMousePressed, - e ) ) - { - nCurrClickCount -= 2; - } - - // fire single-click events for all remaining clicks - while( nCurrClickCount > 0 && - notifyMouseHandlers( localClickHandlers, - &MouseEventHandler::handleMousePressed, - e ) ) - { - --nCurrClickCount; - } -} - -void EventMultiplexer::implMouseReleased( const awt::MouseEvent& e ) -{ - // generate a local copy of all handlers, since we have to - // release the object mutex before firing. - osl::ClearableMutexGuard guard( m_aMutex ); - ImplMouseHandlers const localDoubleClickHandlers( - maMouseDoubleClickHandlers ); - ImplMouseHandlers const localClickHandlers( - maMouseClickHandlers ); - guard.clear(); - - // fire double-click events for every second click - sal_Int32 nCurrClickCount = e.ClickCount; - while( nCurrClickCount > 1 && - notifyMouseHandlers( localDoubleClickHandlers, - &MouseEventHandler::handleMouseReleased, - e ) ) - { - nCurrClickCount -= 2; - } - - // fire single-click events for all remaining clicks - while( nCurrClickCount > 0 && - notifyMouseHandlers( localClickHandlers, - &MouseEventHandler::handleMouseReleased, - e ) ) - { - --nCurrClickCount; - } -} - -void EventMultiplexer::implMouseDragged( const awt::MouseEvent& e ) -{ - osl::ResettableMutexGuard guard( m_aMutex ); - - // generate a local copy of all handlers, since we have to - // release the object mutex before firing. - ImplMouseHandlers const localHandlers( maMouseMoveHandlers ); - - guard.clear(); - - notifyMouseHandlers( - localHandlers, &MouseEventHandler::handleMouseDragged, e ); - - // re-acquire mutex - guard.reset(); - - if( mnVolatileMouseCursor != -1 ) - { - // handlers requested a volatile mouse cursor - set - // one - mnLastVolatileMouseCursor = mnVolatileMouseCursor; - implSetMouseCursor( mnVolatileMouseCursor ); - - mnVolatileMouseCursor = -1; - } - else if( mnMouseCursor != mnLastVolatileMouseCursor ) - { - // handlers did not request a volatile mouse cursor - - // clear to default, if necessary - implSetMouseCursor( mnMouseCursor ); - - mnLastVolatileMouseCursor = mnMouseCursor; - } -} - -void EventMultiplexer::implMouseMoved( const awt::MouseEvent& e ) -{ - osl::ResettableMutexGuard guard( m_aMutex ); - // generate a local copy of all handlers, since we have to - // release the object mutex before firing. - ImplMouseHandlers const localHandlers( maMouseMoveHandlers ); - - guard.clear(); - - notifyMouseHandlers( - localHandlers, &MouseEventHandler::handleMouseMoved, e ); - - // re-acquire mutex - guard.reset(); - - if( mnVolatileMouseCursor != -1 ) - { - // handlers requested a volatile mouse cursor - set - // one - mnLastVolatileMouseCursor = mnVolatileMouseCursor; - implSetMouseCursor( mnVolatileMouseCursor ); - - mnVolatileMouseCursor = -1; - } - else if( mnMouseCursor != mnLastVolatileMouseCursor ) - { - // handlers did not request a volatile mouse cursor - - // clear to default, if necessary - implSetMouseCursor( mnMouseCursor ); - - mnLastVolatileMouseCursor = mnMouseCursor; - } -} - -void SAL_CALL EventMultiplexer::mousePressed( - const awt::MouseEvent& e ) throw (uno::RuntimeException) -{ - osl::MutexGuard const guard( m_aMutex ); - - // notify mouse press. Don't call handlers directly, this - // might not be the main thread! - mrEventQueue.addEvent( - makeEvent( boost::bind( &EventMultiplexer::implMousePressed, - this, e ) ) ); + return mpImpl->maViewHandlers.applyAll( + boost::bind( &ViewEventHandler::viewChanged, + _1, + boost::cref(rView) )); } -void SAL_CALL EventMultiplexer::mouseReleased( - const awt::MouseEvent& e ) throw (uno::RuntimeException) +bool EventMultiplexer::notifyViewChanged( const uno::Reference<presentation::XSlideShowView>& xView ) { - osl::MutexGuard const guard( m_aMutex ); + UnoViewSharedPtr pView( mpImpl->findUnoView(xView) ); - // notify mouse release. Don't call handlers directly, - // this might not be the main thread! - mrEventQueue.addEvent( - makeEvent( boost::bind( &EventMultiplexer::implMouseReleased, - this, e ) ) ); -} + if( !pView ) + return false; // view not registered here -void SAL_CALL EventMultiplexer::mouseEntered( - const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException) -{ - // not used here + return notifyViewChanged( pView ); } -void SAL_CALL EventMultiplexer::mouseExited( - const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException) +bool EventMultiplexer::notifyViewsChanged() { - // not used here + return mpImpl->maViewHandlers.applyAll( + boost::mem_fn( &ViewEventHandler::viewsChanged )); } -// XMouseMotionListener implementation -void SAL_CALL EventMultiplexer::mouseDragged( - const awt::MouseEvent& e ) throw (uno::RuntimeException) +bool EventMultiplexer::notifyViewClobbered( + const uno::Reference<presentation::XSlideShowView>& xView ) { - osl::MutexGuard const guard( m_aMutex ); - - // notify mouse drag. Don't call handlers directly, this - // might not be the main thread! - mrEventQueue.addEvent( - makeEvent( boost::bind( &EventMultiplexer::implMouseDragged, - this, e ) ) ); -} + UnoViewSharedPtr pView( mpImpl->findUnoView(xView) ); -void SAL_CALL EventMultiplexer::mouseMoved( - const awt::MouseEvent& e ) throw (uno::RuntimeException) -{ - osl::MutexGuard const guard( m_aMutex ); + if( !pView ) + return false; // view not registered here - // notify mouse move. Don't call handlers directly, this - // might not be the main thread! - mrEventQueue.addEvent( - makeEvent( boost::bind( &EventMultiplexer::implMouseMoved, - this, e ) ) ); + return mpImpl->maViewRepaintHandlers.applyAll( + boost::bind( &ViewRepaintHandler::viewClobbered, + _1, + boost::cref(pView) )); } -EventMultiplexer::~EventMultiplexer() +bool EventMultiplexer::notifyHyperlinkClicked( + rtl::OUString const& hyperLink ) { - // WeakComponentImplHelperBase calls disposing() upon destruction - // if object has not been disposed yet. -} - -EventMultiplexer::EventMultiplexer( EventQueue& rEventQueue, - const UnoViewContainer& rViewContainer ) : - Listener_UnoBase( m_aMutex ), - mrEventQueue( rEventQueue ), - maViewContainer(rViewContainer.begin(), - rViewContainer.end()), - maNextEffectHandlers(), - maSlideStartHandlers(), - maSlideEndHandlers(), - maAnimationStartHandlers(), - maAnimationEndHandlers(), - maSlideAnimationsEndHandlers(), - maAudioStoppedHandlers(), - maCommandStopAudioHandlers(), - maPauseHandlers(), - maViewHandlers(), - maMouseClickHandlers(), - maMouseDoubleClickHandlers(), - maMouseMoveHandlers(), - maHyperlinkHandlers(), - mnTimeout( 0.0 ), - mpTickEvent(), - mnMouseCursor( awt::SystemPointer::ARROW ), - mnVolatileMouseCursor( -1 ), - mnLastVolatileMouseCursor( mnMouseCursor ), - mbIsAutoMode( false ) -{ -} - -rtl::Reference<EventMultiplexer> EventMultiplexer::create( - EventQueue& rEventQueue, - const UnoViewContainer& rViews ) -{ - return new EventMultiplexer(rEventQueue, - rViews); + return mpImpl->maHyperlinkHandlers.apply( + boost::bind(&HyperlinkHandler::handleHyperlink, + _1, + boost::cref(hyperLink)) ); } } // namespace internal |