summaryrefslogtreecommitdiff
path: root/slideshow/source/engine/eventmultiplexer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'slideshow/source/engine/eventmultiplexer.cxx')
-rw-r--r--slideshow/source/engine/eventmultiplexer.cxx1278
1 files changed, 1278 insertions, 0 deletions
diff --git a/slideshow/source/engine/eventmultiplexer.cxx b/slideshow/source/engine/eventmultiplexer.cxx
new file mode 100644
index 000000000000..ea910d60e575
--- /dev/null
+++ b/slideshow/source/engine/eventmultiplexer.cxx
@@ -0,0 +1,1278 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_slideshow.hxx"
+
+// must be first
+#include <canvas/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#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>
+#include <hash_map>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+
+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 PrioritizedHandlerEntry
+{
+ typedef boost::shared_ptr<HandlerT> HandlerSharedPtrT;
+ HandlerSharedPtrT mpHandler;
+ double mnPrio;
+
+public:
+ PrioritizedHandlerEntry( HandlerSharedPtrT const& pHandler,
+ double nPrio ) :
+ mpHandler(pHandler),
+ mnPrio(nPrio)
+ {}
+
+ HandlerSharedPtrT const& getHandler() const { return mpHandler; }
+
+ /// To sort according to priority
+ bool operator<( PrioritizedHandlerEntry const& rRHS ) const
+ {
+ // reversed order - high prioritized entries
+ // should be at the beginning of the queue
+ return mnPrio > rRHS.mnPrio;
+ }
+
+ /// 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;
+ }
+};
+
+template<typename T> inline T* get_pointer(PrioritizedHandlerEntry<T> const& handler)
+{
+ return handler.getHandler().get();
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+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)
+ */
+class EventMultiplexerListener : private cppu::BaseMutex,
+ public Listener_UnoBase,
+ private ::boost::noncopyable
+{
+public:
+ EventMultiplexerListener( EventQueue& rEventQueue,
+ EventMultiplexerImpl& rEventMultiplexer ) :
+ Listener_UnoBase( m_aMutex ),
+ mpEventQueue( &rEventQueue ),
+ mpEventMultiplexer( &rEventMultiplexer )
+ {
+ }
+
+ // WeakComponentImplHelperBase::disposing
+ virtual void SAL_CALL disposing();
+
+private:
+ virtual void SAL_CALL disposing( const lang::EventObject& Source )
+ throw (uno::RuntimeException);
+
+ // 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);
+
+ // 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);
+
+
+ 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()
+ {
+ if( mxListener.is() )
+ mxListener->dispose();
+ }
+
+ /// 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;
+};
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+void SAL_CALL EventMultiplexerListener::disposing()
+{
+ osl::MutexGuard const guard( m_aMutex );
+ mpEventQueue = NULL;
+ mpEventMultiplexer = NULL;
+}
+
+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...
+}
+
+void SAL_CALL EventMultiplexerListener::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!
+ if( mpEventQueue )
+ mpEventQueue->addEvent(
+ makeEvent( boost::bind( &EventMultiplexerImpl::mousePressed,
+ mpEventMultiplexer,
+ e ),
+ "EventMultiplexerImpl::mousePressed") );
+}
+
+void SAL_CALL EventMultiplexerListener::mouseReleased(
+ const awt::MouseEvent& e ) throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // 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 ),
+ "EventMultiplexerImpl::mouseReleased") );
+}
+
+void SAL_CALL EventMultiplexerListener::mouseEntered(
+ const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException)
+{
+ // not used here
+}
+
+void SAL_CALL EventMultiplexerListener::mouseExited(
+ const awt::MouseEvent& /*e*/ ) throw (uno::RuntimeException)
+{
+ // not used here
+}
+
+// XMouseMotionListener implementation
+void SAL_CALL EventMultiplexerListener::mouseDragged(
+ const awt::MouseEvent& e ) throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // 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 ),
+ "EventMultiplexerImpl::mouseDragged") );
+}
+
+void SAL_CALL EventMultiplexerListener::mouseMoved(
+ const awt::MouseEvent& e ) throw (uno::RuntimeException)
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ // 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 ),
+ "EventMultiplexerImpl::mouseMoved") );
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+bool EventMultiplexerImpl::notifyAllAnimationHandlers( ImplAnimationHandlers const& rContainer,
+ AnimationNodeSharedPtr const& rNode )
+{
+ return rContainer.applyAll(
+ boost::bind( &AnimationEventHandler::handleAnimationEvent,
+ _1, boost::cref(rNode) ) );
+}
+
+template <typename XSlideShowViewFunc>
+void EventMultiplexerImpl::forEachView( XSlideShowViewFunc pViewMethod )
+{
+ if( pViewMethod )
+ {
+ // (un)register mouse listener on all views
+ for( UnoViewVector::const_iterator aIter( mrViewContainer.begin() ),
+ aEnd( mrViewContainer.end() ); aIter != aEnd; ++aIter )
+ {
+ uno::Reference<presentation::XSlideShowView> xView ((*aIter)->getUnoView());
+ if (xView.is())
+ {
+ (xView.get()->*pViewMethod)( mxListener.get() );
+ }
+ else
+ {
+ OSL_ASSERT(xView.is());
+ }
+ }
+ }
+}
+
+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 EventMultiplexerImpl::addMouseHandler(
+ ImplMouseHandlers& rHandlerContainer,
+ const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority,
+ RegisterFunction pRegisterListener )
+{
+ ENSURE_OR_THROW(
+ rHandler,
+ "EventMultiplexer::addMouseHandler(): Invalid handler" );
+
+ // register mouse listener on all views
+ forEachView( pRegisterListener );
+
+ // add into sorted container:
+ rHandlerContainer.addSorted(
+ typename ImplMouseHandlers::container_type::value_type(
+ rHandler,
+ nPriority ));
+}
+
+bool EventMultiplexerImpl::isMouseListenerRegistered() const
+{
+ return !(maMouseClickHandlers.isEmpty() &&
+ maMouseDoubleClickHandlers.isEmpty());
+}
+
+void EventMultiplexerImpl::tick()
+{
+ if( !mbIsAutoMode )
+ return; // this event is just a left-over, ignore
+
+ notifyNextEffect();
+
+ if( !maNextEffectHandlers.isEmpty() )
+ {
+ // still handlers left, schedule next timeout
+ // event. Will also set mbIsTickEventOn back to true
+ scheduleTick();
+ }
+}
+
+void EventMultiplexerImpl::scheduleTick()
+{
+ EventSharedPtr pEvent(
+ makeDelay( boost::bind( &EventMultiplexerImpl::tick,
+ this ),
+ mnTimeout,
+ "EventMultiplexerImpl::tick with delay"));
+
+ // store weak reference to generated event, to notice when
+ // the event queue gets cleansed (we then have to
+ // regenerate the tick event!)
+ mpTickEvent = pEvent;
+
+ // enabled auto mode: simply schedule a timeout event,
+ // which will eventually call our tick() method
+ mrEventQueue.addEventForNextRound( pEvent );
+}
+
+void EventMultiplexerImpl::handleTicks()
+{
+ if( !mbIsAutoMode )
+ return; // nothing to do, don't need no ticks
+
+ EventSharedPtr pTickEvent( mpTickEvent.lock() );
+ if( pTickEvent )
+ return; // nothing to do, there's already a tick
+ // pending
+
+ // schedule initial tick (which reschedules itself
+ // after that, all by itself)
+ scheduleTick();
+}
+
+
+void EventMultiplexerImpl::clear()
+{
+ // deregister from all views.
+ if( isMouseListenerRegistered() )
+ {
+ for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
+ aEnd=mrViewContainer.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+ if( (*aIter)->getUnoView().is() )
+ (*aIter)->getUnoView()->removeMouseListener( mxListener.get() );
+ }
+ }
+
+ if( !maMouseMoveHandlers.isEmpty() )
+ {
+ for( UnoViewVector::const_iterator aIter=mrViewContainer.begin(),
+ aEnd=mrViewContainer.end();
+ aIter!=aEnd;
+ ++aIter )
+ {
+ if( (*aIter)->getUnoView().is() )
+ (*aIter)->getUnoView()->removeMouseMotionListener( mxListener.get() );
+ }
+ }
+
+ // clear all handlers (releases all references)
+ maNextEffectHandlers.clear();
+ maSlideStartHandlers.clear();
+ maSlideEndHandlers.clear();
+ maAnimationStartHandlers.clear();
+ maAnimationEndHandlers.clear();
+ maSlideAnimationsEndHandlers.clear();
+ maAudioStoppedHandlers.clear();
+ maCommandStopAudioHandlers.clear();
+ maPauseHandlers.clear();
+ maViewHandlers.clear();
+ maViewRepaintHandlers.clear();
+ maMouseClickHandlers.clear();
+ maMouseDoubleClickHandlers.clear();
+ maMouseMoveHandlers.clear();
+ maHyperlinkHandlers.clear();
+ mpTickEvent.reset();
+}
+
+// XMouseListener implementation
+bool EventMultiplexerImpl::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_OR_RETURN_FALSE( xView.is(), "EventMultiplexer::notifyHandlers(): "
+ "event source is not an XSlideShowView" );
+
+ // 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_OR_RETURN_FALSE(
+ 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_OR_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 rQueue.apply(
+ boost::bind(
+ pHandlerMethod,
+ boost::bind(
+ &ImplMouseHandlers::container_type::value_type::getHandler,
+ _1 ),
+ aEvent ));
+}
+
+void EventMultiplexerImpl::mousePressed( const awt::MouseEvent& e )
+{
+ // fire double-click events for every second click
+ sal_Int32 nCurrClickCount = e.ClickCount;
+ while( nCurrClickCount > 1 &&
+ notifyMouseHandlers( maMouseDoubleClickHandlers,
+ &MouseEventHandler::handleMousePressed,
+ e ))
+ {
+ nCurrClickCount -= 2;
+ }
+
+ // fire single-click events for all remaining clicks
+ while( nCurrClickCount > 0 &&
+ notifyMouseHandlers( maMouseClickHandlers,
+ &MouseEventHandler::handleMousePressed,
+ e ))
+ {
+ --nCurrClickCount;
+ }
+}
+
+void EventMultiplexerImpl::mouseReleased( const awt::MouseEvent& e )
+{
+ // fire double-click events for every second click
+ sal_Int32 nCurrClickCount = e.ClickCount;
+ while( nCurrClickCount > 1 &&
+ notifyMouseHandlers( maMouseDoubleClickHandlers,
+ &MouseEventHandler::handleMouseReleased,
+ e ))
+ {
+ nCurrClickCount -= 2;
+ }
+
+ // fire single-click events for all remaining clicks
+ while( nCurrClickCount > 0 &&
+ notifyMouseHandlers( maMouseClickHandlers,
+ &MouseEventHandler::handleMouseReleased,
+ e ))
+ {
+ --nCurrClickCount;
+ }
+}
+
+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()
+{
+ mpImpl->clear();
+}
+
+void EventMultiplexer::setAutomaticMode( bool bIsAuto )
+{
+ if( bIsAuto == mpImpl->mbIsAutoMode )
+ return; // no change, nothing to do
+
+ mpImpl->mbIsAutoMode = bIsAuto;
+
+ mpImpl->handleTicks();
+}
+
+bool EventMultiplexer::getAutomaticMode() const
+{
+ return mpImpl->mbIsAutoMode;
+}
+
+void EventMultiplexer::setAutomaticTimeout( double nTimeout )
+{
+ mpImpl->mnTimeout = nTimeout;
+}
+
+double EventMultiplexer::getAutomaticTimeout() const
+{
+ return mpImpl->mnTimeout;
+}
+
+void EventMultiplexer::addNextEffectHandler(
+ EventHandlerSharedPtr const& rHandler,
+ double nPriority )
+{
+ mpImpl->maNextEffectHandlers.addSorted(
+ EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
+ rHandler,
+ nPriority) );
+
+ // Enable tick events, if not done already
+ mpImpl->handleTicks();
+}
+
+void EventMultiplexer::removeNextEffectHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maNextEffectHandlers.remove(
+ EventMultiplexerImpl::ImplNextEffectHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+}
+
+void EventMultiplexer::addSlideStartHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideStartHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeSlideStartHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideStartHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addSlideEndHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideEndHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeSlideEndHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideEndHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addAnimationStartHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAnimationStartHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeAnimationStartHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAnimationStartHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addAnimationEndHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAnimationEndHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeAnimationEndHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAnimationEndHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addSlideAnimationsEndHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideAnimationsEndHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeSlideAnimationsEndHandler(
+ const EventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maSlideAnimationsEndHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addAudioStoppedHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAudioStoppedHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeAudioStoppedHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maAudioStoppedHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addCommandStopAudioHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maCommandStopAudioHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removeCommandStopAudioHandler(
+ const AnimationEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maCommandStopAudioHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addPauseHandler(
+ const PauseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maPauseHandlers.add( rHandler );
+}
+
+void EventMultiplexer::removePauseHandler(
+ const PauseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maPauseHandlers.remove( rHandler );
+}
+
+void EventMultiplexer::addViewHandler(
+ const ViewEventHandlerWeakPtr& rHandler )
+{
+ 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 );
+}
+
+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 )
+{
+ mpImpl->addMouseHandler(
+ mpImpl->maMouseClickHandlers,
+ rHandler,
+ nPriority,
+ mpImpl->isMouseListenerRegistered()
+ ? NULL
+ : &presentation::XSlideShowView::addMouseListener );
+}
+
+void EventMultiplexer::removeClickHandler(
+ const MouseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maMouseClickHandlers.remove(
+ EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+
+ if( !mpImpl->isMouseListenerRegistered() )
+ mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
+}
+
+void EventMultiplexer::addDoubleClickHandler(
+ const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority )
+{
+ mpImpl->addMouseHandler(
+ mpImpl->maMouseDoubleClickHandlers,
+ rHandler,
+ nPriority,
+ mpImpl->isMouseListenerRegistered()
+ ? NULL
+ : &presentation::XSlideShowView::addMouseListener );
+}
+
+void EventMultiplexer::removeDoubleClickHandler(
+ const MouseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maMouseDoubleClickHandlers.remove(
+ EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+
+ if( !mpImpl->isMouseListenerRegistered() )
+ mpImpl->forEachView( &presentation::XSlideShowView::removeMouseListener );
+}
+
+void EventMultiplexer::addMouseMoveHandler(
+ const MouseEventHandlerSharedPtr& rHandler,
+ double nPriority )
+{
+ mpImpl->addMouseHandler(
+ mpImpl->maMouseMoveHandlers,
+ rHandler,
+ nPriority,
+ mpImpl->maMouseMoveHandlers.isEmpty()
+ ? &presentation::XSlideShowView::addMouseMotionListener
+ : NULL );
+}
+
+void EventMultiplexer::removeMouseMoveHandler(
+ const MouseEventHandlerSharedPtr& rHandler )
+{
+ mpImpl->maMouseMoveHandlers.remove(
+ EventMultiplexerImpl::ImplMouseHandlers::container_type::value_type(
+ rHandler,
+ 0.0) );
+
+ if( mpImpl->maMouseMoveHandlers.isEmpty() )
+ mpImpl->forEachView(
+ &presentation::XSlideShowView::removeMouseMotionListener );
+}
+
+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 )
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::bind(&UserPaintEventHandler::colorChanged,
+ _1,
+ boost::cref(rUserColor)));
+}
+
+bool EventMultiplexer::notifyUserPaintStrokeWidth( double rUserStrokeWidth )
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::bind(&UserPaintEventHandler::widthChanged,
+ _1,
+ rUserStrokeWidth));
+}
+
+bool EventMultiplexer::notifyUserPaintDisabled()
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::mem_fn(&UserPaintEventHandler::disable));
+}
+
+bool EventMultiplexer::notifySwitchPenMode(){
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::mem_fn(&UserPaintEventHandler::switchPenMode));
+}
+
+bool EventMultiplexer::notifySwitchEraserMode(){
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::mem_fn(&UserPaintEventHandler::switchEraserMode));
+}
+
+//adding erasing all ink features with UserPaintOverlay
+bool EventMultiplexer::notifyEraseAllInk( bool const& rEraseAllInk )
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::bind(&UserPaintEventHandler::eraseAllInkChanged,
+ _1,
+ boost::cref(rEraseAllInk)));
+}
+
+//adding erasing features with UserPaintOverlay
+bool EventMultiplexer::notifyEraseInkWidth( sal_Int32 rEraseInkSize )
+{
+ return mpImpl->maUserPaintEventHandlers.applyAll(
+ boost::bind(&UserPaintEventHandler::eraseInkWidthChanged,
+ _1,
+ boost::cref(rEraseInkSize)));
+}
+
+bool EventMultiplexer::notifyNextEffect()
+{
+ return mpImpl->notifyNextEffect();
+}
+
+bool EventMultiplexer::notifySlideStartEvent()
+{
+ return mpImpl->maSlideStartHandlers.applyAll(
+ boost::mem_fn(&EventHandler::handleEvent) );
+}
+
+bool EventMultiplexer::notifySlideEndEvent()
+{
+ return mpImpl->maSlideEndHandlers.applyAll(
+ boost::mem_fn(&EventHandler::handleEvent) );
+}
+
+bool EventMultiplexer::notifyAnimationStart(
+ const AnimationNodeSharedPtr& rNode )
+{
+ return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationStartHandlers,
+ rNode );
+}
+
+bool EventMultiplexer::notifyAnimationEnd(
+ const AnimationNodeSharedPtr& rNode )
+{
+ return mpImpl->notifyAllAnimationHandlers( mpImpl->maAnimationEndHandlers,
+ rNode );
+}
+
+bool EventMultiplexer::notifySlideAnimationsEnd()
+{
+ return mpImpl->maSlideAnimationsEndHandlers.applyAll(
+ boost::mem_fn(&EventHandler::handleEvent));
+}
+
+bool EventMultiplexer::notifyAudioStopped(
+ const AnimationNodeSharedPtr& rNode )
+{
+ return mpImpl->notifyAllAnimationHandlers(
+ mpImpl->maAudioStoppedHandlers,
+ rNode );
+}
+
+bool EventMultiplexer::notifyCommandStopAudio(
+ const AnimationNodeSharedPtr& rNode )
+{
+ return mpImpl->notifyAllAnimationHandlers(
+ mpImpl->maCommandStopAudioHandlers,
+ rNode );
+}
+
+bool EventMultiplexer::notifyPauseMode( bool bPauseShow )
+{
+ return mpImpl->maPauseHandlers.applyAll(
+ boost::bind( &PauseEventHandler::handlePause,
+ _1, bPauseShow ));
+}
+
+bool EventMultiplexer::notifyViewAdded( const UnoViewSharedPtr& rView )
+{
+ ENSURE_OR_THROW( rView, "EventMultiplexer::notifyViewAdded(): Invalid view");
+
+ // register event listener
+ uno::Reference<presentation::XSlideShowView> const rUnoView(
+ rView->getUnoView() );
+
+ if( mpImpl->isMouseListenerRegistered() )
+ rUnoView->addMouseListener(
+ mpImpl->mxListener.get() );
+
+ if( !mpImpl->maMouseMoveHandlers.isEmpty() )
+ rUnoView->addMouseMotionListener(
+ mpImpl->mxListener.get() );
+
+ return mpImpl->maViewHandlers.applyAll(
+ boost::bind( &ViewEventHandler::viewAdded,
+ _1,
+ boost::cref(rView) ));
+}
+
+bool EventMultiplexer::notifyViewRemoved( const UnoViewSharedPtr& rView )
+{
+ ENSURE_OR_THROW( rView,
+ "EventMultiplexer::removeView(): Invalid view" );
+
+ // revoke event listeners
+ uno::Reference<presentation::XSlideShowView> const rUnoView(
+ rView->getUnoView() );
+
+ if( mpImpl->isMouseListenerRegistered() )
+ rUnoView->removeMouseListener(
+ mpImpl->mxListener.get() );
+
+ if( !mpImpl->maMouseMoveHandlers.isEmpty() )
+ rUnoView->removeMouseMotionListener(
+ mpImpl->mxListener.get() );
+
+ return mpImpl->maViewHandlers.applyAll(
+ boost::bind( &ViewEventHandler::viewRemoved,
+ _1,
+ boost::cref(rView) ));
+}
+
+bool EventMultiplexer::notifyViewChanged( const UnoViewSharedPtr& rView )
+{
+ return mpImpl->maViewHandlers.applyAll(
+ boost::bind( &ViewEventHandler::viewChanged,
+ _1,
+ boost::cref(rView) ));
+}
+
+bool EventMultiplexer::notifyViewChanged( const uno::Reference<presentation::XSlideShowView>& xView )
+{
+ UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
+
+ if( !pView )
+ return false; // view not registered here
+
+ return notifyViewChanged( pView );
+}
+
+bool EventMultiplexer::notifyViewsChanged()
+{
+ return mpImpl->maViewHandlers.applyAll(
+ boost::mem_fn( &ViewEventHandler::viewsChanged ));
+}
+
+bool EventMultiplexer::notifyViewClobbered(
+ const uno::Reference<presentation::XSlideShowView>& xView )
+{
+ UnoViewSharedPtr pView( mpImpl->findUnoView(xView) );
+
+ if( !pView )
+ return false; // view not registered here
+
+ return mpImpl->maViewRepaintHandlers.applyAll(
+ boost::bind( &ViewRepaintHandler::viewClobbered,
+ _1,
+ boost::cref(pView) ));
+}
+
+bool EventMultiplexer::notifyHyperlinkClicked(
+ rtl::OUString const& hyperLink )
+{
+ return mpImpl->maHyperlinkHandlers.apply(
+ boost::bind(&HyperlinkHandler::handleHyperlink,
+ _1,
+ boost::cref(hyperLink)) );
+}
+
+bool EventMultiplexer::notifySlideTransitionStarted()
+{
+ return true;
+}
+
+} // namespace internal
+} // namespace presentation
+