/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"

#include <canvas/debug.hxx>
#include <tools/diagnose_ex.h>

#include <cppuhelper/basemutex.hxx>
#include <cppuhelper/compbase1.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/compbase2.hxx>
#include <cppuhelper/interfacecontainer.h>
#include <cppuhelper/exc_hlp.hxx>

#include <comphelper/anytostring.hxx>
#include <comphelper/make_shared_from_uno.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/optional.hxx>
#include <comphelper/servicedecl.hxx>
#include <comphelper/namecontainer.hxx>

#include <cppcanvas/spritecanvas.hxx>
#include <cppcanvas/vclfactory.hxx>
#include <cppcanvas/basegfxfactory.hxx>

#include <tools/debug.hxx>

#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/tools/canvastools.hxx>

#include <vcl/font.hxx>
#include "rtl/ref.hxx"

#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/util/XModifyListener.hpp>
#include <com/sun/star/util/XUpdatable.hpp>
#include <com/sun/star/awt/XPaintListener.hpp>
#include <com/sun/star/awt/SystemPointer.hpp>
#include <com/sun/star/animations/TransitionType.hpp>
#include <com/sun/star/animations/TransitionSubType.hpp>
#include <com/sun/star/presentation/XSlideShow.hpp>
#include <com/sun/star/presentation/XSlideShowListener.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XServiceName.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/drawing/PointSequenceSequence.hpp>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/drawing/XLayer.hpp>
#include <com/sun/star/drawing/XLayerSupplier.hpp>
#include <com/sun/star/drawing/XLayerManager.hpp>
#include <com/sun/star/container/XNameAccess.hpp>

#include "com/sun/star/uno/Reference.hxx"
#include <com/sun/star/loader/CannotActivateFactoryException.hpp>

#include "unoviewcontainer.hxx"
#include "transitionfactory.hxx"
#include "eventmultiplexer.hxx"
#include "usereventqueue.hxx"
#include "eventqueue.hxx"
#include "cursormanager.hxx"
#include "slideshowcontext.hxx"
#include "activitiesqueue.hxx"
#include "activitiesfactory.hxx"
#include "interruptabledelayevent.hxx"
#include "slide.hxx"
#include "shapemaps.hxx"
#include "slideview.hxx"
#include "tools.hxx"
#include "unoview.hxx"
#include "slidebitmap.hxx"
#include "rehearsetimingsactivity.hxx"
#include "waitsymbol.hxx"
#include "effectrewinder.hxx"
#include "framerate.hxx"

#include <boost/noncopyable.hpp>
#include <boost/bind.hpp>

#include <map>
#include <vector>
#include <iterator>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <iostream>

using namespace com::sun::star;
using namespace ::slideshow::internal;

namespace {

/** During animations the update() method tells its caller to call it as
    soon as possible.  This gives us more time to render the next frame and
    still maintain a steady frame rate.  This class is responsible for
    synchronizing the display of new frames and thus keeping the frame rate
    steady.
*/
class FrameSynchronization
{
public:
    /** Create new object with a predefined duration between two frames.
        @param nFrameDuration
            The preferred duration between the display of two frames in
            seconds.
    */
    FrameSynchronization (const double nFrameDuration);
    
    /** Set the current time as the time at which the current frame is
        displayed.  From this the target time of the next frame is derived.
    */
    void MarkCurrentFrame (void);

    /** When there is time left until the next frame is due then wait.
        Otherwise return without delay.
    */
    void Synchronize (void);

    /** Activate frame synchronization when an animation is active and
        frames are to be displayed in a steady rate.  While active
        Synchronize() will wait until the frame duration time has passed.
    */
    void Activate (void);

    /** Deactivate frame sychronization when no animation is active and the
        time between frames depends on user actions and other external
        sources.  While deactivated Synchronize() will return without delay.
    */
    void Deactivate (void);

    /** Return the current time of the timer.  It is not synchronized with
        any other timer so its absolute values are of no concern.  Typically
        used during debugging to measure durations.
    */
    double GetCurrentTime (void) const;

private:
    /** The timer that is used for synchronization is independent from the
        one used by SlideShowImpl: it is not paused or modified by
        animations.
    */
    canvas::tools::ElapsedTime maTimer;
    /** Time between the display of frames.  Enforced only when mbIsActive
        is <TRUE/>.
    */
    const double mnFrameDuration;
    /** Time (of maTimer) when the next frame shall be displayed.
        Synchronize() will wait until this time.
    */
    double mnNextFrameTargetTime;
    /** Synchronize() will wait only when this flag is <TRUE/>.  Otherwise
        it returns immediately.
    */
    bool mbIsActive;
};




/******************************************************************************
   
   SlideShowImpl

   This class encapsulates the slideshow presentation viewer.
    
   With an instance of this class, it is possible to statically
   and dynamically show a presentation, as defined by the
   constructor-provided draw model (represented by a sequence
   of ::com::sun::star::drawing::XDrawPage objects).
    
   It is possible to show the presentation on multiple views
   simultaneously (e.g. for a multi-monitor setup). Since this
   class also relies on user interaction, the corresponding
   XSlideShowView interface provides means to register some UI
   event listeners (mostly borrowed from awt::XWindow interface).
   
   Since currently (mid 2004), OOo isn't very well suited to
   multi-threaded rendering, this class relies on <em>very
   frequent</em> external update() calls, which will render the
   next frame of animations. This works as follows: after the
   displaySlide() has been successfully called (which setup and
   starts an actual slide show), the update() method must be
   called until it returns false.
   Effectively, this puts the burden of providing
   concurrency to the clients of this class, which, as noted
   above, is currently unavoidable with the current state of
   affairs (I've actually tried threading here, but failed
   miserably when using the VCL canvas as the render backend -
   deadlocked).
   
 ******************************************************************************/

typedef cppu::WeakComponentImplHelper1<presentation::XSlideShow> SlideShowImplBase;

typedef ::std::vector< ::cppcanvas::PolyPolygonSharedPtr> PolyPolygonVector;
    
/// Maps XDrawPage for annotations persistence
typedef ::std::map< ::com::sun::star::uno::Reference<
                                    ::com::sun::star::drawing::XDrawPage>,
                                    PolyPolygonVector>  PolygonMap;
    
class SlideShowImpl : private cppu::BaseMutex,
                      public CursorManager,
                      public SlideShowImplBase
{
public:
    explicit SlideShowImpl(
        uno::Reference<uno::XComponentContext> const& xContext );

    /** Notify that the transition phase of the current slide
        has ended.

        The life of a slide has three phases: the transition
        phase, when the previous slide vanishes, and the
        current slide becomes visible, the shape animation
        phase, when shape effects are running, and the phase
        after the last shape animation has ended, but before
        the next slide transition starts.

        This method notifies the end of the first phase.

        @param bPaintSlide
        When true, Slide::show() is passed a true as well, denoting
        explicit paint of slide content. Pass false here, if e.g. a
        slide transition has already rendered the initial slide image.
    */
    void notifySlideTransitionEnded( bool bPaintSlide );

    /** Notify that the shape animation phase of the current slide
        has ended.

        The life of a slide has three phases: the transition
        phase, when the previous slide vanishes, and the
        current slide becomes visible, the shape animation
        phase, when shape effects are running, and the phase
        after the last shape animation has ended, but before
        the next slide transition starts.

        This method notifies the end of the second phase.
    */
    void notifySlideAnimationsEnded();

    /** Notify that the slide has ended.

        The life of a slide has three phases: the transition
        phase, when the previous slide vanishes, and the
        current slide becomes visible, the shape animation
        phase, when shape effects are running, and the phase
        after the last shape animation has ended, but before
        the next slide transition starts.
        
        This method notifies the end of the third phase.
    */
    void notifySlideEnded (const bool bReverse);

    /** Notification from eventmultiplexer that a hyperlink
        has been clicked.
    */
    bool notifyHyperLinkClicked( rtl::OUString const& hyperLink );
    
    /** Notification from eventmultiplexer that an animation event has occoured.
		This will be forewarded to all registered XSlideShowListener
     */
	bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode );

private:
    // XSlideShow:
    virtual sal_Bool SAL_CALL nextEffect() throw (uno::RuntimeException);
    virtual sal_Bool SAL_CALL previousEffect() throw (uno::RuntimeException);
    virtual sal_Bool SAL_CALL startShapeActivity(
        uno::Reference<drawing::XShape> const& xShape )
        throw (uno::RuntimeException);
    virtual sal_Bool SAL_CALL stopShapeActivity(
        uno::Reference<drawing::XShape> const& xShape )
        throw (uno::RuntimeException);
    virtual sal_Bool SAL_CALL pause( sal_Bool bPauseShow )
        throw (uno::RuntimeException);
    virtual uno::Reference<drawing::XDrawPage> SAL_CALL getCurrentSlide()
        throw (uno::RuntimeException);
    virtual void SAL_CALL displaySlide(
        uno::Reference<drawing::XDrawPage> const& xSlide,
        uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
        uno::Reference<animations::XAnimationNode> const& xRootNode,
        uno::Sequence<beans::PropertyValue> const& rProperties )
        throw (uno::RuntimeException);
    virtual void SAL_CALL registerUserPaintPolygons( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xDocFactory ) throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL setProperty(
        beans::PropertyValue const& rProperty ) throw (uno::RuntimeException);
    virtual sal_Bool SAL_CALL addView(
        uno::Reference<presentation::XSlideShowView> const& xView )
        throw (uno::RuntimeException);
    virtual sal_Bool SAL_CALL removeView(
        uno::Reference<presentation::XSlideShowView> const& xView )
        throw (uno::RuntimeException);
    virtual sal_Bool SAL_CALL update( double & nNextTimeout )
        throw (uno::RuntimeException);
    virtual void SAL_CALL addSlideShowListener(
        uno::Reference<presentation::XSlideShowListener> const& xListener )
        throw (uno::RuntimeException);
    virtual void SAL_CALL removeSlideShowListener(
        uno::Reference<presentation::XSlideShowListener> const& xListener )
        throw (uno::RuntimeException);
    virtual void SAL_CALL addShapeEventListener(
        uno::Reference<presentation::XShapeEventListener> const& xListener,
        uno::Reference<drawing::XShape> const& xShape )
        throw (uno::RuntimeException);
    virtual void SAL_CALL removeShapeEventListener(
        uno::Reference<presentation::XShapeEventListener> const& xListener,
        uno::Reference<drawing::XShape> const& xShape )
        throw (uno::RuntimeException);
    virtual void SAL_CALL setShapeCursor(
        uno::Reference<drawing::XShape> const& xShape, sal_Int16 nPointerShape )
        throw (uno::RuntimeException);


    // CursorManager
    // -----------------------------------------------------------

    virtual bool requestCursor( sal_Int16 nCursorShape );
    virtual void resetCursor();

    /** This is somewhat similar to displaySlide when called for the current
        slide.  It has been simplified to take advantage of that no slide
        change takes place.  Furthermore it does not show the slide
        transition.
    */
    void redisplayCurrentSlide (void);
    
protected:
    // WeakComponentImplHelperBase
    virtual void SAL_CALL disposing();    
    
    bool isDisposed() const 
    {
        return (rBHelper.bDisposed || rBHelper.bInDispose);
    }
    
private:
    struct SeparateListenerImpl; friend struct SeparateListenerImpl;
    struct PrefetchPropertiesFunc; friend struct PrefetchPropertiesFunc;
    
    /// Stop currently running show.
    void stopShow();
    
    ///Find a polygons vector in maPolygons (map)
    PolygonMap::iterator findPolygons( uno::Reference<drawing::XDrawPage> const& xDrawPage);
    
    /// Creates a new slide.
    SlideSharedPtr makeSlide(
        uno::Reference<drawing::XDrawPage> const& xDrawPage,
        uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
        uno::Reference<animations::XAnimationNode> const& xRootNode );
    
    /// Checks whether the given slide/animation node matches mpPrefetchSlide
    static bool matches(
        SlideSharedPtr const& pSlide,
        uno::Reference<drawing::XDrawPage> const& xSlide,
        uno::Reference<animations::XAnimationNode> const& xNode )
    {
        if (pSlide)
            return (pSlide->getXDrawPage() == xSlide &&
                    pSlide->getXAnimationNode() == xNode);
        else
            return (!xSlide.is() && !xNode.is());
    }
    
    /// Resets the current slide transition sound object with a new one:
    SoundPlayerSharedPtr resetSlideTransitionSound(
		uno::Any const& url = uno::Any(), bool bLoopSound = false );
    
	/// stops the current slide transition sound
	void stopSlideTransitionSound();

    /** Prepare a slide transition
                
        This method registers all necessary events and
        activities for a slide transition.
        
        @return the slide change activity, or NULL for no transition effect
    */
    ActivitySharedPtr createSlideTransition(
        const uno::Reference< drawing::XDrawPage >&    xDrawPage,
        const SlideSharedPtr&                          rLeavingSlide,
        const SlideSharedPtr&                          rEnteringSlide,
        const EventSharedPtr&                          rTransitionEndEvent );
    
    /** Request/release the wait symbol.  The wait symbol is displayed when
        there are more requests then releases.  Locking the wait symbol
        helps to avoid intermediate repaints.
        
        Do not call this method directly.  Use WaitSymbolLock instead.
    */
    void requestWaitSymbol (void);
    void releaseWaitSymbol (void);

    class WaitSymbolLock {public:
        WaitSymbolLock(SlideShowImpl& rSlideShowImpl) : mrSlideShowImpl(rSlideShowImpl)
            { mrSlideShowImpl.requestWaitSymbol(); }
        ~WaitSymbolLock(void)
            { mrSlideShowImpl.releaseWaitSymbol(); }
    private: SlideShowImpl& mrSlideShowImpl;
    };
        

    /// Filter requested cursor shape against hard slideshow cursors (wait, etc.)
    sal_Int16 calcActiveCursor( sal_Int16 nCursorShape ) const;

    /** This method is called asynchronously to finish the rewinding of an
        effect to the previous slide that was initiated earlier.
    */
    void rewindEffectToPreviousSlide (void);

    /// all registered views
    UnoViewContainer                        maViewContainer;
    
    /// all registered slide show listeners
    cppu::OInterfaceContainerHelper         maListenerContainer;
    
    /// map of vectors, containing all registered listeners for a shape
    ShapeEventListenerMap                   maShapeEventListeners;
    /// map of sal_Int16 values, specifying the mouse cursor for every shape
    ShapeCursorMap                          maShapeCursors;
    
    //map of vector of Polygons, containing polygons drawn on each slide.
    PolygonMap                              maPolygons;
    
    boost::optional<RGBColor>               maUserPaintColor;
    
	double									maUserPaintStrokeWidth;
    
    //changed for the eraser project
    boost::optional<bool>		    maEraseAllInk;
    boost::optional<bool>		    maSwitchPenMode;
    boost::optional<bool>		    maSwitchEraserMode;
    boost::optional<sal_Int32>		    maEraseInk;
    //end changed
	
    boost::shared_ptr<canvas::tools::ElapsedTime> mpPresTimer;
    ScreenUpdater                           maScreenUpdater;
    EventQueue                              maEventQueue;
    EventMultiplexer                        maEventMultiplexer;
    ActivitiesQueue                         maActivitiesQueue;
    UserEventQueue                          maUserEventQueue;
    SubsettableShapeManagerSharedPtr        mpDummyPtr;

    boost::shared_ptr<SeparateListenerImpl> mpListener;

    boost::shared_ptr<RehearseTimingsActivity> mpRehearseTimingsActivity;
    boost::shared_ptr<WaitSymbol>           mpWaitSymbol;

    /// the current slide transition sound object:
    SoundPlayerSharedPtr                    mpCurrentSlideTransitionSound;
    
    uno::Reference<uno::XComponentContext>  mxComponentContext;
    uno::Reference<
        presentation::XTransitionFactory>   mxOptionalTransitionFactory;

    /// the previously running slide
    SlideSharedPtr                          mpPreviousSlide;
    /// the currently running slide
    SlideSharedPtr                          mpCurrentSlide;
    /// the already prefetched slide: best candidate for upcoming slide
    SlideSharedPtr                          mpPrefetchSlide;
    /// slide to be prefetched: best candidate for upcoming slide
    uno::Reference<drawing::XDrawPage>      mxPrefetchSlide;
    ///  save the XDrawPagesSupplier to retieve polygons
    uno::Reference<drawing::XDrawPagesSupplier>  mxDrawPagesSupplier;
    /// slide animation to be prefetched:
    uno::Reference<animations::XAnimationNode> mxPrefetchAnimationNode;

    sal_Int16                               mnCurrentCursor;
    
    sal_Int32                               mnWaitSymbolRequestCount;
    bool                                    mbAutomaticAdvancementMode;
    bool                                    mbImageAnimationsAllowed;
    bool                                    mbNoSlideTransitions;
    bool                                    mbMouseVisible;
    bool                                    mbForceManualAdvance;
    bool                                    mbShowPaused;
    bool                                    mbSlideShowIdle;
    bool                                    mbDisableAnimationZOrder;

    EffectRewinder                          maEffectRewinder;
    FrameSynchronization                    maFrameSynchronization;
};


/** Separate event listener for animation, view and hyperlink events.

    This handler is registered for slide animation end, view and
    hyperlink events at the global EventMultiplexer, and forwards
    notifications to the SlideShowImpl
*/
struct SlideShowImpl::SeparateListenerImpl : public EventHandler,
                                             public ViewRepaintHandler,
                                             public HyperlinkHandler,
											 public AnimationEventHandler,
                                             private boost::noncopyable
{
    SlideShowImpl& mrShow;
    ScreenUpdater& mrScreenUpdater;
    EventQueue&    mrEventQueue;

    SeparateListenerImpl( SlideShowImpl& rShow, 
                          ScreenUpdater& rScreenUpdater,
                          EventQueue&    rEventQueue ) :
        mrShow( rShow ), 
        mrScreenUpdater( rScreenUpdater ),
        mrEventQueue( rEventQueue ) 
    {}

    // EventHandler
    virtual bool handleEvent()
    {
        // DON't call notifySlideAnimationsEnded()
        // directly, but queue an event. handleEvent()
        // might be called from e.g.
        // showNext(), and notifySlideAnimationsEnded() must not be called
        // in recursion.  Note that the event is scheduled for the next
        // frame so that its expensive execution does not come in between
        // sprite hiding and shape redraw (at the end of the animation of a
        // shape), which would cause a flicker.
        mrEventQueue.addEventForNextRound(
            makeEvent(
                boost::bind( &SlideShowImpl::notifySlideAnimationsEnded, boost::ref(mrShow) ),
                "SlideShowImpl::notifySlideAnimationsEnded"));
        return true;
    }

    // ViewRepaintHandler
    virtual void viewClobbered( const UnoViewSharedPtr& rView )
    {
        // given view needs repaint, request update
        mrScreenUpdater.notifyUpdate(rView, true);
    }

    // HyperlinkHandler
    virtual bool handleHyperlink( ::rtl::OUString const& rLink )
    {
        return mrShow.notifyHyperLinkClicked(rLink);
    }

	// AnimationEventHandler
    virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
	{
		return mrShow.handleAnimationEvent(rNode);
	}
};


SlideShowImpl::SlideShowImpl(
    uno::Reference<uno::XComponentContext> const& xContext )
    : SlideShowImplBase(m_aMutex),
      maViewContainer(),
      maListenerContainer( m_aMutex ),
      maShapeEventListeners(),
      maShapeCursors(),
      maUserPaintColor(),
      maUserPaintStrokeWidth(4.0),
      mpPresTimer( new canvas::tools::ElapsedTime ),
      maScreenUpdater(maViewContainer),
      maEventQueue( mpPresTimer ),
      maEventMultiplexer( maEventQueue,
                          maViewContainer ),
      maActivitiesQueue( mpPresTimer ),
      maUserEventQueue( maEventMultiplexer, 
                        maEventQueue,
                        *this ),
      mpDummyPtr(),
      mpListener(),
      mpRehearseTimingsActivity(),
      mpWaitSymbol(),
      mpCurrentSlideTransitionSound(),
      mxComponentContext( xContext ),
      mxOptionalTransitionFactory(),
      mpCurrentSlide(),
      mpPrefetchSlide(),
      mxPrefetchSlide(),
      mxDrawPagesSupplier(),
      mxPrefetchAnimationNode(),
      mnCurrentCursor(awt::SystemPointer::ARROW),
      mnWaitSymbolRequestCount(0),
      mbAutomaticAdvancementMode(false),
      mbImageAnimationsAllowed( true ),
      mbNoSlideTransitions( false ),
      mbMouseVisible( true ),
      mbForceManualAdvance( false ),
      mbShowPaused( false ),
      mbSlideShowIdle( true ),
      mbDisableAnimationZOrder( false ),
      maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue),
      maFrameSynchronization(1.0 / FrameRate::PreferredFramesPerSecond)

{
    // keep care not constructing any UNO references to this inside ctor,
    // shift that code to create()!
   
    uno::Reference<lang::XMultiComponentFactory> xFactory( 
        mxComponentContext->getServiceManager() );

    if( xFactory.is() )
    {
        try
	{
            // #i82460# try to retrieve special transition factory
            mxOptionalTransitionFactory.set( 
                xFactory->createInstanceWithContext( 
                    ::rtl::OUString::createFromAscii( "com.sun.star.presentation.TransitionFactory" ),
                    mxComponentContext ), 
                uno::UNO_QUERY );
        }
        catch (loader::CannotActivateFactoryException const&)
	{
	}
    }

    mpListener.reset( new SeparateListenerImpl(
                          *this, 
                          maScreenUpdater,
                          maEventQueue ));
    maEventMultiplexer.addSlideAnimationsEndHandler( mpListener );
    maEventMultiplexer.addViewRepaintHandler( mpListener );
    maEventMultiplexer.addHyperlinkHandler( mpListener, 0.0 );
	maEventMultiplexer.addAnimationStartHandler( mpListener );
	maEventMultiplexer.addAnimationEndHandler( mpListener );
}

// we are about to be disposed (someone call dispose() on us)
void SlideShowImpl::disposing()
{
    osl::MutexGuard const guard( m_aMutex );

    maEffectRewinder.dispose();
    
	// stop slide transition sound, if any:
    stopSlideTransitionSound();

    mxComponentContext.clear();

    if( mpCurrentSlideTransitionSound )
    {
        mpCurrentSlideTransitionSound->dispose();
        mpCurrentSlideTransitionSound.reset();
    }

    mpWaitSymbol.reset();

    if( mpRehearseTimingsActivity ) 
    {
        mpRehearseTimingsActivity->dispose();
        mpRehearseTimingsActivity.reset();
    }

    if( mpListener ) 
    {
        maEventMultiplexer.removeSlideAnimationsEndHandler(mpListener);
        maEventMultiplexer.removeViewRepaintHandler(mpListener);
        maEventMultiplexer.removeHyperlinkHandler(mpListener);
		maEventMultiplexer.removeAnimationStartHandler( mpListener );
		maEventMultiplexer.removeAnimationEndHandler( mpListener );

        mpListener.reset();
    }    

    maUserEventQueue.clear();
    maActivitiesQueue.clear();
    maEventMultiplexer.clear();
    maEventQueue.clear();
    mpPresTimer.reset();
    maShapeCursors.clear();
    maShapeEventListeners.clear();

    // send all listeners a disposing() that we are going down:
    maListenerContainer.disposeAndClear(
        lang::EventObject( static_cast<cppu::OWeakObject *>(this) ) );

    maViewContainer.dispose();

    // release slides:
    mxPrefetchAnimationNode.clear();
    mxPrefetchSlide.clear();
    mpPrefetchSlide.reset();
    mpCurrentSlide.reset();
    mpPreviousSlide.reset();
}

/// stops the current slide transition sound
void SlideShowImpl::stopSlideTransitionSound()
{
    if (mpCurrentSlideTransitionSound) 
    {
        mpCurrentSlideTransitionSound->stopPlayback();
        mpCurrentSlideTransitionSound->dispose();
        mpCurrentSlideTransitionSound.reset();
    }
 }

SoundPlayerSharedPtr SlideShowImpl::resetSlideTransitionSound( const uno::Any& rSound, bool bLoopSound )
{
	sal_Bool bStopSound = sal_False;
	rtl::OUString url;

	if( !(rSound >>= bStopSound) )
		bStopSound = sal_False;
	rSound >>= url;

	if( !bStopSound && (url.getLength() == 0) )
		return SoundPlayerSharedPtr();

	stopSlideTransitionSound();

    if (url.getLength() > 0) 
    {
        try 
        {
            mpCurrentSlideTransitionSound = SoundPlayer::create(
                maEventMultiplexer, url, mxComponentContext );
			mpCurrentSlideTransitionSound->setPlaybackLoop( bLoopSound );
        }
        catch (lang::NoSupportException const&) 
        {
            // catch possible exceptions from SoundPlayer, since
            // being not able to playback the sound is not a hard
            // error here (still, the slide transition should be
            // shown).
        }
    }
    return mpCurrentSlideTransitionSound;
}

ActivitySharedPtr SlideShowImpl::createSlideTransition(
    const uno::Reference< drawing::XDrawPage >& xDrawPage,
    const SlideSharedPtr&                       rLeavingSlide,
    const SlideSharedPtr&                       rEnteringSlide,
    const EventSharedPtr&                       rTransitionEndEvent)
{
    ENSURE_OR_THROW( !maViewContainer.empty(),
                      "createSlideTransition(): No views" );
    ENSURE_OR_THROW( rEnteringSlide,
                      "createSlideTransition(): No entering slide" );
    
    // return empty transition, if slide transitions
    // are disabled.
    if (mbNoSlideTransitions)
        return ActivitySharedPtr();
    
    // retrieve slide change parameters from XDrawPage
    uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
                                                    uno::UNO_QUERY );

    if( !xPropSet.is() )
    {
        OSL_TRACE( "createSlideTransition(): "
                   "Slide has no PropertySet - assuming no transition\n" );
        return ActivitySharedPtr();
    }

    sal_Int16 nTransitionType(0);
    if( !getPropertyValue( nTransitionType,
                           xPropSet,
                           OUSTR("TransitionType" )) )
    {
        OSL_TRACE( "createSlideTransition(): "
                   "Could not extract slide transition type from XDrawPage - assuming no transition\n" );
        return ActivitySharedPtr();
    }
    
    sal_Int16 nTransitionSubType(0);
    if( !getPropertyValue( nTransitionSubType,
                           xPropSet,
                           OUSTR("TransitionSubtype" )) )
    {
        OSL_TRACE( "createSlideTransition(): "
                   "Could not extract slide transition subtype from XDrawPage - assuming no transition\n" );
        return ActivitySharedPtr();
    }
    
    bool bTransitionDirection(false);
    if( !getPropertyValue( bTransitionDirection,
                           xPropSet,
                           OUSTR("TransitionDirection")) )
    {
        OSL_TRACE( "createSlideTransition(): "
                   "Could not extract slide transition direction from XDrawPage - assuming default direction\n" );
    }
    
    sal_Int32 aUnoColor(0);
    if( !getPropertyValue( aUnoColor,
                           xPropSet,
                           OUSTR("TransitionFadeColor")) )
    {
        OSL_TRACE( "createSlideTransition(): "
                   "Could not extract slide transition fade color from XDrawPage - assuming black\n" );
    }

    const RGBColor aTransitionFadeColor( unoColor2RGBColor( aUnoColor ));

	uno::Any aSound;
	sal_Bool bLoopSound = sal_False;

	if( !getPropertyValue( aSound, xPropSet, OUSTR("Sound")) )
		OSL_TRACE( "createSlideTransition(): Could not determine transition sound effect URL from XDrawPage - using no sound\n" );

	if( !getPropertyValue( bLoopSound, xPropSet, OUSTR("LoopSound") ) )
		OSL_TRACE( "createSlideTransition(): Could not get slide property 'LoopSound' - using no sound\n" );
    
    NumberAnimationSharedPtr pTransition(
        TransitionFactory::createSlideTransition(
            rLeavingSlide,
            rEnteringSlide,
            maViewContainer,
            maScreenUpdater,
            maEventMultiplexer,
            mxOptionalTransitionFactory,
            nTransitionType,
            nTransitionSubType,
            bTransitionDirection,
            aTransitionFadeColor,
            resetSlideTransitionSound( aSound, bLoopSound ) ));

    if( !pTransition )
        return ActivitySharedPtr(); // no transition effect has been
                                    // generated. Normally, that means
                                    // that simply no transition is
                                    // set on this slide.

    double nTransitionDuration(0.0);
    if( !getPropertyValue( nTransitionDuration,
                           xPropSet,
                           OUSTR("TransitionDuration")) )
    {
        OSL_TRACE( "createSlideTransition(): "
                   "Could not extract slide transition duration from XDrawPage - assuming no transition\n" );
        return ActivitySharedPtr();
    }
    
    sal_Int32 nMinFrames(5);
    if( !getPropertyValue( nMinFrames,
                           xPropSet,
                           OUSTR("MinimalFrameNumber")) )
    {
        OSL_TRACE( "createSlideTransition(): "
                   "No minimal number of frames given - assuming 5\n" );
    }
    
    // prefetch slide transition bitmaps, but postpone it after
    // displaySlide() has finished - sometimes, view size has not yet
    // reached final size
    maEventQueue.addEvent( 
        makeEvent( 
            boost::bind(
                &::slideshow::internal::Animation::prefetch,
                pTransition,
                AnimatableShapeSharedPtr(),
                ShapeAttributeLayerSharedPtr()),
            "Animation::prefetch"));

    return ActivitySharedPtr(
        ActivitiesFactory::createSimpleActivity(
            ActivitiesFactory::CommonParameters(
                rTransitionEndEvent,
                maEventQueue,
                maActivitiesQueue,
                nTransitionDuration,
                nMinFrames,
                false,
                boost::optional<double>(1.0),
                0.0,
                0.0,
                ShapeSharedPtr(),
                rEnteringSlide->getSlideSize() ),
            pTransition,
            true ));
}

PolygonMap::iterator SlideShowImpl::findPolygons( uno::Reference<drawing::XDrawPage> const& xDrawPage)
{
    // TODO(P2) : Optimze research in the map.
    bool bFound = false;
    PolygonMap::iterator aIter=maPolygons.begin();
        
        	
    while(aIter!=maPolygons.end() && !bFound) 
    {
        if(aIter->first == xDrawPage)
            bFound = true;
        else
            aIter++;
    }

    return aIter;
}    

SlideSharedPtr SlideShowImpl::makeSlide(
    uno::Reference<drawing::XDrawPage> const&          xDrawPage,
    uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
    uno::Reference<animations::XAnimationNode> const&  xRootNode )
{
    if( !xDrawPage.is() )
        return SlideSharedPtr();

    //Retrieve polygons for the current slide
    PolygonMap::iterator aIter;
    aIter = findPolygons(xDrawPage);
    
    const SlideSharedPtr pSlide( createSlide(xDrawPage, 
                                             xDrawPages,
                                             xRootNode,
                                             maEventQueue,
                                             maEventMultiplexer,
                                             maScreenUpdater,
                                             maActivitiesQueue,
                                             maUserEventQueue,
                                             *this,
                                             maViewContainer,
                                             mxComponentContext,
                                             maShapeEventListeners,
                                             maShapeCursors,
                                             (aIter != maPolygons.end()) ? aIter->second :  PolyPolygonVector(),
                                             maUserPaintColor ? *maUserPaintColor : RGBColor(),
											 maUserPaintStrokeWidth,
                                             !!maUserPaintColor,
                                             mbImageAnimationsAllowed,
                                             mbDisableAnimationZOrder) );
    
    // prefetch show content (reducing latency for slide 
    // bitmap and effect start later on)
    pSlide->prefetch();

    return pSlide;
}

void SlideShowImpl::requestWaitSymbol (void)
{
    ++mnWaitSymbolRequestCount;
    OSL_ASSERT(mnWaitSymbolRequestCount>0);

    if (mnWaitSymbolRequestCount == 1)
    {
        if( !mpWaitSymbol )
        {
            // fall back to cursor
            requestCursor(calcActiveCursor(mnCurrentCursor));
        }
        else
            mpWaitSymbol->show();
    }
}
    
void SlideShowImpl::releaseWaitSymbol (void)
{
    --mnWaitSymbolRequestCount;
    OSL_ASSERT(mnWaitSymbolRequestCount>=0);

    if (mnWaitSymbolRequestCount == 0)
    {
        if( !mpWaitSymbol )
        {
            // fall back to cursor
            requestCursor(calcActiveCursor(mnCurrentCursor));
        }
        else
            mpWaitSymbol->hide();
    }
}

sal_Int16 SlideShowImpl::calcActiveCursor( sal_Int16 nCursorShape ) const
{
    if( mnWaitSymbolRequestCount>0 && !mpWaitSymbol ) // enforce wait cursor
        nCursorShape = awt::SystemPointer::WAIT;
    else if( !mbMouseVisible ) // enforce INVISIBLE
        nCursorShape = awt::SystemPointer::INVISIBLE;
    else if( maUserPaintColor &&
             nCursorShape == awt::SystemPointer::ARROW )
        nCursorShape = awt::SystemPointer::PEN;

    return nCursorShape;
}
    

void SlideShowImpl::stopShow()
{
    // Force-end running animation
    // ===========================
    if (mpCurrentSlide)
    {
        mpCurrentSlide->hide();
        //Register polygons in the map
        if(findPolygons(mpCurrentSlide->getXDrawPage()) != maPolygons.end())
            maPolygons.erase(mpCurrentSlide->getXDrawPage());
        
        maPolygons.insert(make_pair(mpCurrentSlide->getXDrawPage(),mpCurrentSlide->getPolygons()));        	
    }
    
    // clear all queues
    maEventQueue.clear();
    maActivitiesQueue.clear();

    // Attention: we MUST clear the user event queue here,
    // this is because the current slide might have registered
    // shape events (click or enter/leave), which might
    // otherwise dangle forever in the queue (because of the
    // shared ptr nature). If someone needs to change this:
    // somehow unregister those shapes at the user event queue
    // on notifySlideEnded().
    maUserEventQueue.clear();

    // re-enable automatic effect advancement
    // (maEventQueue.clear() above might have killed
    // maEventMultiplexer's tick events)
    if (mbAutomaticAdvancementMode) 
    {
        // toggle automatic mode (enabling just again is
        // ignored by EventMultiplexer)
        maEventMultiplexer.setAutomaticMode( false );
        maEventMultiplexer.setAutomaticMode( true );
    }
}



class SlideShowImpl::PrefetchPropertiesFunc 
{
public:
    PrefetchPropertiesFunc( SlideShowImpl * that_,
        bool& rbSkipAllMainSequenceEffects,
        bool& rbSkipSlideTransition)
        : mpSlideShowImpl(that_),
          mrbSkipAllMainSequenceEffects(rbSkipAllMainSequenceEffects),
          mrbSkipSlideTransition(rbSkipSlideTransition)
    {}
    
    void operator()( beans::PropertyValue const& rProperty ) const {
        if (rProperty.Name.equalsAsciiL(
                RTL_CONSTASCII_STRINGPARAM("Prefetch") )) 
        {
            uno::Sequence<uno::Any> seq;
            if ((rProperty.Value >>= seq) && seq.getLength() == 2) 
            {
                seq[0] >>= mpSlideShowImpl->mxPrefetchSlide;
                seq[1] >>= mpSlideShowImpl->mxPrefetchAnimationNode;
            }
        }
        else if (rProperty.Name.equalsAsciiL(
                RTL_CONSTASCII_STRINGPARAM("SkipAllMainSequenceEffects") ))
        {
            rProperty.Value >>= mrbSkipAllMainSequenceEffects;
        }
        else if (rProperty.Name.equalsAsciiL(
                RTL_CONSTASCII_STRINGPARAM("SkipSlideTransition") ))
        {
            rProperty.Value >>= mrbSkipSlideTransition;
        }
        else 
        {
            OSL_ENSURE( false, rtl::OUStringToOString(
                            rProperty.Name, RTL_TEXTENCODING_UTF8 ).getStr() );
        }
    }
private:
    SlideShowImpl *const mpSlideShowImpl;
    bool& mrbSkipAllMainSequenceEffects;
    bool& mrbSkipSlideTransition;
};

void SlideShowImpl::displaySlide(
    uno::Reference<drawing::XDrawPage> const& xSlide,
    uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
    uno::Reference<animations::XAnimationNode> const& xRootNode,
    uno::Sequence<beans::PropertyValue> const& rProperties )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return;

    maEffectRewinder.setRootAnimationNode(xRootNode);

    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    mxDrawPagesSupplier = xDrawPages;
    
    stopShow();  // MUST call that: results in
    // maUserEventQueue.clear(). What's more,
    // stopShow()'s currSlide->hide() call is
    // now also required, notifySlideEnded()
    // relies on that
    // unconditionally. Otherwise, genuine
    // shape animations (drawing layer and
    // GIF) will not be stopped.

    bool bSkipAllMainSequenceEffects (false);
    bool bSkipSlideTransition (false);
    std::for_each( rProperties.getConstArray(),
                   rProperties.getConstArray() + rProperties.getLength(),
        PrefetchPropertiesFunc(this, bSkipAllMainSequenceEffects, bSkipSlideTransition) );
    
    OSL_ENSURE( !maViewContainer.empty(), "### no views!" );
    if (maViewContainer.empty())
        return;

    // this here might take some time
    {
        WaitSymbolLock aLock (*this);
        
        mpPreviousSlide = mpCurrentSlide;
        mpCurrentSlide.reset();

        if (matches( mpPrefetchSlide, xSlide, xRootNode )) 
        {
            // prefetched slide matches:
            mpCurrentSlide = mpPrefetchSlide;
        }
        else 
            mpCurrentSlide = makeSlide( xSlide, xDrawPages, xRootNode );
        
        OSL_ASSERT( mpCurrentSlide );
        if (mpCurrentSlide) 
        {
            basegfx::B2DSize oldSlideSize;
            if( mpPreviousSlide )
                oldSlideSize = mpPreviousSlide->getSlideSize();

            basegfx::B2DSize const slideSize( mpCurrentSlide->getSlideSize() );

            // push new transformation to all views, if size changed
            if( !mpPreviousSlide || oldSlideSize != slideSize )
            {
                std::for_each( maViewContainer.begin(), 
                               maViewContainer.end(),
                               boost::bind( &View::setViewSize, _1,
                                            boost::cref(slideSize) ));
            
                // explicitly notify view change here,
                // because transformation might have changed:
                // optimization, this->notifyViewChange() would
                // repaint slide which is not necessary.
                maEventMultiplexer.notifyViewsChanged();
            }
            
            // create slide transition, and add proper end event 
            // (which then starts the slide effects
            // via CURRENT_SLIDE.show())
            ActivitySharedPtr pSlideChangeActivity (
                createSlideTransition(
                    mpCurrentSlide->getXDrawPage(),
                    mpPreviousSlide,
                    mpCurrentSlide,
                    makeEvent( 
                        boost::bind(
                            &SlideShowImpl::notifySlideTransitionEnded,
                            this,
                            false ),
                        "SlideShowImpl::notifySlideTransitionEnded")));

            if (bSkipSlideTransition)
            {
                // The transition activity was created for the side effects
                // (like sound transitions).  Because we want to skip the
                // acutual transition animation we do not need the activity
                // anymore.
                pSlideChangeActivity.reset();
            }
            
            if (pSlideChangeActivity) 
            {
                // factory generated a slide transition - activate it!
                maActivitiesQueue.addActivity( pSlideChangeActivity );
            }
            else 
            {
                // no transition effect on this slide - schedule slide
                // effect start event right away.
                maEventQueue.addEvent( 
                    makeEvent( 
                        boost::bind(
                            &SlideShowImpl::notifySlideTransitionEnded,
                            this,
                            true ),
                        "SlideShowImpl::notifySlideTransitionEnded"));
            }
        }
    } // finally

    maEventMultiplexer.notifySlideTransitionStarted();
    maListenerContainer.forEach<presentation::XSlideShowListener>(
        boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) );

    // We are currently rewinding an effect.  This lead us from the next
    // slide to this one.  To complete this we have to play back all main
    // sequence effects on this slide.
    if (bSkipAllMainSequenceEffects)
        maEffectRewinder.skipAllMainSequenceEffects();
}

void SlideShowImpl::redisplayCurrentSlide (void)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return;

    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();
    stopShow();
    
    OSL_ENSURE( !maViewContainer.empty(), "### no views!" );
    if (maViewContainer.empty())
        return;

    // No transition effect on this slide - schedule slide
    // effect start event right away.
    maEventQueue.addEvent( 
        makeEvent( 
            boost::bind(
                &SlideShowImpl::notifySlideTransitionEnded,
                this,
                true ),
            "SlideShowImpl::notifySlideTransitionEnded"));

    maEventMultiplexer.notifySlideTransitionStarted();
    maListenerContainer.forEach<presentation::XSlideShowListener>(
        boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) );
}

sal_Bool SlideShowImpl::nextEffect() throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return false;
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    if (mbShowPaused)
        return true;
    else
        return maEventMultiplexer.notifyNextEffect();
}

           
sal_Bool SlideShowImpl::previousEffect() throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return false;
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    if (mbShowPaused)
        return true;
    else
    {
        return maEffectRewinder.rewind(
            maScreenUpdater.createLock(false),
            ::boost::bind<void>(::boost::mem_fn(&SlideShowImpl::redisplayCurrentSlide), this),
            ::boost::bind<void>(::boost::mem_fn(&SlideShowImpl::rewindEffectToPreviousSlide), this));
    }
}

void SlideShowImpl::rewindEffectToPreviousSlide (void)
{
    // Show the wait symbol now and prevent it from showing temporary slide
    // content while effects are played back.
    WaitSymbolLock aLock (*this);

    // A previous call to EffectRewinder::Rewind could not rewind the current
    // effect because there are no effects on the current slide or none has
    // yet been displayed.  Go to the previous slide.
    notifySlideEnded(true);
    
    // Process pending events once more in order to have the following
    // screen update show the last effect.  Not sure whether this should be
    // necessary.
    maEventQueue.forceEmpty();
    
    // We have to call the screen updater before the wait symbol is turned
    // off.  Otherwise the wait symbol would force the display of an
    // intermediate state of the slide (before the effects are replayed.)
    maScreenUpdater.commitUpdates();
}

sal_Bool SlideShowImpl::startShapeActivity(
    uno::Reference<drawing::XShape> const& /*xShape*/ )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    // TODO(F3): NYI
    OSL_ENSURE( false, "not yet implemented!" );
    return false;
}

sal_Bool SlideShowImpl::stopShapeActivity(
    uno::Reference<drawing::XShape> const& /*xShape*/ )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    // TODO(F3): NYI
    OSL_ENSURE( false, "not yet implemented!" );
    return false;
}

sal_Bool SlideShowImpl::pause( sal_Bool bPauseShow )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return false;
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();


    if (bPauseShow)
        mpPresTimer->pauseTimer();
    else
        mpPresTimer->continueTimer();
    
    maEventMultiplexer.notifyPauseMode(bPauseShow);
    
    mbShowPaused = bPauseShow;
    return true;
}

uno::Reference<drawing::XDrawPage> SlideShowImpl::getCurrentSlide()
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return uno::Reference<drawing::XDrawPage>();
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    if (mpCurrentSlide)
        return mpCurrentSlide->getXDrawPage();
    else
        return uno::Reference<drawing::XDrawPage>();
}

sal_Bool SlideShowImpl::addView(
    uno::Reference<presentation::XSlideShowView> const& xView )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return false;
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    // first of all, check if view has a valid canvas
    ENSURE_OR_RETURN_FALSE( xView.is(), "addView(): Invalid view" );
    ENSURE_OR_RETURN_FALSE( xView->getCanvas().is(),
                       "addView(): View does not provide a valid canvas" );
    
    UnoViewSharedPtr const pView( createSlideView(
                                      xView, 
                                      maEventQueue,
                                      maEventMultiplexer ));
    if (!maViewContainer.addView( pView ))
        return false; // view already added
    
    // initialize view content
    // =======================

    if (mpCurrentSlide) 
    {
        // set view transformation
        const basegfx::B2ISize slideSize = mpCurrentSlide->getSlideSize();
        pView->setViewSize( basegfx::B2DSize( slideSize.getX(),
                                              slideSize.getY() ) );
    }

    // clear view area (since its newly added, 
    // we need a clean slate)
    pView->clearAll();

    // broadcast newly added view
    maEventMultiplexer.notifyViewAdded( pView );

    // set current mouse ptr
    pView->setCursorShape( calcActiveCursor(mnCurrentCursor) );

    return true;
}

sal_Bool SlideShowImpl::removeView(
    uno::Reference<presentation::XSlideShowView> const& xView )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    ENSURE_OR_RETURN_FALSE( xView.is(), "removeView(): Invalid view" );
    
    UnoViewSharedPtr const pView( maViewContainer.removeView( xView ) );
    if( !pView )
        return false; // view was not added in the first place
    
    // remove view from EventMultiplexer (mouse events etc.)
    maEventMultiplexer.notifyViewRemoved( pView );
    
    pView->_dispose();

    return true;
}

void SlideShowImpl::registerUserPaintPolygons( const uno::Reference< lang::XMultiServiceFactory >& xDocFactory ) throw (uno::RuntimeException)
{	
    //Retrieve Polygons if user ends presentation by context menu
    if (mpCurrentSlide)
    {
        if(findPolygons(mpCurrentSlide->getXDrawPage()) != maPolygons.end())
            maPolygons.erase(mpCurrentSlide->getXDrawPage());

        maPolygons.insert(make_pair(mpCurrentSlide->getXDrawPage(),mpCurrentSlide->getPolygons()));
    }
     
    //Creating the layer for shapes
    // query for the XLayerManager
    uno::Reference< drawing::XLayerSupplier > xLayerSupplier(xDocFactory, uno::UNO_QUERY);
    uno::Reference< container::XNameAccess > xNameAccess = xLayerSupplier->getLayerManager();
        
    uno::Reference< drawing::XLayerManager > xLayerManager(xNameAccess, uno::UNO_QUERY);
    // create a layer and set its properties
    uno::Reference< drawing::XLayer > xDrawnInSlideshow = xLayerManager->insertNewByIndex(xLayerManager->getCount());
    uno::Reference< beans::XPropertySet > xLayerPropSet(xDrawnInSlideshow, uno::UNO_QUERY);
    
    //Layer Name which enables to catch annotations
    rtl::OUString layerName = rtl::OUString::createFromAscii("DrawnInSlideshow");
    uno::Any aPropLayer;
        
    aPropLayer <<= layerName;
    xLayerPropSet->setPropertyValue(rtl::OUString::createFromAscii("Name"), aPropLayer);
    
    aPropLayer <<= true;
    xLayerPropSet->setPropertyValue(rtl::OUString::createFromAscii("IsVisible"), aPropLayer);
    
    aPropLayer <<= false;
    xLayerPropSet->setPropertyValue(rtl::OUString::createFromAscii("IsLocked"), aPropLayer);

    PolygonMap::iterator aIter=maPolygons.begin();
        
    PolyPolygonVector aPolygons;
    ::cppcanvas::PolyPolygonSharedPtr pPolyPoly;
    ::basegfx::B2DPolyPolygon b2DPolyPoly;
    
    //Register polygons for each slide
    while(aIter!=maPolygons.end()) 
    {
        aPolygons = aIter->second;
        //Get shapes for the slide
        ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > Shapes(aIter->first, ::com::sun::star::uno::UNO_QUERY);
        //Retrieve polygons for one slide
        for( PolyPolygonVector::iterator aIterPoly=aPolygons.begin(), 
                 aEnd=aPolygons.end();
             aIterPoly!=aEnd; ++aIterPoly )
        {        					
            pPolyPoly = (*aIterPoly);
            b2DPolyPoly = ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(pPolyPoly->getUNOPolyPolygon());			
                			
            //Normally there is only one polygon									
            for(sal_uInt32 i=0; i< b2DPolyPoly.count();i++)
            {
                const ::basegfx::B2DPolygon& aPoly =  b2DPolyPoly.getB2DPolygon(i);
                sal_uInt32 nPoints = aPoly.count();
                    					
                if( nPoints > 1)
                {
                    //create the PolyLineShape
                    uno::Reference< uno::XInterface > polyshape(xDocFactory->createInstance(
                                                                    rtl::OUString::createFromAscii("com.sun.star.drawing.PolyLineShape") ) );		
                    uno::Reference< drawing::XShape > rPolyShape(polyshape, uno::UNO_QUERY);
                        				
                    //Add the shape to the slide
                    Shapes->add(rPolyShape);
                        		
                    //Retrieve shape properties 				
                    uno::Reference< beans::XPropertySet > aXPropSet = uno::Reference< beans::XPropertySet >( rPolyShape, uno::UNO_QUERY );
                    //Construct a sequence of points sequence
                    drawing::PointSequenceSequence aRetval;
                    //Create only one sequence for one polygon
                    aRetval.realloc( 1 );
                    // Retrieve the sequence of points from aRetval
                    drawing::PointSequence* pOuterSequence = aRetval.getArray();
                    // Create 2 points in this sequence
                    pOuterSequence->realloc(nPoints);
                    // Get these points which are in an array
                    awt::Point* pInnerSequence = pOuterSequence->getArray();
                    for( sal_uInt32 n = 0; n < nPoints; n++ )
                    {
                        //Create a point from the polygon
                        *pInnerSequence++ = awt::Point( 
                            basegfx::fround(aPoly.getB2DPoint(n).getX()), 
                            basegfx::fround(aPoly.getB2DPoint(n).getY()));
                    }

                    //Fill the properties
                    //Give the built PointSequenceSequence.
                    uno::Any aParam;
                    aParam <<= aRetval;
                    aXPropSet->setPropertyValue( rtl::OUString::createFromAscii("PolyPolygon"), aParam );                        				

                    //LineStyle : SOLID by default
                    uno::Any			aAny;
                    drawing::LineStyle	eLS;
                    eLS = drawing::LineStyle_SOLID;
                    aAny <<= eLS;
                    aXPropSet->setPropertyValue( rtl::OUString::createFromAscii("LineStyle"), aAny );

                    //LineColor
                    sal_uInt32			nLineColor;
                    nLineColor = pPolyPoly->getRGBALineColor();
                    //Transform polygon color from RRGGBBAA to AARRGGBB					
                    aAny <<= RGBAColor2UnoColor(nLineColor);
                    aXPropSet->setPropertyValue( rtl::OUString::createFromAscii("LineColor"), aAny );
                        
                    //LineWidth
                    double				fLineWidth;
                    fLineWidth = pPolyPoly->getStrokeWidth();
                    aAny <<= (sal_Int32)fLineWidth;
                    aXPropSet->setPropertyValue( rtl::OUString::createFromAscii("LineWidth"), aAny );			

                    // make polygons special						
                    xLayerManager->attachShapeToLayer(rPolyShape, xDrawnInSlideshow);
                }
            }			
        }
        ++aIter;
    }
}
        
sal_Bool SlideShowImpl::setProperty( beans::PropertyValue const& rProperty )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return false;

    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("AutomaticAdvancement") ))
    {
        double nTimeout(0.0);
        mbAutomaticAdvancementMode = (rProperty.Value >>= nTimeout);
        if (mbAutomaticAdvancementMode) 
        {
            maEventMultiplexer.setAutomaticTimeout( nTimeout );
        }
        maEventMultiplexer.setAutomaticMode( mbAutomaticAdvancementMode );
        return true;
    }
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("UserPaintColor") ))
    {
        sal_Int32 nColor(0);
        if (rProperty.Value >>= nColor) 
        {
            OSL_ENSURE( mbMouseVisible,
                        "setProperty(): User paint overrides invisible mouse" );

            // enable user paint
            maUserPaintColor.reset( unoColor2RGBColor( nColor ) );
			if( mpCurrentSlide && !mpCurrentSlide->isPaintOverlayActive() )
				mpCurrentSlide->enablePaintOverlay();

			maEventMultiplexer.notifyUserPaintColor( *maUserPaintColor );
        }
        else 
        {
            // disable user paint
            maUserPaintColor.reset();
            maEventMultiplexer.notifyUserPaintDisabled();
			if( mpCurrentSlide )
				mpCurrentSlide->disablePaintOverlay();
        }

        resetCursor();

        return true;
    }
    
	//adding support for erasing features in UserPaintOverlay
	if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("EraseAllInk") ))
	{
		bool nEraseAllInk(false);
		if (rProperty.Value >>= nEraseAllInk) 
		{
		    OSL_ENSURE( mbMouseVisible,
                        "setProperty(): User paint overrides invisible mouse" );
			
		    // enable user paint
		    maEraseAllInk.reset( nEraseAllInk );
		    maEventMultiplexer.notifyEraseAllInk( *maEraseAllInk );
	    }
		
	    return true;
	}

	if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("SwitchPenMode") ))
	{
		bool nSwitchPenMode(false);
		if (rProperty.Value >>= nSwitchPenMode) 
		{
		    OSL_ENSURE( mbMouseVisible,
                        "setProperty(): User paint overrides invisible mouse" );

		    if(nSwitchPenMode == true){
			// Switch to Pen Mode
			maSwitchPenMode.reset( nSwitchPenMode );
			maEventMultiplexer.notifySwitchPenMode();
		    }
		}
		return true;
	}


	if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("SwitchEraserMode") ))
	{
		bool nSwitchEraserMode(false);
		if (rProperty.Value >>= nSwitchEraserMode) 
		{
		    OSL_ENSURE( mbMouseVisible,
                        "setProperty(): User paint overrides invisible mouse" );
		    if(nSwitchEraserMode == true){
			// switch to Eraser mode
			maSwitchEraserMode.reset( nSwitchEraserMode );
			maEventMultiplexer.notifySwitchEraserMode();
		    }
		}
		
		return true;
	}



	if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("EraseInk") ))
	{
		sal_Int32 nEraseInk(100);
		if (rProperty.Value >>= nEraseInk) 
		{
		    OSL_ENSURE( mbMouseVisible,
                        "setProperty(): User paint overrides invisible mouse" );
			
		    // enable user paint
		    maEraseInk.reset( nEraseInk );
		    maEventMultiplexer.notifyEraseInkWidth( *maEraseInk );
		}
		
		return true;
	}
	
	// new Property for pen's width
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("UserPaintStrokeWidth") ))
    {
        double nWidth(4.0);
        if (rProperty.Value >>= nWidth)
        {
            OSL_ENSURE( mbMouseVisible,"setProperty(): User paint overrides invisible mouse" );
            // enable user paint stroke width
            maUserPaintStrokeWidth = nWidth;
            maEventMultiplexer.notifyUserPaintStrokeWidth( maUserPaintStrokeWidth );
        }

        return true;
    }
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("AdvanceOnClick") )) 
    {
        sal_Bool bAdvanceOnClick = sal_False;
        if (! (rProperty.Value >>= bAdvanceOnClick))
            return false;
        maUserEventQueue.setAdvanceOnClick( bAdvanceOnClick );
        return true;
    }            
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("DisableAnimationZOrder") )) 
    {
        sal_Bool bDisableAnimationZOrder = sal_False;
        if (! (rProperty.Value >>= bDisableAnimationZOrder))
            return false;
        mbDisableAnimationZOrder = bDisableAnimationZOrder == sal_True;
        return true;
    }            
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("ImageAnimationsAllowed") ) )
    {
        if (! (rProperty.Value >>= mbImageAnimationsAllowed))
            return false;

        // TODO(F3): Forward to slides!
//         if( bOldValue != mbImageAnimationsAllowed )
//         {
//             if( mbImageAnimationsAllowed )
//                 maEventMultiplexer.notifyIntrinsicAnimationsEnabled();
//             else
//                 maEventMultiplexer.notifyIntrinsicAnimationsDisabled();
//         }

        return true;
    }
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("MouseVisible") ))
    {
        if (! (rProperty.Value >>= mbMouseVisible))
            return false;

        requestCursor(mnCurrentCursor);

        return true;
    }
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("ForceManualAdvance") )) 
    {
        return (rProperty.Value >>= mbForceManualAdvance);
    }
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("RehearseTimings") ))
    {
        bool bRehearseTimings = false;
        if (! (rProperty.Value >>= bRehearseTimings))
            return false;
        
        if (bRehearseTimings) 
        {
            // TODO(Q3): Move to slide
            mpRehearseTimingsActivity = RehearseTimingsActivity::create(
                SlideShowContext(
                    mpDummyPtr,
                    maEventQueue, 
                    maEventMultiplexer, 
                    maScreenUpdater,
                    maActivitiesQueue,
                    maUserEventQueue,
                    *this,
                    maViewContainer,
                    mxComponentContext) );
        }
        else if (mpRehearseTimingsActivity) 
        {
            // removes timer from all views:
            mpRehearseTimingsActivity->dispose();
            mpRehearseTimingsActivity.reset();
        }
        return true;
    }
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("WaitSymbolBitmap") ))
    {
        uno::Reference<rendering::XBitmap> xBitmap;
        if (! (rProperty.Value >>= xBitmap))
            return false;
        
        mpWaitSymbol = WaitSymbol::create( xBitmap, 
                                           maScreenUpdater,
                                           maEventMultiplexer,
                                           maViewContainer );

        return true;
    }
    
    if (rProperty.Name.equalsAsciiL(
            RTL_CONSTASCII_STRINGPARAM("NoSlideTransitions") )) 
    {
        return (rProperty.Value >>= mbNoSlideTransitions);
    }
    
    if (rProperty.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsSoundEnabled")))
    {
        uno::Sequence<uno::Any> aValues;
        uno::Reference<presentation::XSlideShowView> xView;
        sal_Bool bValue (false);
        if ((rProperty.Value >>= aValues)
            && aValues.getLength()==2
            && (aValues[0] >>= xView)
            && (aValues[1] >>= bValue))
        {
            // Look up the view.
            for (UnoViewVector::const_iterator
                     iView (maViewContainer.begin()),
                     iEnd (maViewContainer.end());
                 iView!=iEnd;
                 ++iView)
            {
                if (*iView && (*iView)->getUnoView()==xView)
                {
                    // Store the flag at the view so that media shapes have
                    // access to it.
                    (*iView)->setIsSoundEnabled(bValue);
                    return true;
                }
            }
        }
    }

    return false;
}

void SlideShowImpl::addSlideShowListener(
    uno::Reference<presentation::XSlideShowListener> const& xListener )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return;

    // container syncs with passed mutex ref
    maListenerContainer.addInterface(xListener);
}

void SlideShowImpl::removeSlideShowListener(
    uno::Reference<presentation::XSlideShowListener> const& xListener )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    // container syncs with passed mutex ref
    maListenerContainer.removeInterface(xListener);
}

void SlideShowImpl::addShapeEventListener(
    uno::Reference<presentation::XShapeEventListener> const& xListener,
    uno::Reference<drawing::XShape> const& xShape )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return;
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    ShapeEventListenerMap::iterator aIter;
    if( (aIter=maShapeEventListeners.find( xShape )) ==
        maShapeEventListeners.end() )
    {
        // no entry for this shape -> create one
        aIter = maShapeEventListeners.insert( 
            ShapeEventListenerMap::value_type(
                xShape,
                boost::shared_ptr<cppu::OInterfaceContainerHelper>( 
                    new cppu::OInterfaceContainerHelper(m_aMutex)))).first;    
    }

    // add new listener to broadcaster
    if( aIter->second.get() )
        aIter->second->addInterface( xListener );

    maEventMultiplexer.notifyShapeListenerAdded(xListener,
                                                xShape);
}

void SlideShowImpl::removeShapeEventListener(
    uno::Reference<presentation::XShapeEventListener> const& xListener,
    uno::Reference<drawing::XShape> const& xShape )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    ShapeEventListenerMap::iterator aIter;
    if( (aIter = maShapeEventListeners.find( xShape )) !=
        maShapeEventListeners.end() )
    {
        // entry for this shape found -> remove listener from
        // helper object
        ENSURE_OR_THROW(
            aIter->second.get(),
            "SlideShowImpl::removeShapeEventListener(): "
            "listener map contains NULL broadcast helper" );
        
        aIter->second->removeInterface( xListener );
    }

    maEventMultiplexer.notifyShapeListenerRemoved(xListener,
                                                  xShape);
}

void SlideShowImpl::setShapeCursor(
    uno::Reference<drawing::XShape> const& xShape, sal_Int16 nPointerShape )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return;
    
    // precondition: must only be called from the main thread!
    DBG_TESTSOLARMUTEX();

    ShapeCursorMap::iterator aIter;
    if( (aIter=maShapeCursors.find( xShape )) == maShapeCursors.end() ) 
    {
        // no entry for this shape -> create one
        if( nPointerShape != awt::SystemPointer::ARROW ) 
        {
            // add new entry, unless shape shall display
            // normal pointer arrow -> no need to handle that
            // case
            maShapeCursors.insert(
                ShapeCursorMap::value_type(xShape, 
                                           nPointerShape) );
        }
    }
    else if( nPointerShape == awt::SystemPointer::ARROW ) 
    {
        // shape shall display normal cursor -> can disable
        // the cursor and clear the entry
        maShapeCursors.erase( xShape );
    }
    else 
    {
        // existing entry found, update with new cursor ID
        aIter->second = nPointerShape;
    }

    maEventMultiplexer.notifyShapeCursorChange(xShape, 
                                               nPointerShape);
}

bool SlideShowImpl::requestCursor( sal_Int16 nCursorShape )
{
    mnCurrentCursor = nCursorShape;

    const sal_Int16 nActualCursor = calcActiveCursor(mnCurrentCursor);

    // change all views to the requested cursor ID
    std::for_each( maViewContainer.begin(), 
                   maViewContainer.end(),
                   boost::bind( &View::setCursorShape, 
                                _1, 
                                nActualCursor ));

    return nActualCursor==nCursorShape;
}

void SlideShowImpl::resetCursor()
{
    mnCurrentCursor = awt::SystemPointer::ARROW;

    // change all views to the default cursor ID
    std::for_each( maViewContainer.begin(), 
                   maViewContainer.end(),
                   boost::bind( &View::setCursorShape, 
                                _1, 
                                calcActiveCursor(mnCurrentCursor) ));
}

sal_Bool SlideShowImpl::update( double & nNextTimeout )
    throw (uno::RuntimeException)
{
    osl::MutexGuard const guard( m_aMutex );

    if (isDisposed())
        return false;
    
    // precondition: update() must only be called from the
    // main thread!
    DBG_TESTSOLARMUTEX();

    if( mbShowPaused ) 
    {
        // commit frame (might be repaints pending)
        maScreenUpdater.commitUpdates();

        return false;
    }
    else 
    {
        // TODO(F2): re-evaluate whether that timer lagging makes
        // sense.
        
        // hold timer, while processing the queues:
        // 1. when there is more than one active activity this ensures the
        //    same time for all activities and events
        // 2. processing of events may lead to creation of further events
        //    that have zero delay.  While the timer is stopped these events
        //    are processed in the same run.
        {
            comphelper::ScopeGuard scopeGuard(
                boost::bind( &canvas::tools::ElapsedTime::releaseTimer,
                             boost::cref(mpPresTimer) ) );
            mpPresTimer->holdTimer();

            // process queues
            maEventQueue.process();
            maActivitiesQueue.process();

            // commit frame to screen
            maFrameSynchronization.Synchronize();
            maScreenUpdater.commitUpdates();

            // TODO(Q3): remove need to call dequeued() from
            // activities. feels like a wart.
            //
            // Rationale for ActivitiesQueue::processDequeued(): when
            // an activity ends, it usually pushed the end state to
            // the animated shape in question, and ends the animation
            // (which, in turn, will usually disable shape sprite
            // mode). Disabling shape sprite mode causes shape
            // repaint, which, depending on slide content, takes
            // considerably more time than sprite updates. Thus, the
            // last animation step tends to look delayed. To
            // camouflage this, reaching end position and disabling
            // sprite mode is split into two (normal Activity::end(),
            // and Activity::dequeued()). Now, the reason to call
            // commitUpdates() twice here is caused by the unrelated
            // fact that during wait cursor display/hide, the screen
            // is updated, and shows hidden sprites, but, in case of
            // leaving the second commitUpdates() call out and punting
            // that to the next round, no updated static slide
            // content. In short, the last shape animation of a slide
            // tends to blink at its end.
            
            // process dequeued activities _after_ commit to screen
            maActivitiesQueue.processDequeued();

            // commit frame to screen
            maScreenUpdater.commitUpdates();
        }
        // Time held until here
                
        const bool bActivitiesLeft = (! maActivitiesQueue.isEmpty());
        const bool bTimerEventsLeft = (! maEventQueue.isEmpty());
        const bool bRet = (bActivitiesLeft || bTimerEventsLeft);
                
        if (bRet) 
        {
            // calc nNextTimeout value:
            if (bActivitiesLeft) 
            {
                // Activity queue is not empty.  Tell caller that we would
                // like to render another frame.

                // Return a zero time-out to signal our caller to call us
                // back as soon as possible.  The actual timing, waiting the
                // appropriate amount of time between frames, is then done
                // by the maFrameSynchronization object.
                nNextTimeout = 0;
                maFrameSynchronization.Activate();
            }
            else 
            {
                // timer events left:
                // difference from current time (nota bene:
                // time no longer held here!) to the next event in
                // the event queue.

                // #i61190# Retrieve next timeout only _after_
                // processing activity queue

                // ensure positive value:
                nNextTimeout = std::max( 0.0, maEventQueue.nextTimeout() );

                // There is no active animation so the frame rate does not
                // need to be synchronized.
                maFrameSynchronization.Deactivate();
            }

            mbSlideShowIdle = false;
        }

#if defined(VERBOSE) && defined(DBG_UTIL)
        // when slideshow is idle, issue an XUpdatable::update() call
        // exactly once after a previous animation sequence finished -
        // this might trigger screen dumps on some canvas
        // implementations
        if( !mbSlideShowIdle &&
            (!bRet ||
             nNextTimeout > 1.0) )
        {
            UnoViewVector::const_iterator       aCurr(maViewContainer.begin());
            const UnoViewVector::const_iterator aEnd(maViewContainer.end());
            while( aCurr != aEnd )
            {
                try
                {
                    uno::Reference< presentation::XSlideShowView > xView( (*aCurr)->getUnoView(),
                                                                          uno::UNO_QUERY_THROW );
                    uno::Reference< util::XUpdatable >             xUpdatable( xView->getCanvas(),
                                                                               uno::UNO_QUERY_THROW );
                    xUpdatable->update();
                } 
                catch( uno::RuntimeException& )
                {
                    throw;
                }
                catch( uno::Exception& )
                {
                    OSL_ENSURE( false,
                                rtl::OUStringToOString(
                                    comphelper::anyToString( cppu::getCaughtException() ),
                                    RTL_TEXTENCODING_UTF8 ).getStr() );
                }

                ++aCurr;
            }

            mbSlideShowIdle = true;
        }
#endif
    
        return bRet;
    }
}

void SlideShowImpl::notifySlideTransitionEnded( bool bPaintSlide )
{
    osl::MutexGuard const guard( m_aMutex );

    OSL_ENSURE( !isDisposed(), "### already disposed!" );
    OSL_ENSURE( mpCurrentSlide,
                "notifySlideTransitionEnded(): Invalid current slide" );
    if (mpCurrentSlide) 
    {
		mpCurrentSlide->update_settings( !!maUserPaintColor, maUserPaintColor ? *maUserPaintColor : RGBColor(), maUserPaintStrokeWidth );

		// first init show, to give the animations
        // the chance to register SlideStartEvents
        const bool bBackgroundLayerRendered( !bPaintSlide );
        mpCurrentSlide->show( bBackgroundLayerRendered );
        maEventMultiplexer.notifySlideStartEvent();
    }
}

void queryAutomaticSlideTransition( uno::Reference<drawing::XDrawPage> const& xDrawPage,
                                    double&                                   nAutomaticNextSlideTimeout,
                                    bool&                                     bHasAutomaticNextSlide )
{
    // retrieve slide change parameters from XDrawPage
    // ===============================================

    uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
                                                    uno::UNO_QUERY );
            
    sal_Int32 nChange(0);
    if( !xPropSet.is() ||
        !getPropertyValue( nChange,
                           xPropSet,
                           ::rtl::OUString( 
                               RTL_CONSTASCII_USTRINGPARAM("Change"))) )
    {
        OSL_TRACE(
            "queryAutomaticSlideTransition(): "
            "Could not extract slide change mode from XDrawPage - assuming <none>\n" );
    }
            
    bHasAutomaticNextSlide = nChange == 1;

    if( !xPropSet.is() ||
        !getPropertyValue( nAutomaticNextSlideTimeout,
                           xPropSet,
                           ::rtl::OUString( 
                               RTL_CONSTASCII_USTRINGPARAM("Duration"))) )
    {
        OSL_TRACE(
            "queryAutomaticSlideTransition(): "
            "Could not extract slide transition timeout from "
            "XDrawPage - assuming 1 sec\n" );
    }
}

void SlideShowImpl::notifySlideAnimationsEnded()
{
    osl::MutexGuard const guard( m_aMutex );

    //Draw polygons above animations
    mpCurrentSlide->drawPolygons();
    
    OSL_ENSURE( !isDisposed(), "### already disposed!" );
    
    // This struct will receive the (interruptable) event,
    // that triggers the notifySlideEnded() method.
    InterruptableEventPair aNotificationEvents;

    if( maEventMultiplexer.getAutomaticMode() ) 
    {
        OSL_ENSURE( ! mpRehearseTimingsActivity,
                    "unexpected: RehearseTimings mode!" );
                
        // schedule a slide end event, with automatic mode's
        // delay
        aNotificationEvents = makeInterruptableDelay(
            boost::bind<void>( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
            maEventMultiplexer.getAutomaticTimeout() );
    }
    else 
    {
        OSL_ENSURE( mpCurrentSlide,
                    "notifySlideAnimationsEnded(): Invalid current slide!" );
        
        bool   bHasAutomaticNextSlide=false;
        double nAutomaticNextSlideTimeout=0.0;
        queryAutomaticSlideTransition(mpCurrentSlide->getXDrawPage(),
                                      nAutomaticNextSlideTimeout,
                                      bHasAutomaticNextSlide);

        // check whether slide transition should happen
        // 'automatically'. If yes, simply schedule the
        // specified timeout.
        // NOTE: mbForceManualAdvance and mpRehearseTimingsActivity
        // override any individual slide setting, to always
        // step slides manually.
        if( !mbForceManualAdvance &&
            !mpRehearseTimingsActivity &&
            bHasAutomaticNextSlide )
        {
            aNotificationEvents = makeInterruptableDelay(
                boost::bind<void>( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
                nAutomaticNextSlideTimeout);
            
            // TODO(F2): Provide a mechanism to let the user override   
            // this automatic timeout via next()
        }
        else 
        {
            if (mpRehearseTimingsActivity)
                mpRehearseTimingsActivity->start();
                    
            // generate click event. Thus, the user must
            // trigger the actual end of a slide. No need to
            // generate interruptable event here, there's no
            // timeout involved.
            aNotificationEvents.mpImmediateEvent = 
                makeEvent( boost::bind<void>(
                    boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
                    "SlideShowImpl::notifySlideEnded");
        }
    }
    
    // register events on the queues. To make automatic slide
    // changes interruptable, register the interruption event
    // as a nextEffectEvent target. Note that the timeout
    // event is optional (e.g. manual slide changes don't
    // generate a timeout)            
    maUserEventQueue.registerNextEffectEvent(
        aNotificationEvents.mpImmediateEvent );
    
    if( aNotificationEvents.mpTimeoutEvent )
        maEventQueue.addEvent( aNotificationEvents.mpTimeoutEvent );
    
    // current slide's main sequence is over. Now should be
    // the time to prefetch the next slide (if any), and
    // prepare the initial slide bitmap (speeds up slide
    // change setup time a lot). Show the wait cursor, this
    // indeed might take some seconds.
    {
        WaitSymbolLock aLock (*this);
        
        if (! matches( mpPrefetchSlide,
                       mxPrefetchSlide, mxPrefetchAnimationNode )) 
        {
            mpPrefetchSlide = makeSlide( mxPrefetchSlide, mxDrawPagesSupplier,
                                         mxPrefetchAnimationNode );
        }
        if (mpPrefetchSlide) 
        {
            // ignore return value, this is just to populate
            // Slide's internal bitmap buffer, such that the time
            // needed to generate the slide bitmap is not spent
            // when the slide change is requested.
            mpPrefetchSlide->getCurrentSlideBitmap( *maViewContainer.begin() );
        }
    } // finally

    maListenerContainer.forEach<presentation::XSlideShowListener>(
        boost::mem_fn( &presentation::XSlideShowListener::slideAnimationsEnded ) );
}

void SlideShowImpl::notifySlideEnded (const bool bReverse)
{
    osl::MutexGuard const guard( m_aMutex );

    OSL_ENSURE( !isDisposed(), "### already disposed!" );
    
    if (mpRehearseTimingsActivity && !bReverse) 
    {
        const double time = mpRehearseTimingsActivity->stop();
        if (mpRehearseTimingsActivity->hasBeenClicked()) 
        {
            // save time at current drawpage:
            uno::Reference<beans::XPropertySet> xPropSet(
                mpCurrentSlide->getXDrawPage(), uno::UNO_QUERY );
            OSL_ASSERT( xPropSet.is() );
            if (xPropSet.is()) 
            {
                xPropSet->setPropertyValue(
                    OUSTR("Change"),
                    uno::Any( static_cast<sal_Int32>(1) ) );
                xPropSet->setPropertyValue(
                    OUSTR("Duration"),
                    uno::Any( static_cast<sal_Int32>(time) ) );
            }
        }
    }

    if (bReverse)
        maEventMultiplexer.notifySlideEndEvent();
    
    stopShow();  // MUST call that: results in
                 // maUserEventQueue.clear(). What's more,
                 // stopShow()'s currSlide->hide() call is
                 // now also required, notifySlideEnded()
                 // relies on that
                 // unconditionally. Otherwise, genuine
                 // shape animations (drawing layer and
                 // GIF) will not be stopped.

    maListenerContainer.forEach<presentation::XSlideShowListener>(
        boost::bind<void>(
            ::boost::mem_fn(&presentation::XSlideShowListener::slideEnded),
            _1,
            sal_Bool(bReverse)));
}

bool SlideShowImpl::notifyHyperLinkClicked( rtl::OUString const& hyperLink )
{
    osl::MutexGuard const guard( m_aMutex );

    maListenerContainer.forEach<presentation::XSlideShowListener>(
        boost::bind( &presentation::XSlideShowListener::hyperLinkClicked,
                     _1, 
                     boost::cref(hyperLink) ));
    return true;
}

/** Notification from eventmultiplexer that an animation event has occoured.
	This will be forewarded to all registered XSlideShoeListener
 */
bool SlideShowImpl::handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
{
    osl::MutexGuard const guard( m_aMutex );

	uno::Reference<animations::XAnimationNode> xNode( rNode->getXAnimationNode() );

	switch( rNode->getState() )
	{
	case AnimationNode::ACTIVE:
	    maListenerContainer.forEach<presentation::XSlideShowListener>(
		    boost::bind( &animations::XAnimationListener::beginEvent,
			             _1, 
				         boost::cref(xNode) ));
		break;
		
	case AnimationNode::FROZEN:
	case AnimationNode::ENDED:
	    maListenerContainer.forEach<presentation::XSlideShowListener>(
		    boost::bind( &animations::XAnimationListener::endEvent,
			             _1, 
				         boost::cref(xNode) ));
        if(mpCurrentSlide->isPaintOverlayActive())
           mpCurrentSlide->drawPolygons();
		break;
	default:
		break;
	}

	return true;
}


//===== FrameSynchronization ==================================================

FrameSynchronization::FrameSynchronization (const double nFrameDuration)
    : maTimer(),
      mnFrameDuration(nFrameDuration),
      mnNextFrameTargetTime(0),
      mbIsActive(false)
{
    MarkCurrentFrame();
}




void FrameSynchronization::MarkCurrentFrame (void)
{
    mnNextFrameTargetTime = maTimer.getElapsedTime() + mnFrameDuration;
}




void FrameSynchronization::Synchronize (void)
{
    if (mbIsActive)
    {
        // Do busy waiting for now.
        while (maTimer.getElapsedTime() < mnNextFrameTargetTime)
            ;
    }

    MarkCurrentFrame();
}




void FrameSynchronization::Activate (void)
{
    mbIsActive = true;
}




void FrameSynchronization::Deactivate (void)
{
    mbIsActive = false;
}




double FrameSynchronization::GetCurrentTime (void) const
{
    return maTimer.getElapsedTime();
}


} // anon namespace

namespace sdecl = comphelper::service_decl;
#if defined (__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
 sdecl::class_<SlideShowImpl> serviceImpl;
 const sdecl::ServiceDecl slideShowDecl(
     serviceImpl,
#else
 const sdecl::ServiceDecl slideShowDecl(
     sdecl::class_<SlideShowImpl>(),
#endif
    "com.sun.star.comp.presentation.SlideShow",
    "com.sun.star.presentation.SlideShow" );

// The C shared lib entry points
COMPHELPER_SERVICEDECL_EXPORTS1(slideShowDecl)

