/**************************************************************
 * 
 * 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;
    class PrefetchPropertiesFunc; friend class 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();

            // #118671# the call above may execute a macro bound to an object. In
            // that case this macro may have destroyed this local sliseshow so that it 
            // is disposed (see bugdoc at task). In that case, detect this and exit
            // gently from this slideshow. Do not forget to disable the scoped
            // call to mpPresTimer, this will be deleted if we are disposed.
            if (isDisposed())
            {
                scopeGuard.dismiss();
                return false;
            }

            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)

