LCOV - code coverage report
Current view: top level - slideshow/source/engine - slideshowimpl.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 65 717 9.1 %
Date: 2015-06-13 12:38:46 Functions: 13 62 21.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <canvas/debug.hxx>
      22             : #include <tools/diagnose_ex.h>
      23             : 
      24             : #include <cppuhelper/basemutex.hxx>
      25             : #include <cppuhelper/compbase1.hxx>
      26             : #include <cppuhelper/factory.hxx>
      27             : #include <cppuhelper/implementationentry.hxx>
      28             : #include <cppuhelper/compbase2.hxx>
      29             : #include <cppuhelper/interfacecontainer.h>
      30             : #include <cppuhelper/exc_hlp.hxx>
      31             : 
      32             : #include <comphelper/anytostring.hxx>
      33             : #include <comphelper/make_shared_from_uno.hxx>
      34             : #include <comphelper/scopeguard.hxx>
      35             : #include <comphelper/optional.hxx>
      36             : #include <comphelper/servicedecl.hxx>
      37             : #include <comphelper/namecontainer.hxx>
      38             : 
      39             : #include <cppcanvas/spritecanvas.hxx>
      40             : #include <cppcanvas/vclfactory.hxx>
      41             : #include <cppcanvas/basegfxfactory.hxx>
      42             : 
      43             : #include <tools/debug.hxx>
      44             : 
      45             : #include <basegfx/point/b2dpoint.hxx>
      46             : #include <basegfx/polygon/b2dpolygon.hxx>
      47             : #include <basegfx/matrix/b2dhommatrix.hxx>
      48             : #include <basegfx/polygon/b2dpolygontools.hxx>
      49             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      50             : #include <basegfx/tools/canvastools.hxx>
      51             : 
      52             : #include <vcl/font.hxx>
      53             : #include "rtl/ref.hxx"
      54             : 
      55             : #include <com/sun/star/beans/XPropertySet.hpp>
      56             : #include <com/sun/star/util/XModifyListener.hpp>
      57             : #include <com/sun/star/util/XUpdatable.hpp>
      58             : #include <com/sun/star/awt/XPaintListener.hpp>
      59             : #include <com/sun/star/awt/SystemPointer.hpp>
      60             : #include <com/sun/star/animations/TransitionType.hpp>
      61             : #include <com/sun/star/animations/TransitionSubType.hpp>
      62             : #include <com/sun/star/presentation/XSlideShow.hpp>
      63             : #include <com/sun/star/presentation/XSlideShowListener.hpp>
      64             : #include <com/sun/star/lang/XServiceInfo.hpp>
      65             : #include <com/sun/star/lang/XServiceName.hpp>
      66             : #include <com/sun/star/lang/XComponent.hpp>
      67             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      68             : #include <com/sun/star/drawing/PointSequenceSequence.hpp>
      69             : #include <com/sun/star/drawing/PointSequence.hpp>
      70             : #include <com/sun/star/drawing/XLayer.hpp>
      71             : #include <com/sun/star/drawing/XLayerSupplier.hpp>
      72             : #include <com/sun/star/drawing/XLayerManager.hpp>
      73             : #include <com/sun/star/container/XNameAccess.hpp>
      74             : 
      75             : #include "com/sun/star/uno/Reference.hxx"
      76             : #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
      77             : 
      78             : #include "unoviewcontainer.hxx"
      79             : #include "transitionfactory.hxx"
      80             : #include "eventmultiplexer.hxx"
      81             : #include "usereventqueue.hxx"
      82             : #include "eventqueue.hxx"
      83             : #include "cursormanager.hxx"
      84             : #include "slideshowcontext.hxx"
      85             : #include "activitiesqueue.hxx"
      86             : #include "activitiesfactory.hxx"
      87             : #include "interruptabledelayevent.hxx"
      88             : #include "slide.hxx"
      89             : #include "shapemaps.hxx"
      90             : #include "slideview.hxx"
      91             : #include "tools.hxx"
      92             : #include "unoview.hxx"
      93             : #include "slidebitmap.hxx"
      94             : #include "rehearsetimingsactivity.hxx"
      95             : #include "waitsymbol.hxx"
      96             : #include "effectrewinder.hxx"
      97             : #include "framerate.hxx"
      98             : #include "pointersymbol.hxx"
      99             : 
     100             : #include <boost/noncopyable.hpp>
     101             : #include <boost/bind.hpp>
     102             : 
     103             : #include <map>
     104             : #include <vector>
     105             : #include <iterator>
     106             : #include <string>
     107             : #include <algorithm>
     108             : #include <stdio.h>
     109             : #include <iostream>
     110             : 
     111             : using namespace com::sun::star;
     112             : using namespace ::slideshow::internal;
     113             : 
     114             : namespace {
     115             : 
     116             : /** During animations the update() method tells its caller to call it as
     117             :     soon as possible.  This gives us more time to render the next frame and
     118             :     still maintain a steady frame rate.  This class is responsible for
     119             :     synchronizing the display of new frames and thus keeping the frame rate
     120             :     steady.
     121             : */
     122           1 : class FrameSynchronization
     123             : {
     124             : public:
     125             :     /** Create new object with a predefined duration between two frames.
     126             :         @param nFrameDuration
     127             :             The preferred duration between the display of two frames in
     128             :             seconds.
     129             :     */
     130             :     FrameSynchronization (const double nFrameDuration);
     131             : 
     132             :     /** Set the current time as the time at which the current frame is
     133             :         displayed.  From this the target time of the next frame is derived.
     134             :     */
     135             :     void MarkCurrentFrame();
     136             : 
     137             :     /** When there is time left until the next frame is due then wait.
     138             :         Otherwise return without delay.
     139             :     */
     140             :     void Synchronize();
     141             : 
     142             :     /** Activate frame synchronization when an animation is active and
     143             :         frames are to be displayed in a steady rate.  While active
     144             :         Synchronize() will wait until the frame duration time has passed.
     145             :     */
     146             :     void Activate();
     147             : 
     148             :     /** Deactivate frame sychronization when no animation is active and the
     149             :         time between frames depends on user actions and other external
     150             :         sources.  While deactivated Synchronize() will return without delay.
     151             :     */
     152             :     void Deactivate();
     153             : 
     154             : private:
     155             :     /** The timer that is used for synchronization is independent from the
     156             :         one used by SlideShowImpl: it is not paused or modified by
     157             :         animations.
     158             :     */
     159             :     canvas::tools::ElapsedTime maTimer;
     160             :     /** Time between the display of frames.  Enforced only when mbIsActive
     161             :         is <TRUE/>.
     162             :     */
     163             :     const double mnFrameDuration;
     164             :     /** Time (of maTimer) when the next frame shall be displayed.
     165             :         Synchronize() will wait until this time.
     166             :     */
     167             :     double mnNextFrameTargetTime;
     168             :     /** Synchronize() will wait only when this flag is <TRUE/>.  Otherwise
     169             :         it returns immediately.
     170             :     */
     171             :     bool mbIsActive;
     172             : };
     173             : 
     174             : /******************************************************************************
     175             : 
     176             :    SlideShowImpl
     177             : 
     178             :    This class encapsulates the slideshow presentation viewer.
     179             : 
     180             :    With an instance of this class, it is possible to statically
     181             :    and dynamically show a presentation, as defined by the
     182             :    constructor-provided draw model (represented by a sequence
     183             :    of ::com::sun::star::drawing::XDrawPage objects).
     184             : 
     185             :    It is possible to show the presentation on multiple views
     186             :    simultaneously (e.g. for a multi-monitor setup). Since this
     187             :    class also relies on user interaction, the corresponding
     188             :    XSlideShowView interface provides means to register some UI
     189             :    event listeners (mostly borrowed from awt::XWindow interface).
     190             : 
     191             :    Since currently (mid 2004), OOo isn't very well suited to
     192             :    multi-threaded rendering, this class relies on <em>very
     193             :    frequent</em> external update() calls, which will render the
     194             :    next frame of animations. This works as follows: after the
     195             :    displaySlide() has been successfully called (which setup and
     196             :    starts an actual slide show), the update() method must be
     197             :    called until it returns false.
     198             :    Effectively, this puts the burden of providing
     199             :    concurrency to the clients of this class, which, as noted
     200             :    above, is currently unavoidable with the current state of
     201             :    affairs (I've actually tried threading here, but failed
     202             :    miserably when using the VCL canvas as the render backend -
     203             :    deadlocked).
     204             : 
     205             :  ******************************************************************************/
     206             : 
     207             : typedef cppu::WeakComponentImplHelper1<presentation::XSlideShow> SlideShowImplBase;
     208             : 
     209             : typedef ::std::vector< ::cppcanvas::PolyPolygonSharedPtr> PolyPolygonVector;
     210             : 
     211             : /// Maps XDrawPage for annotations persistence
     212             : typedef ::std::map< ::com::sun::star::uno::Reference<
     213             :                                     ::com::sun::star::drawing::XDrawPage>,
     214             :                                     PolyPolygonVector>  PolygonMap;
     215             : 
     216           1 : class SlideShowImpl : private cppu::BaseMutex,
     217             :                       public CursorManager,
     218             :                       public SlideShowImplBase
     219             : {
     220             : public:
     221             :     explicit SlideShowImpl(
     222             :         uno::Reference<uno::XComponentContext> const& xContext );
     223             : 
     224             :     /** Notify that the transition phase of the current slide
     225             :         has ended.
     226             : 
     227             :         The life of a slide has three phases: the transition
     228             :         phase, when the previous slide vanishes, and the
     229             :         current slide becomes visible, the shape animation
     230             :         phase, when shape effects are running, and the phase
     231             :         after the last shape animation has ended, but before
     232             :         the next slide transition starts.
     233             : 
     234             :         This method notifies the end of the first phase.
     235             : 
     236             :         @param bPaintSlide
     237             :         When true, Slide::show() is passed a true as well, denoting
     238             :         explicit paint of slide content. Pass false here, if e.g. a
     239             :         slide transition has already rendered the initial slide image.
     240             :     */
     241             :     void notifySlideTransitionEnded( bool bPaintSlide );
     242             : 
     243             :     /** Notify that the shape animation phase of the current slide
     244             :         has ended.
     245             : 
     246             :         The life of a slide has three phases: the transition
     247             :         phase, when the previous slide vanishes, and the
     248             :         current slide becomes visible, the shape animation
     249             :         phase, when shape effects are running, and the phase
     250             :         after the last shape animation has ended, but before
     251             :         the next slide transition starts.
     252             : 
     253             :         This method notifies the end of the second phase.
     254             :     */
     255             :     void notifySlideAnimationsEnded();
     256             : 
     257             :     /** Notify that the slide has ended.
     258             : 
     259             :         The life of a slide has three phases: the transition
     260             :         phase, when the previous slide vanishes, and the
     261             :         current slide becomes visible, the shape animation
     262             :         phase, when shape effects are running, and the phase
     263             :         after the last shape animation has ended, but before
     264             :         the next slide transition starts.
     265             : 
     266             :         This method notifies the end of the third phase.
     267             :     */
     268             :     void notifySlideEnded (const bool bReverse);
     269             : 
     270             :     /** Notification from eventmultiplexer that a hyperlink
     271             :         has been clicked.
     272             :     */
     273             :     bool notifyHyperLinkClicked( OUString const& hyperLink );
     274             : 
     275             :     /** Notification from eventmultiplexer that an animation event has occoured.
     276             :         This will be forewarded to all registered XSlideShowListener
     277             :      */
     278             :     bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode );
     279             : 
     280             : private:
     281             :     // XSlideShow:
     282             :     virtual sal_Bool SAL_CALL nextEffect() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     283             :     virtual sal_Bool SAL_CALL previousEffect() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     284             :     virtual sal_Bool SAL_CALL startShapeActivity(
     285             :         uno::Reference<drawing::XShape> const& xShape )
     286             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     287             :     virtual sal_Bool SAL_CALL stopShapeActivity(
     288             :         uno::Reference<drawing::XShape> const& xShape )
     289             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     290             :     virtual sal_Bool SAL_CALL pause( sal_Bool bPauseShow )
     291             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     292             :     virtual uno::Reference<drawing::XDrawPage> SAL_CALL getCurrentSlide()
     293             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     294             :     virtual void SAL_CALL displaySlide(
     295             :         uno::Reference<drawing::XDrawPage> const& xSlide,
     296             :         uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
     297             :         uno::Reference<animations::XAnimationNode> const& xRootNode,
     298             :         uno::Sequence<beans::PropertyValue> const& rProperties )
     299             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     300             :     virtual void SAL_CALL registerUserPaintPolygons( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xDocFactory ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     301             :     virtual sal_Bool SAL_CALL setProperty(
     302             :         beans::PropertyValue const& rProperty ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     303             :     virtual sal_Bool SAL_CALL addView(
     304             :         uno::Reference<presentation::XSlideShowView> const& xView )
     305             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     306             :     virtual sal_Bool SAL_CALL removeView(
     307             :         uno::Reference<presentation::XSlideShowView> const& xView )
     308             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     309             :     virtual sal_Bool SAL_CALL update( double & nNextTimeout )
     310             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     311             :     virtual void SAL_CALL addSlideShowListener(
     312             :         uno::Reference<presentation::XSlideShowListener> const& xListener )
     313             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     314             :     virtual void SAL_CALL removeSlideShowListener(
     315             :         uno::Reference<presentation::XSlideShowListener> const& xListener )
     316             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     317             :     virtual void SAL_CALL addShapeEventListener(
     318             :         uno::Reference<presentation::XShapeEventListener> const& xListener,
     319             :         uno::Reference<drawing::XShape> const& xShape )
     320             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     321             :     virtual void SAL_CALL removeShapeEventListener(
     322             :         uno::Reference<presentation::XShapeEventListener> const& xListener,
     323             :         uno::Reference<drawing::XShape> const& xShape )
     324             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     325             :     virtual void SAL_CALL setShapeCursor(
     326             :         uno::Reference<drawing::XShape> const& xShape, sal_Int16 nPointerShape )
     327             :         throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     328             : 
     329             :     // CursorManager
     330             : 
     331             : 
     332             :     virtual bool requestCursor( sal_Int16 nCursorShape ) SAL_OVERRIDE;
     333             :     virtual void resetCursor() SAL_OVERRIDE;
     334             : 
     335             :     /** This is somewhat similar to displaySlide when called for the current
     336             :         slide.  It has been simplified to take advantage of that no slide
     337             :         change takes place.  Furthermore it does not show the slide
     338             :         transition.
     339             :     */
     340             :     void redisplayCurrentSlide();
     341             : 
     342             : protected:
     343             :     // WeakComponentImplHelperBase
     344             :     virtual void SAL_CALL disposing() SAL_OVERRIDE;
     345             : 
     346           0 :     bool isDisposed() const
     347             :     {
     348           0 :         return (rBHelper.bDisposed || rBHelper.bInDispose);
     349             :     }
     350             : 
     351             : private:
     352             :     struct SeparateListenerImpl; friend struct SeparateListenerImpl;
     353             :     class PrefetchPropertiesFunc; friend class PrefetchPropertiesFunc;
     354             : 
     355             :     /// Stop currently running show.
     356             :     void stopShow();
     357             : 
     358             :     ///Find a polygons vector in maPolygons (map)
     359             :     PolygonMap::iterator findPolygons( uno::Reference<drawing::XDrawPage> const& xDrawPage);
     360             : 
     361             :     /// Creates a new slide.
     362             :     SlideSharedPtr makeSlide(
     363             :         uno::Reference<drawing::XDrawPage> const& xDrawPage,
     364             :         uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
     365             :         uno::Reference<animations::XAnimationNode> const& xRootNode );
     366             : 
     367             :     /// Checks whether the given slide/animation node matches mpPrefetchSlide
     368           0 :     static bool matches(
     369             :         SlideSharedPtr const& pSlide,
     370             :         uno::Reference<drawing::XDrawPage> const& xSlide,
     371             :         uno::Reference<animations::XAnimationNode> const& xNode )
     372             :     {
     373           0 :         if (pSlide)
     374           0 :             return (pSlide->getXDrawPage() == xSlide &&
     375           0 :                     pSlide->getXAnimationNode() == xNode);
     376             :         else
     377           0 :             return (!xSlide.is() && !xNode.is());
     378             :     }
     379             : 
     380             :     /// Resets the current slide transition sound object with a new one:
     381             :     SoundPlayerSharedPtr resetSlideTransitionSound(
     382             :         uno::Any const& url = uno::Any(), bool bLoopSound = false );
     383             : 
     384             :     /// stops the current slide transition sound
     385             :     void stopSlideTransitionSound();
     386             : 
     387             :     /** Prepare a slide transition
     388             : 
     389             :         This method registers all necessary events and
     390             :         activities for a slide transition.
     391             : 
     392             :         @return the slide change activity, or NULL for no transition effect
     393             :     */
     394             :     ActivitySharedPtr createSlideTransition(
     395             :         const uno::Reference< drawing::XDrawPage >&    xDrawPage,
     396             :         const SlideSharedPtr&                          rLeavingSlide,
     397             :         const SlideSharedPtr&                          rEnteringSlide,
     398             :         const EventSharedPtr&                          rTransitionEndEvent );
     399             : 
     400             :     /** Request/release the wait symbol.  The wait symbol is displayed when
     401             :         there are more requests then releases.  Locking the wait symbol
     402             :         helps to avoid intermediate repaints.
     403             : 
     404             :         Do not call this method directly.  Use WaitSymbolLock instead.
     405             :     */
     406             :     void requestWaitSymbol();
     407             :     void releaseWaitSymbol();
     408             : 
     409             :     class WaitSymbolLock {public:
     410           0 :         WaitSymbolLock(SlideShowImpl& rSlideShowImpl) : mrSlideShowImpl(rSlideShowImpl)
     411           0 :             { mrSlideShowImpl.requestWaitSymbol(); }
     412           0 :         ~WaitSymbolLock()
     413           0 :             { mrSlideShowImpl.releaseWaitSymbol(); }
     414             :     private: SlideShowImpl& mrSlideShowImpl;
     415             :     };
     416             : 
     417             :     /// Filter requested cursor shape against hard slideshow cursors (wait, etc.)
     418             :     sal_Int16 calcActiveCursor( sal_Int16 nCursorShape ) const;
     419             : 
     420             :     /** This method is called asynchronously to finish the rewinding of an
     421             :         effect to the previous slide that was initiated earlier.
     422             :     */
     423             :     void rewindEffectToPreviousSlide();
     424             : 
     425             :     /// all registered views
     426             :     UnoViewContainer                        maViewContainer;
     427             : 
     428             :     /// all registered slide show listeners
     429             :     cppu::OInterfaceContainerHelper         maListenerContainer;
     430             : 
     431             :     /// map of vectors, containing all registered listeners for a shape
     432             :     ShapeEventListenerMap                   maShapeEventListeners;
     433             :     /// map of sal_Int16 values, specifying the mouse cursor for every shape
     434             :     ShapeCursorMap                          maShapeCursors;
     435             : 
     436             :     //map of vector of Polygons, containing polygons drawn on each slide.
     437             :     PolygonMap                              maPolygons;
     438             : 
     439             :     boost::optional<RGBColor>               maUserPaintColor;
     440             : 
     441             :     double                                  maUserPaintStrokeWidth;
     442             : 
     443             :     //changed for the eraser project
     444             :     boost::optional<bool>           maEraseAllInk;
     445             :     boost::optional<bool>           maSwitchPenMode;
     446             :     boost::optional<bool>           maSwitchEraserMode;
     447             :     boost::optional<sal_Int32>          maEraseInk;
     448             :     //end changed
     449             : 
     450             :     boost::shared_ptr<canvas::tools::ElapsedTime> mpPresTimer;
     451             :     ScreenUpdater                           maScreenUpdater;
     452             :     EventQueue                              maEventQueue;
     453             :     EventMultiplexer                        maEventMultiplexer;
     454             :     ActivitiesQueue                         maActivitiesQueue;
     455             :     UserEventQueue                          maUserEventQueue;
     456             :     SubsettableShapeManagerSharedPtr        mpDummyPtr;
     457             : 
     458             :     boost::shared_ptr<SeparateListenerImpl> mpListener;
     459             : 
     460             :     boost::shared_ptr<RehearseTimingsActivity> mpRehearseTimingsActivity;
     461             :     boost::shared_ptr<WaitSymbol>           mpWaitSymbol;
     462             : 
     463             :     boost::shared_ptr<PointerSymbol>        mpPointerSymbol;
     464             : 
     465             :     /// the current slide transition sound object:
     466             :     SoundPlayerSharedPtr                    mpCurrentSlideTransitionSound;
     467             : 
     468             :     uno::Reference<uno::XComponentContext>  mxComponentContext;
     469             :     uno::Reference<
     470             :         presentation::XTransitionFactory>   mxOptionalTransitionFactory;
     471             : 
     472             :     /// the previously running slide
     473             :     SlideSharedPtr                          mpPreviousSlide;
     474             :     /// the currently running slide
     475             :     SlideSharedPtr                          mpCurrentSlide;
     476             :     /// the already prefetched slide: best candidate for upcoming slide
     477             :     SlideSharedPtr                          mpPrefetchSlide;
     478             :     /// slide to be prefetched: best candidate for upcoming slide
     479             :     uno::Reference<drawing::XDrawPage>      mxPrefetchSlide;
     480             :     ///  save the XDrawPagesSupplier to retieve polygons
     481             :     uno::Reference<drawing::XDrawPagesSupplier>  mxDrawPagesSupplier;
     482             :     /// slide animation to be prefetched:
     483             :     uno::Reference<animations::XAnimationNode> mxPrefetchAnimationNode;
     484             : 
     485             :     sal_Int16                               mnCurrentCursor;
     486             : 
     487             :     sal_Int32                               mnWaitSymbolRequestCount;
     488             :     bool                                    mbAutomaticAdvancementMode;
     489             :     bool                                    mbImageAnimationsAllowed;
     490             :     bool                                    mbNoSlideTransitions;
     491             :     bool                                    mbMouseVisible;
     492             :     bool                                    mbForceManualAdvance;
     493             :     bool                                    mbShowPaused;
     494             :     bool                                    mbSlideShowIdle;
     495             :     bool                                    mbDisableAnimationZOrder;
     496             : 
     497             :     EffectRewinder                          maEffectRewinder;
     498             :     FrameSynchronization                    maFrameSynchronization;
     499             : };
     500             : 
     501             : /** Separate event listener for animation, view and hyperlink events.
     502             : 
     503             :     This handler is registered for slide animation end, view and
     504             :     hyperlink events at the global EventMultiplexer, and forwards
     505             :     notifications to the SlideShowImpl
     506             : */
     507           2 : struct SlideShowImpl::SeparateListenerImpl : public EventHandler,
     508             :                                              public ViewRepaintHandler,
     509             :                                              public HyperlinkHandler,
     510             :                                              public AnimationEventHandler,
     511             :                                              private boost::noncopyable
     512             : {
     513             :     SlideShowImpl& mrShow;
     514             :     ScreenUpdater& mrScreenUpdater;
     515             :     EventQueue&    mrEventQueue;
     516             : 
     517           1 :     SeparateListenerImpl( SlideShowImpl& rShow,
     518             :                           ScreenUpdater& rScreenUpdater,
     519             :                           EventQueue&    rEventQueue ) :
     520             :         mrShow( rShow ),
     521             :         mrScreenUpdater( rScreenUpdater ),
     522           1 :         mrEventQueue( rEventQueue )
     523           1 :     {}
     524             : 
     525             :     // EventHandler
     526           0 :     virtual bool handleEvent() SAL_OVERRIDE
     527             :     {
     528             :         // DON't call notifySlideAnimationsEnded()
     529             :         // directly, but queue an event. handleEvent()
     530             :         // might be called from e.g.
     531             :         // showNext(), and notifySlideAnimationsEnded() must not be called
     532             :         // in recursion.  Note that the event is scheduled for the next
     533             :         // frame so that its expensive execution does not come in between
     534             :         // sprite hiding and shape redraw (at the end of the animation of a
     535             :         // shape), which would cause a flicker.
     536             :         mrEventQueue.addEventForNextRound(
     537           0 :             makeEvent(
     538             :                 boost::bind( &SlideShowImpl::notifySlideAnimationsEnded, boost::ref(mrShow) ),
     539           0 :                 "SlideShowImpl::notifySlideAnimationsEnded"));
     540           0 :         return true;
     541             :     }
     542             : 
     543             :     // ViewRepaintHandler
     544           0 :     virtual void viewClobbered( const UnoViewSharedPtr& rView ) SAL_OVERRIDE
     545             :     {
     546             :         // given view needs repaint, request update
     547           0 :         mrScreenUpdater.notifyUpdate(rView, true);
     548           0 :     }
     549             : 
     550             :     // HyperlinkHandler
     551           0 :     virtual bool handleHyperlink( OUString const& rLink ) SAL_OVERRIDE
     552             :     {
     553           0 :         return mrShow.notifyHyperLinkClicked(rLink);
     554             :     }
     555             : 
     556             :     // AnimationEventHandler
     557           0 :     virtual bool handleAnimationEvent( const AnimationNodeSharedPtr& rNode ) SAL_OVERRIDE
     558             :     {
     559           0 :         return mrShow.handleAnimationEvent(rNode);
     560             :     }
     561             : };
     562             : 
     563           1 : SlideShowImpl::SlideShowImpl(
     564             :     uno::Reference<uno::XComponentContext> const& xContext )
     565             :     : SlideShowImplBase(m_aMutex),
     566             :       maViewContainer(),
     567             :       maListenerContainer( m_aMutex ),
     568             :       maShapeEventListeners(),
     569             :       maShapeCursors(),
     570             :       maUserPaintColor(),
     571             :       maUserPaintStrokeWidth(4.0),
     572           1 :       mpPresTimer( new canvas::tools::ElapsedTime ),
     573             :       maScreenUpdater(maViewContainer),
     574             :       maEventQueue( mpPresTimer ),
     575             :       maEventMultiplexer( maEventQueue,
     576             :                           maViewContainer ),
     577             :       maActivitiesQueue( mpPresTimer ),
     578             :       maUserEventQueue( maEventMultiplexer,
     579             :                         maEventQueue,
     580             :                         *this ),
     581             :       mpDummyPtr(),
     582             :       mpListener(),
     583             :       mpRehearseTimingsActivity(),
     584             :       mpWaitSymbol(),
     585             :       mpPointerSymbol(),
     586             :       mpCurrentSlideTransitionSound(),
     587             :       mxComponentContext( xContext ),
     588             :       mxOptionalTransitionFactory(),
     589             :       mpCurrentSlide(),
     590             :       mpPrefetchSlide(),
     591             :       mxPrefetchSlide(),
     592             :       mxDrawPagesSupplier(),
     593             :       mxPrefetchAnimationNode(),
     594             :       mnCurrentCursor(awt::SystemPointer::ARROW),
     595             :       mnWaitSymbolRequestCount(0),
     596             :       mbAutomaticAdvancementMode(false),
     597             :       mbImageAnimationsAllowed( true ),
     598             :       mbNoSlideTransitions( false ),
     599             :       mbMouseVisible( true ),
     600             :       mbForceManualAdvance( false ),
     601             :       mbShowPaused( false ),
     602             :       mbSlideShowIdle( true ),
     603             :       mbDisableAnimationZOrder( false ),
     604             :       maEffectRewinder(maEventMultiplexer, maEventQueue, maUserEventQueue),
     605           2 :       maFrameSynchronization(1.0 / FrameRate::PreferredFramesPerSecond)
     606             : 
     607             : {
     608             :     // keep care not constructing any UNO references to this inside ctor,
     609             :     // shift that code to create()!
     610             : 
     611             :     uno::Reference<lang::XMultiComponentFactory> xFactory(
     612           1 :         mxComponentContext->getServiceManager() );
     613             : 
     614           1 :     if( xFactory.is() )
     615             :     {
     616             :         try
     617             :     {
     618             :             // #i82460# try to retrieve special transition factory
     619             :             mxOptionalTransitionFactory.set(
     620           1 :                 xFactory->createInstanceWithContext(
     621             :                     OUString("com.sun.star.presentation.TransitionFactory" ),
     622           1 :                     mxComponentContext ),
     623           1 :                 uno::UNO_QUERY );
     624             :         }
     625           0 :         catch (loader::CannotActivateFactoryException const&)
     626             :     {
     627             :     }
     628             :     }
     629             : 
     630             :     mpListener.reset( new SeparateListenerImpl(
     631             :                           *this,
     632             :                           maScreenUpdater,
     633           1 :                           maEventQueue ));
     634           1 :     maEventMultiplexer.addSlideAnimationsEndHandler( mpListener );
     635           1 :     maEventMultiplexer.addViewRepaintHandler( mpListener );
     636           1 :     maEventMultiplexer.addHyperlinkHandler( mpListener, 0.0 );
     637           1 :     maEventMultiplexer.addAnimationStartHandler( mpListener );
     638           1 :     maEventMultiplexer.addAnimationEndHandler( mpListener );
     639           1 : }
     640             : 
     641             : // we are about to be disposed (someone call dispose() on us)
     642           1 : void SlideShowImpl::disposing()
     643             : {
     644           1 :     osl::MutexGuard const guard( m_aMutex );
     645             : 
     646           1 :     maEffectRewinder.dispose();
     647             : 
     648             :     // stop slide transition sound, if any:
     649           1 :     stopSlideTransitionSound();
     650             : 
     651           1 :     mxComponentContext.clear();
     652             : 
     653           1 :     if( mpCurrentSlideTransitionSound )
     654             :     {
     655           0 :         mpCurrentSlideTransitionSound->dispose();
     656           0 :         mpCurrentSlideTransitionSound.reset();
     657             :     }
     658             : 
     659           1 :     mpWaitSymbol.reset();
     660           1 :     mpPointerSymbol.reset();
     661             : 
     662           1 :     if( mpRehearseTimingsActivity )
     663             :     {
     664           0 :         mpRehearseTimingsActivity->dispose();
     665           0 :         mpRehearseTimingsActivity.reset();
     666             :     }
     667             : 
     668           1 :     if( mpListener )
     669             :     {
     670           1 :         maEventMultiplexer.removeSlideAnimationsEndHandler(mpListener);
     671           1 :         maEventMultiplexer.removeViewRepaintHandler(mpListener);
     672           1 :         maEventMultiplexer.removeHyperlinkHandler(mpListener);
     673           1 :         maEventMultiplexer.removeAnimationStartHandler( mpListener );
     674           1 :         maEventMultiplexer.removeAnimationEndHandler( mpListener );
     675             : 
     676           1 :         mpListener.reset();
     677             :     }
     678             : 
     679           1 :     maUserEventQueue.clear();
     680           1 :     maActivitiesQueue.clear();
     681           1 :     maEventMultiplexer.clear();
     682           1 :     maEventQueue.clear();
     683           1 :     mpPresTimer.reset();
     684           1 :     maShapeCursors.clear();
     685           1 :     maShapeEventListeners.clear();
     686             : 
     687             :     // send all listeners a disposing() that we are going down:
     688             :     maListenerContainer.disposeAndClear(
     689           1 :         lang::EventObject( static_cast<cppu::OWeakObject *>(this) ) );
     690             : 
     691           1 :     maViewContainer.dispose();
     692             : 
     693             :     // release slides:
     694           1 :     mxPrefetchAnimationNode.clear();
     695           1 :     mxPrefetchSlide.clear();
     696           1 :     mpPrefetchSlide.reset();
     697           1 :     mpCurrentSlide.reset();
     698           1 :     mpPreviousSlide.reset();
     699           1 : }
     700             : 
     701             : /// stops the current slide transition sound
     702           1 : void SlideShowImpl::stopSlideTransitionSound()
     703             : {
     704           1 :     if (mpCurrentSlideTransitionSound)
     705             :     {
     706           0 :         mpCurrentSlideTransitionSound->stopPlayback();
     707           0 :         mpCurrentSlideTransitionSound->dispose();
     708           0 :         mpCurrentSlideTransitionSound.reset();
     709             :     }
     710           1 :  }
     711             : 
     712           0 : SoundPlayerSharedPtr SlideShowImpl::resetSlideTransitionSound( const uno::Any& rSound, bool bLoopSound )
     713             : {
     714           0 :     bool bStopSound = false;
     715           0 :     OUString url;
     716             : 
     717           0 :     if( !(rSound >>= bStopSound) )
     718           0 :         bStopSound = false;
     719           0 :     rSound >>= url;
     720             : 
     721           0 :     if( !bStopSound && url.isEmpty() )
     722           0 :         return SoundPlayerSharedPtr();
     723             : 
     724           0 :     stopSlideTransitionSound();
     725             : 
     726           0 :     if (!url.isEmpty())
     727             :     {
     728             :         try
     729             :         {
     730           0 :             mpCurrentSlideTransitionSound = SoundPlayer::create(
     731           0 :                 maEventMultiplexer, url, mxComponentContext );
     732           0 :             mpCurrentSlideTransitionSound->setPlaybackLoop( bLoopSound );
     733             :         }
     734           0 :         catch (lang::NoSupportException const&)
     735             :         {
     736             :             // catch possible exceptions from SoundPlayer, since
     737             :             // being not able to playback the sound is not a hard
     738             :             // error here (still, the slide transition should be
     739             :             // shown).
     740             :         }
     741             :     }
     742           0 :     return mpCurrentSlideTransitionSound;
     743             : }
     744             : 
     745           0 : ActivitySharedPtr SlideShowImpl::createSlideTransition(
     746             :     const uno::Reference< drawing::XDrawPage >& xDrawPage,
     747             :     const SlideSharedPtr&                       rLeavingSlide,
     748             :     const SlideSharedPtr&                       rEnteringSlide,
     749             :     const EventSharedPtr&                       rTransitionEndEvent)
     750             : {
     751           0 :     ENSURE_OR_THROW( !maViewContainer.empty(),
     752             :                       "createSlideTransition(): No views" );
     753           0 :     ENSURE_OR_THROW( rEnteringSlide,
     754             :                       "createSlideTransition(): No entering slide" );
     755             : 
     756             :     // return empty transition, if slide transitions
     757             :     // are disabled.
     758           0 :     if (mbNoSlideTransitions)
     759           0 :         return ActivitySharedPtr();
     760             : 
     761             :     // retrieve slide change parameters from XDrawPage
     762             :     uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
     763           0 :                                                     uno::UNO_QUERY );
     764             : 
     765           0 :     if( !xPropSet.is() )
     766             :     {
     767             :         OSL_TRACE( "createSlideTransition(): "
     768             :                    "Slide has no PropertySet - assuming no transition\n" );
     769           0 :         return ActivitySharedPtr();
     770             :     }
     771             : 
     772           0 :     sal_Int16 nTransitionType(0);
     773           0 :     if( !getPropertyValue( nTransitionType,
     774             :                            xPropSet,
     775           0 :                            "TransitionType") )
     776             :     {
     777             :         OSL_TRACE( "createSlideTransition(): "
     778             :                    "Could not extract slide transition type from XDrawPage - assuming no transition\n" );
     779           0 :         return ActivitySharedPtr();
     780             :     }
     781             : 
     782           0 :     sal_Int16 nTransitionSubType(0);
     783           0 :     if( !getPropertyValue( nTransitionSubType,
     784             :                            xPropSet,
     785           0 :                            "TransitionSubtype") )
     786             :     {
     787             :         OSL_TRACE( "createSlideTransition(): "
     788             :                    "Could not extract slide transition subtype from XDrawPage - assuming no transition\n" );
     789           0 :         return ActivitySharedPtr();
     790             :     }
     791             : 
     792           0 :     bool bTransitionDirection(false);
     793           0 :     if( !getPropertyValue( bTransitionDirection,
     794             :                            xPropSet,
     795           0 :                            "TransitionDirection") )
     796             :     {
     797             :         OSL_TRACE( "createSlideTransition(): "
     798             :                    "Could not extract slide transition direction from XDrawPage - assuming default direction\n" );
     799             :     }
     800             : 
     801           0 :     sal_Int32 aUnoColor(0);
     802           0 :     if( !getPropertyValue( aUnoColor,
     803             :                            xPropSet,
     804           0 :                            "TransitionFadeColor") )
     805             :     {
     806             :         OSL_TRACE( "createSlideTransition(): "
     807             :                    "Could not extract slide transition fade color from XDrawPage - assuming black\n" );
     808             :     }
     809             : 
     810           0 :     const RGBColor aTransitionFadeColor( unoColor2RGBColor( aUnoColor ));
     811             : 
     812           0 :     uno::Any aSound;
     813           0 :     bool bLoopSound = false;
     814             : 
     815           0 :     if( !getPropertyValue( aSound, xPropSet, "Sound") )
     816             :         OSL_TRACE( "createSlideTransition(): Could not determine transition sound effect URL from XDrawPage - using no sound" );
     817             : 
     818           0 :     if( !getPropertyValue( bLoopSound, xPropSet, "LoopSound" ) )
     819             :         OSL_TRACE( "createSlideTransition(): Could not get slide property 'LoopSound' - using no sound" );
     820             : 
     821             :     NumberAnimationSharedPtr pTransition(
     822             :         TransitionFactory::createSlideTransition(
     823             :             rLeavingSlide,
     824             :             rEnteringSlide,
     825             :             maViewContainer,
     826             :             maScreenUpdater,
     827             :             maEventMultiplexer,
     828             :             mxOptionalTransitionFactory,
     829             :             nTransitionType,
     830             :             nTransitionSubType,
     831             :             bTransitionDirection,
     832             :             aTransitionFadeColor,
     833           0 :             resetSlideTransitionSound( aSound, bLoopSound ) ));
     834             : 
     835           0 :     if( !pTransition )
     836           0 :         return ActivitySharedPtr(); // no transition effect has been
     837             :                                     // generated. Normally, that means
     838             :                                     // that simply no transition is
     839             :                                     // set on this slide.
     840             : 
     841           0 :     double nTransitionDuration(0.0);
     842           0 :     if( !getPropertyValue( nTransitionDuration,
     843             :                            xPropSet,
     844           0 :                            "TransitionDuration") )
     845             :     {
     846             :         OSL_TRACE( "createSlideTransition(): "
     847             :                    "Could not extract slide transition duration from XDrawPage - assuming no transition\n" );
     848           0 :         return ActivitySharedPtr();
     849             :     }
     850             : 
     851           0 :     sal_Int32 nMinFrames(5);
     852           0 :     if( !getPropertyValue( nMinFrames,
     853             :                            xPropSet,
     854           0 :                            "MinimalFrameNumber") )
     855             :     {
     856             :         OSL_TRACE( "createSlideTransition(): "
     857             :                    "No minimal number of frames given - assuming 5\n" );
     858             :     }
     859             : 
     860             :     // prefetch slide transition bitmaps, but postpone it after
     861             :     // displaySlide() has finished - sometimes, view size has not yet
     862             :     // reached final size
     863             :     maEventQueue.addEvent(
     864             :         makeEvent(
     865             :             boost::bind(
     866             :                 &::slideshow::internal::Animation::prefetch,
     867             :                 pTransition,
     868             :                 AnimatableShapeSharedPtr(),
     869             :                 ShapeAttributeLayerSharedPtr()),
     870           0 :             "Animation::prefetch"));
     871             : 
     872             :     return ActivitySharedPtr(
     873             :         ActivitiesFactory::createSimpleActivity(
     874             :             ActivitiesFactory::CommonParameters(
     875             :                 rTransitionEndEvent,
     876             :                 maEventQueue,
     877             :                 maActivitiesQueue,
     878             :                 nTransitionDuration,
     879             :                 nMinFrames,
     880             :                 false,
     881             :                 boost::optional<double>(1.0),
     882             :                 0.0,
     883             :                 0.0,
     884             :                 ShapeSharedPtr(),
     885           0 :                 basegfx::B2DSize( rEnteringSlide->getSlideSize() ) ),
     886             :             pTransition,
     887           0 :             true ));
     888             : }
     889             : 
     890           0 : PolygonMap::iterator SlideShowImpl::findPolygons( uno::Reference<drawing::XDrawPage> const& xDrawPage)
     891             : {
     892             :     // TODO(P2) : Optimze research in the map.
     893           0 :     bool bFound = false;
     894           0 :     PolygonMap::iterator aIter=maPolygons.begin();
     895             : 
     896           0 :     while(aIter!=maPolygons.end() && !bFound)
     897             :     {
     898           0 :         if(aIter->first == xDrawPage)
     899           0 :             bFound = true;
     900             :         else
     901           0 :             ++aIter;
     902             :     }
     903             : 
     904           0 :     return aIter;
     905             : }
     906             : 
     907           0 : SlideSharedPtr SlideShowImpl::makeSlide(
     908             :     uno::Reference<drawing::XDrawPage> const&          xDrawPage,
     909             :     uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
     910             :     uno::Reference<animations::XAnimationNode> const&  xRootNode )
     911             : {
     912           0 :     if( !xDrawPage.is() )
     913           0 :         return SlideSharedPtr();
     914             : 
     915             :     //Retrieve polygons for the current slide
     916           0 :     PolygonMap::iterator aIter;
     917           0 :     aIter = findPolygons(xDrawPage);
     918             : 
     919             :     const SlideSharedPtr pSlide( createSlide(xDrawPage,
     920             :                                              xDrawPages,
     921             :                                              xRootNode,
     922             :                                              maEventQueue,
     923             :                                              maEventMultiplexer,
     924             :                                              maScreenUpdater,
     925             :                                              maActivitiesQueue,
     926             :                                              maUserEventQueue,
     927             :                                              *this,
     928             :                                              maViewContainer,
     929             :                                              mxComponentContext,
     930             :                                              maShapeEventListeners,
     931             :                                              maShapeCursors,
     932           0 :                                              (aIter != maPolygons.end()) ? aIter->second :  PolyPolygonVector(),
     933           0 :                                              maUserPaintColor ? *maUserPaintColor : RGBColor(),
     934             :                                              maUserPaintStrokeWidth,
     935           0 :                                              !!maUserPaintColor,
     936             :                                              mbImageAnimationsAllowed,
     937           0 :                                              mbDisableAnimationZOrder) );
     938             : 
     939             :     // prefetch show content (reducing latency for slide
     940             :     // bitmap and effect start later on)
     941           0 :     pSlide->prefetch();
     942             : 
     943           0 :     return pSlide;
     944             : }
     945             : 
     946           0 : void SlideShowImpl::requestWaitSymbol()
     947             : {
     948           0 :     ++mnWaitSymbolRequestCount;
     949             :     OSL_ASSERT(mnWaitSymbolRequestCount>0);
     950             : 
     951           0 :     if (mnWaitSymbolRequestCount == 1)
     952             :     {
     953           0 :         if( !mpWaitSymbol )
     954             :         {
     955             :             // fall back to cursor
     956           0 :             requestCursor(calcActiveCursor(mnCurrentCursor));
     957             :         }
     958             :         else
     959           0 :             mpWaitSymbol->show();
     960             :     }
     961           0 : }
     962             : 
     963           0 : void SlideShowImpl::releaseWaitSymbol()
     964             : {
     965           0 :     --mnWaitSymbolRequestCount;
     966             :     OSL_ASSERT(mnWaitSymbolRequestCount>=0);
     967             : 
     968           0 :     if (mnWaitSymbolRequestCount == 0)
     969             :     {
     970           0 :         if( !mpWaitSymbol )
     971             :         {
     972             :             // fall back to cursor
     973           0 :             requestCursor(calcActiveCursor(mnCurrentCursor));
     974             :         }
     975             :         else
     976           0 :             mpWaitSymbol->hide();
     977             :     }
     978           0 : }
     979             : 
     980           0 : sal_Int16 SlideShowImpl::calcActiveCursor( sal_Int16 nCursorShape ) const
     981             : {
     982           0 :     if( mnWaitSymbolRequestCount>0 && !mpWaitSymbol ) // enforce wait cursor
     983           0 :         nCursorShape = awt::SystemPointer::WAIT;
     984           0 :     else if( !mbMouseVisible ) // enforce INVISIBLE
     985           0 :         nCursorShape = awt::SystemPointer::INVISIBLE;
     986           0 :     else if( maUserPaintColor &&
     987           0 :              nCursorShape == awt::SystemPointer::ARROW )
     988           0 :         nCursorShape = awt::SystemPointer::PEN;
     989             : 
     990           0 :     return nCursorShape;
     991             : }
     992             : 
     993           0 : void SlideShowImpl::stopShow()
     994             : {
     995             :     // Force-end running animation
     996             :     // ===========================
     997           0 :     if (mpCurrentSlide)
     998             :     {
     999           0 :         mpCurrentSlide->hide();
    1000             :         //Register polygons in the map
    1001           0 :         if(findPolygons(mpCurrentSlide->getXDrawPage()) != maPolygons.end())
    1002           0 :             maPolygons.erase(mpCurrentSlide->getXDrawPage());
    1003             : 
    1004           0 :         maPolygons.insert(make_pair(mpCurrentSlide->getXDrawPage(),mpCurrentSlide->getPolygons()));
    1005             :     }
    1006             : 
    1007             :     // clear all queues
    1008           0 :     maEventQueue.clear();
    1009           0 :     maActivitiesQueue.clear();
    1010             : 
    1011             :     // Attention: we MUST clear the user event queue here,
    1012             :     // this is because the current slide might have registered
    1013             :     // shape events (click or enter/leave), which might
    1014             :     // otherwise dangle forever in the queue (because of the
    1015             :     // shared ptr nature). If someone needs to change this:
    1016             :     // somehow unregister those shapes at the user event queue
    1017             :     // on notifySlideEnded().
    1018           0 :     maUserEventQueue.clear();
    1019             : 
    1020             :     // re-enable automatic effect advancement
    1021             :     // (maEventQueue.clear() above might have killed
    1022             :     // maEventMultiplexer's tick events)
    1023           0 :     if (mbAutomaticAdvancementMode)
    1024             :     {
    1025             :         // toggle automatic mode (enabling just again is
    1026             :         // ignored by EventMultiplexer)
    1027           0 :         maEventMultiplexer.setAutomaticMode( false );
    1028           0 :         maEventMultiplexer.setAutomaticMode( true );
    1029             :     }
    1030           0 : }
    1031             : 
    1032             : class SlideShowImpl::PrefetchPropertiesFunc
    1033             : {
    1034             : public:
    1035           0 :     PrefetchPropertiesFunc( SlideShowImpl * that_,
    1036             :         bool& rbSkipAllMainSequenceEffects,
    1037             :         bool& rbSkipSlideTransition)
    1038             :         : mpSlideShowImpl(that_),
    1039             :           mrbSkipAllMainSequenceEffects(rbSkipAllMainSequenceEffects),
    1040           0 :           mrbSkipSlideTransition(rbSkipSlideTransition)
    1041           0 :     {}
    1042             : 
    1043           0 :     void operator()( beans::PropertyValue const& rProperty ) const {
    1044           0 :         if (rProperty.Name == "Prefetch" )
    1045             :         {
    1046           0 :             uno::Sequence<uno::Any> seq;
    1047           0 :             if ((rProperty.Value >>= seq) && seq.getLength() == 2)
    1048             :             {
    1049           0 :                 seq[0] >>= mpSlideShowImpl->mxPrefetchSlide;
    1050           0 :                 seq[1] >>= mpSlideShowImpl->mxPrefetchAnimationNode;
    1051           0 :             }
    1052             :         }
    1053           0 :         else if ( rProperty.Name == "SkipAllMainSequenceEffects" )
    1054             :         {
    1055           0 :             rProperty.Value >>= mrbSkipAllMainSequenceEffects;
    1056             :         }
    1057           0 :         else if ( rProperty.Name == "SkipSlideTransition" )
    1058             :         {
    1059           0 :             rProperty.Value >>= mrbSkipSlideTransition;
    1060             :         }
    1061             :         else
    1062             :         {
    1063             :             OSL_FAIL( OUStringToOString(
    1064             :                             rProperty.Name, RTL_TEXTENCODING_UTF8 ).getStr() );
    1065             :         }
    1066           0 :     }
    1067             : private:
    1068             :     SlideShowImpl *const mpSlideShowImpl;
    1069             :     bool& mrbSkipAllMainSequenceEffects;
    1070             :     bool& mrbSkipSlideTransition;
    1071             : };
    1072             : 
    1073           0 : void SlideShowImpl::displaySlide(
    1074             :     uno::Reference<drawing::XDrawPage> const& xSlide,
    1075             :     uno::Reference<drawing::XDrawPagesSupplier> const& xDrawPages,
    1076             :     uno::Reference<animations::XAnimationNode> const& xRootNode,
    1077             :     uno::Sequence<beans::PropertyValue> const& rProperties )
    1078             :     throw (uno::RuntimeException, std::exception)
    1079             : {
    1080           0 :     osl::MutexGuard const guard( m_aMutex );
    1081             : 
    1082           0 :     if (isDisposed())
    1083           0 :         return;
    1084             : 
    1085           0 :     maEffectRewinder.setRootAnimationNode(xRootNode);
    1086             : 
    1087             :     // precondition: must only be called from the main thread!
    1088             :     DBG_TESTSOLARMUTEX();
    1089             : 
    1090           0 :     mxDrawPagesSupplier = xDrawPages;
    1091             : 
    1092           0 :     stopShow();  // MUST call that: results in
    1093             :     // maUserEventQueue.clear(). What's more,
    1094             :     // stopShow()'s currSlide->hide() call is
    1095             :     // now also required, notifySlideEnded()
    1096             :     // relies on that
    1097             :     // unconditionally. Otherwise, genuine
    1098             :     // shape animations (drawing layer and
    1099             :     // GIF) will not be stopped.
    1100             : 
    1101           0 :     bool bSkipAllMainSequenceEffects (false);
    1102           0 :     bool bSkipSlideTransition (false);
    1103             :     std::for_each( rProperties.getConstArray(),
    1104           0 :                    rProperties.getConstArray() + rProperties.getLength(),
    1105           0 :         PrefetchPropertiesFunc(this, bSkipAllMainSequenceEffects, bSkipSlideTransition) );
    1106             : 
    1107             :     OSL_ENSURE( !maViewContainer.empty(), "### no views!" );
    1108           0 :     if (maViewContainer.empty())
    1109           0 :         return;
    1110             : 
    1111             :     // this here might take some time
    1112             :     {
    1113           0 :         WaitSymbolLock aLock (*this);
    1114             : 
    1115           0 :         mpPreviousSlide = mpCurrentSlide;
    1116           0 :         mpCurrentSlide.reset();
    1117             : 
    1118           0 :         if (matches( mpPrefetchSlide, xSlide, xRootNode ))
    1119             :         {
    1120             :             // prefetched slide matches:
    1121           0 :             mpCurrentSlide = mpPrefetchSlide;
    1122             :         }
    1123             :         else
    1124           0 :             mpCurrentSlide = makeSlide( xSlide, xDrawPages, xRootNode );
    1125             : 
    1126             :         OSL_ASSERT( mpCurrentSlide );
    1127           0 :         if (mpCurrentSlide)
    1128             :         {
    1129           0 :             basegfx::B2DSize oldSlideSize;
    1130           0 :             if( mpPreviousSlide )
    1131           0 :                 oldSlideSize = basegfx::B2DSize( mpPreviousSlide->getSlideSize() );
    1132             : 
    1133           0 :             basegfx::B2DSize const slideSize( mpCurrentSlide->getSlideSize() );
    1134             : 
    1135             :             // push new transformation to all views, if size changed
    1136           0 :             if( !mpPreviousSlide || oldSlideSize != slideSize )
    1137             :             {
    1138             :                 std::for_each( maViewContainer.begin(),
    1139             :                                maViewContainer.end(),
    1140             :                                boost::bind( &View::setViewSize, _1,
    1141           0 :                                             boost::cref(slideSize) ));
    1142             : 
    1143             :                 // explicitly notify view change here,
    1144             :                 // because transformation might have changed:
    1145             :                 // optimization, this->notifyViewChange() would
    1146             :                 // repaint slide which is not necessary.
    1147           0 :                 maEventMultiplexer.notifyViewsChanged();
    1148             :             }
    1149             : 
    1150             :             // create slide transition, and add proper end event
    1151             :             // (which then starts the slide effects
    1152             :             // via CURRENT_SLIDE.show())
    1153             :             ActivitySharedPtr pSlideChangeActivity (
    1154             :                 createSlideTransition(
    1155           0 :                     mpCurrentSlide->getXDrawPage(),
    1156             :                     mpPreviousSlide,
    1157             :                     mpCurrentSlide,
    1158           0 :                     makeEvent(
    1159             :                         boost::bind(
    1160             :                             &SlideShowImpl::notifySlideTransitionEnded,
    1161             :                             this,
    1162             :                             false ),
    1163           0 :                         "SlideShowImpl::notifySlideTransitionEnded")));
    1164             : 
    1165           0 :             if (bSkipSlideTransition)
    1166             :             {
    1167             :                 // The transition activity was created for the side effects
    1168             :                 // (like sound transitions).  Because we want to skip the
    1169             :                 // acutual transition animation we do not need the activity
    1170             :                 // anymore.
    1171           0 :                 pSlideChangeActivity.reset();
    1172             :             }
    1173             : 
    1174           0 :             if (pSlideChangeActivity)
    1175             :             {
    1176             :                 // factory generated a slide transition - activate it!
    1177           0 :                 maActivitiesQueue.addActivity( pSlideChangeActivity );
    1178             :             }
    1179             :             else
    1180             :             {
    1181             :                 // no transition effect on this slide - schedule slide
    1182             :                 // effect start event right away.
    1183             :                 maEventQueue.addEvent(
    1184           0 :                     makeEvent(
    1185             :                         boost::bind(
    1186             :                             &SlideShowImpl::notifySlideTransitionEnded,
    1187             :                             this,
    1188             :                             true ),
    1189           0 :                         "SlideShowImpl::notifySlideTransitionEnded"));
    1190           0 :             }
    1191           0 :         }
    1192             :     } // finally
    1193             : 
    1194             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    1195           0 :         boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) );
    1196             : 
    1197             :     // We are currently rewinding an effect.  This lead us from the next
    1198             :     // slide to this one.  To complete this we have to play back all main
    1199             :     // sequence effects on this slide.
    1200           0 :     if (bSkipAllMainSequenceEffects)
    1201           0 :         maEffectRewinder.skipAllMainSequenceEffects();
    1202             : }
    1203             : 
    1204           0 : void SlideShowImpl::redisplayCurrentSlide()
    1205             : {
    1206           0 :     osl::MutexGuard const guard( m_aMutex );
    1207             : 
    1208           0 :     if (isDisposed())
    1209           0 :         return;
    1210             : 
    1211             :     // precondition: must only be called from the main thread!
    1212             :     DBG_TESTSOLARMUTEX();
    1213           0 :     stopShow();
    1214             : 
    1215             :     OSL_ENSURE( !maViewContainer.empty(), "### no views!" );
    1216           0 :     if (maViewContainer.empty())
    1217           0 :         return;
    1218             : 
    1219             :     // No transition effect on this slide - schedule slide
    1220             :     // effect start event right away.
    1221             :     maEventQueue.addEvent(
    1222           0 :         makeEvent(
    1223             :             boost::bind(
    1224             :                 &SlideShowImpl::notifySlideTransitionEnded,
    1225             :                 this,
    1226             :                 true ),
    1227           0 :             "SlideShowImpl::notifySlideTransitionEnded"));
    1228             : 
    1229             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    1230           0 :         boost::mem_fn( &presentation::XSlideShowListener::slideTransitionStarted ) );
    1231             : }
    1232             : 
    1233           0 : sal_Bool SlideShowImpl::nextEffect() throw (uno::RuntimeException, std::exception)
    1234             : {
    1235           0 :     osl::MutexGuard const guard( m_aMutex );
    1236             : 
    1237           0 :     if (isDisposed())
    1238           0 :         return false;
    1239             : 
    1240             :     // precondition: must only be called from the main thread!
    1241             :     DBG_TESTSOLARMUTEX();
    1242             : 
    1243           0 :     if (mbShowPaused)
    1244           0 :         return true;
    1245             :     else
    1246           0 :         return maEventMultiplexer.notifyNextEffect();
    1247             : }
    1248             : 
    1249           0 : sal_Bool SlideShowImpl::previousEffect() throw (uno::RuntimeException, std::exception)
    1250             : {
    1251           0 :     osl::MutexGuard const guard( m_aMutex );
    1252             : 
    1253           0 :     if (isDisposed())
    1254           0 :         return false;
    1255             : 
    1256             :     // precondition: must only be called from the main thread!
    1257             :     DBG_TESTSOLARMUTEX();
    1258             : 
    1259           0 :     if (mbShowPaused)
    1260           0 :         return true;
    1261             :     else
    1262             :     {
    1263             :         return maEffectRewinder.rewind(
    1264             :             maScreenUpdater.createLock(false),
    1265             :             ::boost::bind<void>(::boost::mem_fn(&SlideShowImpl::redisplayCurrentSlide), this),
    1266           0 :             ::boost::bind<void>(::boost::mem_fn(&SlideShowImpl::rewindEffectToPreviousSlide), this));
    1267           0 :     }
    1268             : }
    1269             : 
    1270           0 : void SlideShowImpl::rewindEffectToPreviousSlide()
    1271             : {
    1272             :     // Show the wait symbol now and prevent it from showing temporary slide
    1273             :     // content while effects are played back.
    1274           0 :     WaitSymbolLock aLock (*this);
    1275             : 
    1276             :     // A previous call to EffectRewinder::Rewind could not rewind the current
    1277             :     // effect because there are no effects on the current slide or none has
    1278             :     // yet been displayed.  Go to the previous slide.
    1279           0 :     notifySlideEnded(true);
    1280             : 
    1281             :     // Process pending events once more in order to have the following
    1282             :     // screen update show the last effect.  Not sure whether this should be
    1283             :     // necessary.
    1284           0 :     maEventQueue.forceEmpty();
    1285             : 
    1286             :     // We have to call the screen updater before the wait symbol is turned
    1287             :     // off.  Otherwise the wait symbol would force the display of an
    1288             :     // intermediate state of the slide (before the effects are replayed.)
    1289           0 :     maScreenUpdater.commitUpdates();
    1290           0 : }
    1291             : 
    1292           0 : sal_Bool SlideShowImpl::startShapeActivity(
    1293             :     uno::Reference<drawing::XShape> const& /*xShape*/ )
    1294             :     throw (uno::RuntimeException, std::exception)
    1295             : {
    1296           0 :     osl::MutexGuard const guard( m_aMutex );
    1297             : 
    1298             :     // precondition: must only be called from the main thread!
    1299             :     DBG_TESTSOLARMUTEX();
    1300             : 
    1301             :     // TODO(F3): NYI
    1302             :     OSL_FAIL( "not yet implemented!" );
    1303           0 :     return false;
    1304             : }
    1305             : 
    1306           0 : sal_Bool SlideShowImpl::stopShapeActivity(
    1307             :     uno::Reference<drawing::XShape> const& /*xShape*/ )
    1308             :     throw (uno::RuntimeException, std::exception)
    1309             : {
    1310           0 :     osl::MutexGuard const guard( m_aMutex );
    1311             : 
    1312             :     // precondition: must only be called from the main thread!
    1313             :     DBG_TESTSOLARMUTEX();
    1314             : 
    1315             :     // TODO(F3): NYI
    1316             :     OSL_FAIL( "not yet implemented!" );
    1317           0 :     return false;
    1318             : }
    1319             : 
    1320           0 : sal_Bool SlideShowImpl::pause( sal_Bool bPauseShow )
    1321             :     throw (uno::RuntimeException, std::exception)
    1322             : {
    1323           0 :     osl::MutexGuard const guard( m_aMutex );
    1324             : 
    1325           0 :     if (isDisposed())
    1326           0 :         return false;
    1327             : 
    1328             :     // precondition: must only be called from the main thread!
    1329             :     DBG_TESTSOLARMUTEX();
    1330             : 
    1331           0 :     if (bPauseShow)
    1332           0 :         mpPresTimer->pauseTimer();
    1333             :     else
    1334           0 :         mpPresTimer->continueTimer();
    1335             : 
    1336           0 :     maEventMultiplexer.notifyPauseMode(bPauseShow);
    1337             : 
    1338           0 :     mbShowPaused = bPauseShow;
    1339           0 :     return true;
    1340             : }
    1341             : 
    1342           0 : uno::Reference<drawing::XDrawPage> SlideShowImpl::getCurrentSlide()
    1343             :     throw (uno::RuntimeException, std::exception)
    1344             : {
    1345           0 :     osl::MutexGuard const guard( m_aMutex );
    1346             : 
    1347           0 :     if (isDisposed())
    1348           0 :         return uno::Reference<drawing::XDrawPage>();
    1349             : 
    1350             :     // precondition: must only be called from the main thread!
    1351             :     DBG_TESTSOLARMUTEX();
    1352             : 
    1353           0 :     if (mpCurrentSlide)
    1354           0 :         return mpCurrentSlide->getXDrawPage();
    1355             :     else
    1356           0 :         return uno::Reference<drawing::XDrawPage>();
    1357             : }
    1358             : 
    1359           0 : sal_Bool SlideShowImpl::addView(
    1360             :     uno::Reference<presentation::XSlideShowView> const& xView )
    1361             :     throw (uno::RuntimeException, std::exception)
    1362             : {
    1363           0 :     osl::MutexGuard const guard( m_aMutex );
    1364             : 
    1365           0 :     if (isDisposed())
    1366           0 :         return false;
    1367             : 
    1368             :     // precondition: must only be called from the main thread!
    1369             :     DBG_TESTSOLARMUTEX();
    1370             : 
    1371             :     // first of all, check if view has a valid canvas
    1372           0 :     ENSURE_OR_RETURN_FALSE( xView.is(), "addView(): Invalid view" );
    1373           0 :     ENSURE_OR_RETURN_FALSE( xView->getCanvas().is(),
    1374             :                        "addView(): View does not provide a valid canvas" );
    1375             : 
    1376             :     UnoViewSharedPtr const pView( createSlideView(
    1377             :                                       xView,
    1378             :                                       maEventQueue,
    1379           0 :                                       maEventMultiplexer ));
    1380           0 :     if (!maViewContainer.addView( pView ))
    1381           0 :         return false; // view already added
    1382             : 
    1383             :     // initialize view content
    1384             :     // =======================
    1385             : 
    1386           0 :     if (mpCurrentSlide)
    1387             :     {
    1388             :         // set view transformation
    1389           0 :         const basegfx::B2ISize slideSize = mpCurrentSlide->getSlideSize();
    1390           0 :         pView->setViewSize( basegfx::B2DSize( slideSize.getX(),
    1391           0 :                                               slideSize.getY() ) );
    1392             :     }
    1393             : 
    1394             :     // clear view area (since its newly added,
    1395             :     // we need a clean slate)
    1396           0 :     pView->clearAll();
    1397             : 
    1398             :     // broadcast newly added view
    1399           0 :     maEventMultiplexer.notifyViewAdded( pView );
    1400             : 
    1401             :     // set current mouse ptr
    1402           0 :     pView->setCursorShape( calcActiveCursor(mnCurrentCursor) );
    1403             : 
    1404           0 :     return true;
    1405             : }
    1406             : 
    1407           0 : sal_Bool SlideShowImpl::removeView(
    1408             :     uno::Reference<presentation::XSlideShowView> const& xView )
    1409             :     throw (uno::RuntimeException, std::exception)
    1410             : {
    1411           0 :     osl::MutexGuard const guard( m_aMutex );
    1412             : 
    1413             :     // precondition: must only be called from the main thread!
    1414             :     DBG_TESTSOLARMUTEX();
    1415             : 
    1416           0 :     ENSURE_OR_RETURN_FALSE( xView.is(), "removeView(): Invalid view" );
    1417             : 
    1418           0 :     UnoViewSharedPtr const pView( maViewContainer.removeView( xView ) );
    1419           0 :     if( !pView )
    1420           0 :         return false; // view was not added in the first place
    1421             : 
    1422             :     // remove view from EventMultiplexer (mouse events etc.)
    1423           0 :     maEventMultiplexer.notifyViewRemoved( pView );
    1424             : 
    1425           0 :     pView->_dispose();
    1426             : 
    1427           0 :     return true;
    1428             : }
    1429             : 
    1430           0 : void SlideShowImpl::registerUserPaintPolygons( const uno::Reference< lang::XMultiServiceFactory >& xDocFactory ) throw (uno::RuntimeException, std::exception)
    1431             : {
    1432             :     //Retrieve Polygons if user ends presentation by context menu
    1433           0 :     if (mpCurrentSlide)
    1434             :     {
    1435           0 :         if(findPolygons(mpCurrentSlide->getXDrawPage()) != maPolygons.end())
    1436           0 :             maPolygons.erase(mpCurrentSlide->getXDrawPage());
    1437             : 
    1438           0 :         maPolygons.insert(make_pair(mpCurrentSlide->getXDrawPage(),mpCurrentSlide->getPolygons()));
    1439             :     }
    1440             : 
    1441             :     //Creating the layer for shapes
    1442             :     // query for the XLayerManager
    1443           0 :     uno::Reference< drawing::XLayerSupplier > xLayerSupplier(xDocFactory, uno::UNO_QUERY);
    1444           0 :     uno::Reference< container::XNameAccess > xNameAccess = xLayerSupplier->getLayerManager();
    1445             : 
    1446           0 :     uno::Reference< drawing::XLayerManager > xLayerManager(xNameAccess, uno::UNO_QUERY);
    1447             :     // create a layer and set its properties
    1448           0 :     uno::Reference< drawing::XLayer > xDrawnInSlideshow = xLayerManager->insertNewByIndex(xLayerManager->getCount());
    1449           0 :     uno::Reference< beans::XPropertySet > xLayerPropSet(xDrawnInSlideshow, uno::UNO_QUERY);
    1450             : 
    1451             :     //Layer Name which enables to catch annotations
    1452           0 :     OUString layerName = "DrawnInSlideshow";
    1453           0 :     uno::Any aPropLayer;
    1454             : 
    1455           0 :     aPropLayer <<= layerName;
    1456           0 :     xLayerPropSet->setPropertyValue("Name", aPropLayer);
    1457             : 
    1458           0 :     aPropLayer <<= true;
    1459           0 :     xLayerPropSet->setPropertyValue("IsVisible", aPropLayer);
    1460             : 
    1461           0 :     aPropLayer <<= false;
    1462           0 :     xLayerPropSet->setPropertyValue("IsLocked", aPropLayer);
    1463             : 
    1464           0 :     PolygonMap::iterator aIter=maPolygons.begin();
    1465             : 
    1466           0 :     PolyPolygonVector aPolygons;
    1467           0 :     ::cppcanvas::PolyPolygonSharedPtr pPolyPoly;
    1468           0 :     ::basegfx::B2DPolyPolygon b2DPolyPoly;
    1469             : 
    1470             :     //Register polygons for each slide
    1471           0 :     while(aIter!=maPolygons.end())
    1472             :     {
    1473           0 :         aPolygons = aIter->second;
    1474             :         //Get shapes for the slide
    1475           0 :         ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > Shapes(aIter->first, ::com::sun::star::uno::UNO_QUERY);
    1476             :         //Retrieve polygons for one slide
    1477           0 :         for( PolyPolygonVector::iterator aIterPoly=aPolygons.begin(),
    1478           0 :                  aEnd=aPolygons.end();
    1479             :              aIterPoly!=aEnd; ++aIterPoly )
    1480             :         {
    1481           0 :             pPolyPoly = (*aIterPoly);
    1482           0 :             b2DPolyPoly = ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(pPolyPoly->getUNOPolyPolygon());
    1483             : 
    1484             :             //Normally there is only one polygon
    1485           0 :             for(sal_uInt32 i=0; i< b2DPolyPoly.count();i++)
    1486             :             {
    1487           0 :                 const ::basegfx::B2DPolygon& aPoly =  b2DPolyPoly.getB2DPolygon(i);
    1488           0 :                 sal_uInt32 nPoints = aPoly.count();
    1489             : 
    1490           0 :                 if( nPoints > 1)
    1491             :                 {
    1492             :                     //create the PolyLineShape
    1493           0 :                     uno::Reference< uno::XInterface > polyshape(xDocFactory->createInstance(
    1494           0 :                                                                     OUString("com.sun.star.drawing.PolyLineShape") ) );
    1495           0 :                     uno::Reference< drawing::XShape > rPolyShape(polyshape, uno::UNO_QUERY);
    1496             : 
    1497             :                     //Add the shape to the slide
    1498           0 :                     Shapes->add(rPolyShape);
    1499             : 
    1500             :                     //Retrieve shape properties
    1501           0 :                     uno::Reference< beans::XPropertySet > aXPropSet = uno::Reference< beans::XPropertySet >( rPolyShape, uno::UNO_QUERY );
    1502             :                     //Construct a sequence of points sequence
    1503           0 :                     drawing::PointSequenceSequence aRetval;
    1504             :                     //Create only one sequence for one polygon
    1505           0 :                     aRetval.realloc( 1 );
    1506             :                     // Retrieve the sequence of points from aRetval
    1507           0 :                     drawing::PointSequence* pOuterSequence = aRetval.getArray();
    1508             :                     // Create 2 points in this sequence
    1509           0 :                     pOuterSequence->realloc(nPoints);
    1510             :                     // Get these points which are in an array
    1511           0 :                     awt::Point* pInnerSequence = pOuterSequence->getArray();
    1512           0 :                     for( sal_uInt32 n = 0; n < nPoints; n++ )
    1513             :                     {
    1514             :                         //Create a point from the polygon
    1515             :                         *pInnerSequence++ = awt::Point(
    1516           0 :                             basegfx::fround(aPoly.getB2DPoint(n).getX()),
    1517           0 :                             basegfx::fround(aPoly.getB2DPoint(n).getY()));
    1518             :                     }
    1519             : 
    1520             :                     //Fill the properties
    1521             :                     //Give the built PointSequenceSequence.
    1522           0 :                     uno::Any aParam;
    1523           0 :                     aParam <<= aRetval;
    1524           0 :                     aXPropSet->setPropertyValue("PolyPolygon", aParam );
    1525             : 
    1526             :                     //LineStyle : SOLID by default
    1527           0 :                     uno::Any            aAny;
    1528             :                     drawing::LineStyle  eLS;
    1529           0 :                     eLS = drawing::LineStyle_SOLID;
    1530           0 :                     aAny <<= eLS;
    1531           0 :                     aXPropSet->setPropertyValue("LineStyle", aAny );
    1532             : 
    1533             :                     //LineColor
    1534             :                     sal_uInt32          nLineColor;
    1535           0 :                     nLineColor = pPolyPoly->getRGBALineColor();
    1536             :                     //Transform polygon color from RRGGBBAA to AARRGGBB
    1537           0 :                     aAny <<= RGBAColor2UnoColor(nLineColor);
    1538           0 :                     aXPropSet->setPropertyValue("LineColor", aAny );
    1539             : 
    1540             :                     //LineWidth
    1541             :                     double              fLineWidth;
    1542           0 :                     fLineWidth = pPolyPoly->getStrokeWidth();
    1543           0 :                     aAny <<= (sal_Int32)fLineWidth;
    1544           0 :                     aXPropSet->setPropertyValue("LineWidth", aAny );
    1545             : 
    1546             :                     // make polygons special
    1547           0 :                     xLayerManager->attachShapeToLayer(rPolyShape, xDrawnInSlideshow);
    1548             :                 }
    1549           0 :             }
    1550             :         }
    1551           0 :         ++aIter;
    1552           0 :     }
    1553           0 : }
    1554             : 
    1555           0 : sal_Bool SlideShowImpl::setProperty( beans::PropertyValue const& rProperty )
    1556             :     throw (uno::RuntimeException, std::exception)
    1557             : {
    1558           0 :     osl::MutexGuard const guard( m_aMutex );
    1559             : 
    1560           0 :     if (isDisposed())
    1561           0 :         return false;
    1562             : 
    1563             :     // precondition: must only be called from the main thread!
    1564             :     DBG_TESTSOLARMUTEX();
    1565             : 
    1566           0 :     if ( rProperty.Name == "AutomaticAdvancement" )
    1567             :     {
    1568           0 :         double nTimeout(0.0);
    1569           0 :         mbAutomaticAdvancementMode = (rProperty.Value >>= nTimeout);
    1570           0 :         if (mbAutomaticAdvancementMode)
    1571             :         {
    1572           0 :             maEventMultiplexer.setAutomaticTimeout( nTimeout );
    1573             :         }
    1574           0 :         maEventMultiplexer.setAutomaticMode( mbAutomaticAdvancementMode );
    1575           0 :         return true;
    1576             :     }
    1577             : 
    1578           0 :     if ( rProperty.Name == "UserPaintColor" )
    1579             :     {
    1580           0 :         sal_Int32 nColor(0);
    1581           0 :         if (rProperty.Value >>= nColor)
    1582             :         {
    1583             :             OSL_ENSURE( mbMouseVisible,
    1584             :                         "setProperty(): User paint overrides invisible mouse" );
    1585             : 
    1586             :             // enable user paint
    1587           0 :             maUserPaintColor.reset( unoColor2RGBColor( nColor ) );
    1588           0 :             if( mpCurrentSlide && !mpCurrentSlide->isPaintOverlayActive() )
    1589           0 :                 mpCurrentSlide->enablePaintOverlay();
    1590             : 
    1591           0 :             maEventMultiplexer.notifyUserPaintColor( *maUserPaintColor );
    1592             :         }
    1593             :         else
    1594             :         {
    1595             :             // disable user paint
    1596           0 :             maUserPaintColor.reset();
    1597           0 :             maEventMultiplexer.notifyUserPaintDisabled();
    1598           0 :             if( mpCurrentSlide )
    1599           0 :                 mpCurrentSlide->disablePaintOverlay();
    1600             :         }
    1601             : 
    1602           0 :         resetCursor();
    1603             : 
    1604           0 :         return true;
    1605             :     }
    1606             : 
    1607             :     //adding support for erasing features in UserPaintOverlay
    1608           0 :     if ( rProperty.Name == "EraseAllInk" )
    1609             :     {
    1610           0 :         bool nEraseAllInk(false);
    1611           0 :         if (rProperty.Value >>= nEraseAllInk)
    1612             :         {
    1613             :             OSL_ENSURE( mbMouseVisible,
    1614             :                         "setProperty(): User paint overrides invisible mouse" );
    1615             : 
    1616             :             // enable user paint
    1617           0 :             maEraseAllInk.reset( nEraseAllInk );
    1618           0 :             maEventMultiplexer.notifyEraseAllInk( *maEraseAllInk );
    1619             :         }
    1620             : 
    1621           0 :         return true;
    1622             :     }
    1623             : 
    1624           0 :     if ( rProperty.Name == "SwitchPenMode" )
    1625             :     {
    1626           0 :         bool nSwitchPenMode(false);
    1627           0 :         if (rProperty.Value >>= nSwitchPenMode)
    1628             :         {
    1629             :             OSL_ENSURE( mbMouseVisible,
    1630             :                         "setProperty(): User paint overrides invisible mouse" );
    1631             : 
    1632           0 :             if(nSwitchPenMode){
    1633             :             // Switch to Pen Mode
    1634           0 :             maSwitchPenMode.reset( nSwitchPenMode );
    1635           0 :             maEventMultiplexer.notifySwitchPenMode();
    1636             :             }
    1637             :         }
    1638           0 :         return true;
    1639             :     }
    1640             : 
    1641           0 :     if ( rProperty.Name == "SwitchEraserMode" )
    1642             :     {
    1643           0 :         bool nSwitchEraserMode(false);
    1644           0 :         if (rProperty.Value >>= nSwitchEraserMode)
    1645             :         {
    1646             :             OSL_ENSURE( mbMouseVisible,
    1647             :                         "setProperty(): User paint overrides invisible mouse" );
    1648           0 :             if(nSwitchEraserMode){
    1649             :             // switch to Eraser mode
    1650           0 :             maSwitchEraserMode.reset( nSwitchEraserMode );
    1651           0 :             maEventMultiplexer.notifySwitchEraserMode();
    1652             :             }
    1653             :         }
    1654             : 
    1655           0 :         return true;
    1656             :     }
    1657             : 
    1658           0 :     if ( rProperty.Name == "EraseInk" )
    1659             :     {
    1660           0 :         sal_Int32 nEraseInk(100);
    1661           0 :         if (rProperty.Value >>= nEraseInk)
    1662             :         {
    1663             :             OSL_ENSURE( mbMouseVisible,
    1664             :                         "setProperty(): User paint overrides invisible mouse" );
    1665             : 
    1666             :             // enable user paint
    1667           0 :             maEraseInk.reset( nEraseInk );
    1668           0 :             maEventMultiplexer.notifyEraseInkWidth( *maEraseInk );
    1669             :         }
    1670             : 
    1671           0 :         return true;
    1672             :     }
    1673             : 
    1674             :     // new Property for pen's width
    1675           0 :     if ( rProperty.Name == "UserPaintStrokeWidth" )
    1676             :     {
    1677           0 :         double nWidth(4.0);
    1678           0 :         if (rProperty.Value >>= nWidth)
    1679             :         {
    1680             :             OSL_ENSURE( mbMouseVisible,"setProperty(): User paint overrides invisible mouse" );
    1681             :             // enable user paint stroke width
    1682           0 :             maUserPaintStrokeWidth = nWidth;
    1683           0 :             maEventMultiplexer.notifyUserPaintStrokeWidth( maUserPaintStrokeWidth );
    1684             :         }
    1685             : 
    1686           0 :         return true;
    1687             :     }
    1688             : 
    1689           0 :     if ( rProperty.Name == "AdvanceOnClick" )
    1690             :     {
    1691           0 :         bool bAdvanceOnClick = false;
    1692           0 :         if (! (rProperty.Value >>= bAdvanceOnClick))
    1693           0 :             return false;
    1694           0 :         maUserEventQueue.setAdvanceOnClick( bAdvanceOnClick );
    1695           0 :         return true;
    1696             :     }
    1697             : 
    1698           0 :     if ( rProperty.Name == "DisableAnimationZOrder" )
    1699             :     {
    1700           0 :         bool bDisableAnimationZOrder = false;
    1701           0 :         if (! (rProperty.Value >>= bDisableAnimationZOrder))
    1702           0 :             return false;
    1703           0 :         mbDisableAnimationZOrder = bDisableAnimationZOrder;
    1704           0 :         return true;
    1705             :     }
    1706             : 
    1707           0 :     if ( rProperty.Name == "ImageAnimationsAllowed" )
    1708             :     {
    1709           0 :         if (! (rProperty.Value >>= mbImageAnimationsAllowed))
    1710           0 :             return false;
    1711             : 
    1712             :         // TODO(F3): Forward to slides!
    1713           0 :         return true;
    1714             :     }
    1715             : 
    1716           0 :     if ( rProperty.Name == "MouseVisible" )
    1717             :     {
    1718           0 :         if (! (rProperty.Value >>= mbMouseVisible))
    1719           0 :             return false;
    1720             : 
    1721           0 :         requestCursor(mnCurrentCursor);
    1722             : 
    1723           0 :         return true;
    1724             :     }
    1725             : 
    1726           0 :     if ( rProperty.Name == "ForceManualAdvance" )
    1727             :     {
    1728           0 :         return (rProperty.Value >>= mbForceManualAdvance);
    1729             :     }
    1730             : 
    1731           0 :     if ( rProperty.Name == "RehearseTimings" )
    1732             :     {
    1733           0 :         bool bRehearseTimings = false;
    1734           0 :         if (! (rProperty.Value >>= bRehearseTimings))
    1735           0 :             return false;
    1736             : 
    1737           0 :         if (bRehearseTimings)
    1738             :         {
    1739             :             // TODO(Q3): Move to slide
    1740           0 :             mpRehearseTimingsActivity = RehearseTimingsActivity::create(
    1741             :                 SlideShowContext(
    1742             :                     mpDummyPtr,
    1743             :                     maEventQueue,
    1744             :                     maEventMultiplexer,
    1745             :                     maScreenUpdater,
    1746             :                     maActivitiesQueue,
    1747             :                     maUserEventQueue,
    1748             :                     *this,
    1749             :                     maViewContainer,
    1750           0 :                     mxComponentContext) );
    1751             :         }
    1752           0 :         else if (mpRehearseTimingsActivity)
    1753             :         {
    1754             :             // removes timer from all views:
    1755           0 :             mpRehearseTimingsActivity->dispose();
    1756           0 :             mpRehearseTimingsActivity.reset();
    1757             :         }
    1758           0 :         return true;
    1759             :     }
    1760             : 
    1761           0 :     if ( rProperty.Name == "WaitSymbolBitmap" )
    1762             :     {
    1763           0 :         uno::Reference<rendering::XBitmap> xBitmap;
    1764           0 :         if (! (rProperty.Value >>= xBitmap))
    1765           0 :             return false;
    1766             : 
    1767           0 :         mpWaitSymbol = WaitSymbol::create( xBitmap,
    1768             :                                            maScreenUpdater,
    1769             :                                            maEventMultiplexer,
    1770           0 :                                            maViewContainer );
    1771             : 
    1772           0 :         return true;
    1773             :     }
    1774             : 
    1775           0 :     if ( rProperty.Name == "PointerSymbolBitmap" )
    1776             :     {
    1777           0 :         uno::Reference<rendering::XBitmap> xBitmap;
    1778           0 :         if (! (rProperty.Value >>= xBitmap))
    1779           0 :             return false;
    1780             : 
    1781           0 :         mpPointerSymbol = PointerSymbol::create( xBitmap,
    1782             :                                            maScreenUpdater,
    1783             :                                            maEventMultiplexer,
    1784           0 :                                            maViewContainer );
    1785             : 
    1786           0 :         return true;
    1787             :     }
    1788             : 
    1789           0 :     if ( rProperty.Name == "PointerVisible" )
    1790             :     {
    1791             :         bool visible;
    1792           0 :         if (!(rProperty.Value >>= visible))
    1793           0 :             return false;
    1794             : 
    1795           0 :         mpPointerSymbol->setVisible(visible);
    1796           0 :         return true;
    1797             :     }
    1798             : 
    1799           0 :     if ( rProperty.Name == "PointerPosition")
    1800             :     {
    1801           0 :         ::com::sun::star::geometry::RealPoint2D pos;
    1802           0 :         if (! (rProperty.Value >>= pos))
    1803           0 :             return false;
    1804             : 
    1805           0 :         mpPointerSymbol->viewsChanged(pos);
    1806           0 :         return true;
    1807             :     }
    1808             : 
    1809           0 :     if (rProperty.Name == "NoSlideTransitions" )
    1810             :     {
    1811           0 :         return (rProperty.Value >>= mbNoSlideTransitions);
    1812             :     }
    1813             : 
    1814           0 :     if ( rProperty.Name == "IsSoundEnabled" )
    1815             :     {
    1816           0 :         uno::Sequence<uno::Any> aValues;
    1817           0 :         uno::Reference<presentation::XSlideShowView> xView;
    1818           0 :         bool bValue (false);
    1819           0 :         if ((rProperty.Value >>= aValues)
    1820           0 :             && aValues.getLength()==2
    1821           0 :             && (aValues[0] >>= xView)
    1822           0 :             && (aValues[1] >>= bValue))
    1823             :         {
    1824             :             // Look up the view.
    1825           0 :             for (UnoViewVector::const_iterator
    1826           0 :                      iView (maViewContainer.begin()),
    1827           0 :                      iEnd (maViewContainer.end());
    1828             :                  iView!=iEnd;
    1829             :                  ++iView)
    1830             :             {
    1831           0 :                 if (*iView && (*iView)->getUnoView()==xView)
    1832             :                 {
    1833             :                     // Store the flag at the view so that media shapes have
    1834             :                     // access to it.
    1835           0 :                     (*iView)->setIsSoundEnabled(bValue);
    1836           0 :                     return true;
    1837             :                 }
    1838             :             }
    1839           0 :         }
    1840             :     }
    1841             : 
    1842           0 :     return false;
    1843             : }
    1844             : 
    1845           0 : void SlideShowImpl::addSlideShowListener(
    1846             :     uno::Reference<presentation::XSlideShowListener> const& xListener )
    1847             :     throw (uno::RuntimeException, std::exception)
    1848             : {
    1849           0 :     osl::MutexGuard const guard( m_aMutex );
    1850             : 
    1851           0 :     if (isDisposed())
    1852           0 :         return;
    1853             : 
    1854             :     // container syncs with passed mutex ref
    1855           0 :     maListenerContainer.addInterface(xListener);
    1856             : }
    1857             : 
    1858           0 : void SlideShowImpl::removeSlideShowListener(
    1859             :     uno::Reference<presentation::XSlideShowListener> const& xListener )
    1860             :     throw (uno::RuntimeException, std::exception)
    1861             : {
    1862           0 :     osl::MutexGuard const guard( m_aMutex );
    1863             : 
    1864             :     // container syncs with passed mutex ref
    1865           0 :     maListenerContainer.removeInterface(xListener);
    1866           0 : }
    1867             : 
    1868           0 : void SlideShowImpl::addShapeEventListener(
    1869             :     uno::Reference<presentation::XShapeEventListener> const& xListener,
    1870             :     uno::Reference<drawing::XShape> const& xShape )
    1871             :     throw (uno::RuntimeException, std::exception)
    1872             : {
    1873           0 :     osl::MutexGuard const guard( m_aMutex );
    1874             : 
    1875           0 :     if (isDisposed())
    1876           0 :         return;
    1877             : 
    1878             :     // precondition: must only be called from the main thread!
    1879             :     DBG_TESTSOLARMUTEX();
    1880             : 
    1881           0 :     ShapeEventListenerMap::iterator aIter;
    1882           0 :     if( (aIter=maShapeEventListeners.find( xShape )) ==
    1883           0 :         maShapeEventListeners.end() )
    1884             :     {
    1885             :         // no entry for this shape -> create one
    1886             :         aIter = maShapeEventListeners.insert(
    1887             :             ShapeEventListenerMap::value_type(
    1888             :                 xShape,
    1889             :                 boost::shared_ptr<cppu::OInterfaceContainerHelper>(
    1890           0 :                     new cppu::OInterfaceContainerHelper(m_aMutex)))).first;
    1891             :     }
    1892             : 
    1893             :     // add new listener to broadcaster
    1894           0 :     if( aIter->second.get() )
    1895           0 :         aIter->second->addInterface( xListener );
    1896             : 
    1897             :     maEventMultiplexer.notifyShapeListenerAdded(xListener,
    1898           0 :                                                 xShape);
    1899             : }
    1900             : 
    1901           0 : void SlideShowImpl::removeShapeEventListener(
    1902             :     uno::Reference<presentation::XShapeEventListener> const& xListener,
    1903             :     uno::Reference<drawing::XShape> const& xShape )
    1904             :     throw (uno::RuntimeException, std::exception)
    1905             : {
    1906           0 :     osl::MutexGuard const guard( m_aMutex );
    1907             : 
    1908             :     // precondition: must only be called from the main thread!
    1909             :     DBG_TESTSOLARMUTEX();
    1910             : 
    1911           0 :     ShapeEventListenerMap::iterator aIter;
    1912           0 :     if( (aIter = maShapeEventListeners.find( xShape )) !=
    1913           0 :         maShapeEventListeners.end() )
    1914             :     {
    1915             :         // entry for this shape found -> remove listener from
    1916             :         // helper object
    1917           0 :         ENSURE_OR_THROW(
    1918             :             aIter->second.get(),
    1919             :             "SlideShowImpl::removeShapeEventListener(): "
    1920             :             "listener map contains NULL broadcast helper" );
    1921             : 
    1922           0 :         aIter->second->removeInterface( xListener );
    1923             :     }
    1924             : 
    1925             :     maEventMultiplexer.notifyShapeListenerRemoved(xListener,
    1926           0 :                                                   xShape);
    1927           0 : }
    1928             : 
    1929           0 : void SlideShowImpl::setShapeCursor(
    1930             :     uno::Reference<drawing::XShape> const& xShape, sal_Int16 nPointerShape )
    1931             :     throw (uno::RuntimeException, std::exception)
    1932             : {
    1933           0 :     osl::MutexGuard const guard( m_aMutex );
    1934             : 
    1935           0 :     if (isDisposed())
    1936           0 :         return;
    1937             : 
    1938             :     // precondition: must only be called from the main thread!
    1939             :     DBG_TESTSOLARMUTEX();
    1940             : 
    1941           0 :     ShapeCursorMap::iterator aIter;
    1942           0 :     if( (aIter=maShapeCursors.find( xShape )) == maShapeCursors.end() )
    1943             :     {
    1944             :         // no entry for this shape -> create one
    1945           0 :         if( nPointerShape != awt::SystemPointer::ARROW )
    1946             :         {
    1947             :             // add new entry, unless shape shall display
    1948             :             // normal pointer arrow -> no need to handle that
    1949             :             // case
    1950             :             maShapeCursors.insert(
    1951             :                 ShapeCursorMap::value_type(xShape,
    1952           0 :                                            nPointerShape) );
    1953             :         }
    1954             :     }
    1955           0 :     else if( nPointerShape == awt::SystemPointer::ARROW )
    1956             :     {
    1957             :         // shape shall display normal cursor -> can disable
    1958             :         // the cursor and clear the entry
    1959           0 :         maShapeCursors.erase( xShape );
    1960             :     }
    1961             :     else
    1962             :     {
    1963             :         // existing entry found, update with new cursor ID
    1964           0 :         aIter->second = nPointerShape;
    1965             :     }
    1966             : 
    1967             :     maEventMultiplexer.notifyShapeCursorChange(xShape,
    1968           0 :                                                nPointerShape);
    1969             : }
    1970             : 
    1971           0 : bool SlideShowImpl::requestCursor( sal_Int16 nCursorShape )
    1972             : {
    1973           0 :     mnCurrentCursor = nCursorShape;
    1974             : 
    1975           0 :     const sal_Int16 nActualCursor = calcActiveCursor(mnCurrentCursor);
    1976             : 
    1977             :     // change all views to the requested cursor ID
    1978             :     std::for_each( maViewContainer.begin(),
    1979             :                    maViewContainer.end(),
    1980             :                    boost::bind( &View::setCursorShape,
    1981             :                                 _1,
    1982           0 :                                 nActualCursor ));
    1983             : 
    1984           0 :     return nActualCursor==nCursorShape;
    1985             : }
    1986             : 
    1987           0 : void SlideShowImpl::resetCursor()
    1988             : {
    1989           0 :     mnCurrentCursor = awt::SystemPointer::ARROW;
    1990             : 
    1991             :     // change all views to the default cursor ID
    1992             :     std::for_each( maViewContainer.begin(),
    1993             :                    maViewContainer.end(),
    1994             :                    boost::bind( &View::setCursorShape,
    1995             :                                 _1,
    1996           0 :                                 calcActiveCursor(mnCurrentCursor) ));
    1997           0 : }
    1998             : 
    1999           0 : sal_Bool SlideShowImpl::update( double & nNextTimeout )
    2000             :     throw (uno::RuntimeException, std::exception)
    2001             : {
    2002           0 :     osl::MutexGuard const guard( m_aMutex );
    2003             : 
    2004           0 :     if (isDisposed())
    2005           0 :         return false;
    2006             : 
    2007             :     // precondition: update() must only be called from the
    2008             :     // main thread!
    2009             :     DBG_TESTSOLARMUTEX();
    2010             : 
    2011           0 :     if( mbShowPaused )
    2012             :     {
    2013             :         // commit frame (might be repaints pending)
    2014           0 :         maScreenUpdater.commitUpdates();
    2015             : 
    2016           0 :         return false;
    2017             :     }
    2018             :     else
    2019             :     {
    2020             :         // TODO(F2): re-evaluate whether that timer lagging makes
    2021             :         // sense.
    2022             : 
    2023             :         // hold timer, while processing the queues:
    2024             :         // 1. when there is more than one active activity this ensures the
    2025             :         //    same time for all activities and events
    2026             :         // 2. processing of events may lead to creation of further events
    2027             :         //    that have zero delay.  While the timer is stopped these events
    2028             :         //    are processed in the same run.
    2029             :         {
    2030             :             //Get a shared-ptr that outlives the scope-guard which will
    2031             :             //ensure that the pointed-to-item exists in the case of a
    2032             :             //::dispose clearing mpPresTimer
    2033           0 :             boost::shared_ptr<canvas::tools::ElapsedTime> xTimer(mpPresTimer);
    2034             :             comphelper::ScopeGuard scopeGuard(
    2035             :                 boost::bind( &canvas::tools::ElapsedTime::releaseTimer,
    2036           0 :                              boost::cref(xTimer) ) );
    2037           0 :             xTimer->holdTimer();
    2038             : 
    2039             :             // process queues
    2040           0 :             maEventQueue.process();
    2041             : 
    2042             :             // #i118671# the call above may execute a macro bound to an object. In
    2043             :             // that case this macro may have destroyed this local sliseshow so that it
    2044             :             // is disposed (see bugdoc at task). In that case, detect this and exit
    2045             :             // gently from this slideshow. Do not forget to disable the scoped
    2046             :             // call to mpPresTimer, this will be deleted if we are disposed.
    2047           0 :             if (isDisposed())
    2048             :             {
    2049           0 :                 scopeGuard.dismiss();
    2050           0 :                 return false;
    2051             :             }
    2052             : 
    2053           0 :             maActivitiesQueue.process();
    2054             : 
    2055             :             // commit frame to screen
    2056           0 :             maFrameSynchronization.Synchronize();
    2057           0 :             maScreenUpdater.commitUpdates();
    2058             : 
    2059             :             // TODO(Q3): remove need to call dequeued() from
    2060             :             // activities. feels like a wart.
    2061             : 
    2062             :             // Rationale for ActivitiesQueue::processDequeued(): when
    2063             :             // an activity ends, it usually pushed the end state to
    2064             :             // the animated shape in question, and ends the animation
    2065             :             // (which, in turn, will usually disable shape sprite
    2066             :             // mode). Disabling shape sprite mode causes shape
    2067             :             // repaint, which, depending on slide content, takes
    2068             :             // considerably more time than sprite updates. Thus, the
    2069             :             // last animation step tends to look delayed. To
    2070             :             // camouflage this, reaching end position and disabling
    2071             :             // sprite mode is split into two (normal Activity::end(),
    2072             :             // and Activity::dequeued()). Now, the reason to call
    2073             :             // commitUpdates() twice here is caused by the unrelated
    2074             :             // fact that during wait cursor display/hide, the screen
    2075             :             // is updated, and shows hidden sprites, but, in case of
    2076             :             // leaving the second commitUpdates() call out and punting
    2077             :             // that to the next round, no updated static slide
    2078             :             // content. In short, the last shape animation of a slide
    2079             :             // tends to blink at its end.
    2080             : 
    2081             :             // process dequeued activities _after_ commit to screen
    2082           0 :             maActivitiesQueue.processDequeued();
    2083             : 
    2084             :             // commit frame to screen
    2085           0 :             maScreenUpdater.commitUpdates();
    2086             :         }
    2087             :         // Time held until here
    2088             : 
    2089           0 :         const bool bActivitiesLeft = (! maActivitiesQueue.isEmpty());
    2090           0 :         const bool bTimerEventsLeft = (! maEventQueue.isEmpty());
    2091           0 :         const bool bRet = (bActivitiesLeft || bTimerEventsLeft);
    2092             : 
    2093           0 :         if (bRet)
    2094             :         {
    2095             :             // calc nNextTimeout value:
    2096           0 :             if (bActivitiesLeft)
    2097             :             {
    2098             :                 // Activity queue is not empty.  Tell caller that we would
    2099             :                 // like to render another frame.
    2100             : 
    2101             :                 // Return a zero time-out to signal our caller to call us
    2102             :                 // back as soon as possible.  The actual timing, waiting the
    2103             :                 // appropriate amount of time between frames, is then done
    2104             :                 // by the maFrameSynchronization object.
    2105           0 :                 nNextTimeout = 0;
    2106           0 :                 maFrameSynchronization.Activate();
    2107             :             }
    2108             :             else
    2109             :             {
    2110             :                 // timer events left:
    2111             :                 // difference from current time (nota bene:
    2112             :                 // time no longer held here!) to the next event in
    2113             :                 // the event queue.
    2114             : 
    2115             :                 // #i61190# Retrieve next timeout only _after_
    2116             :                 // processing activity queue
    2117             : 
    2118             :                 // ensure positive value:
    2119           0 :                 nNextTimeout = std::max( 0.0, maEventQueue.nextTimeout() );
    2120             : 
    2121             :                 // There is no active animation so the frame rate does not
    2122             :                 // need to be synchronized.
    2123           0 :                 maFrameSynchronization.Deactivate();
    2124             :             }
    2125             : 
    2126           0 :             mbSlideShowIdle = false;
    2127             :         }
    2128             : 
    2129             : #if OSL_DEBUG_LEVEL >= 2 && defined(DBG_UTIL)
    2130             :         // when slideshow is idle, issue an XUpdatable::update() call
    2131             :         // exactly once after a previous animation sequence finished -
    2132             :         // this might trigger screen dumps on some canvas
    2133             :         // implementations
    2134             :         if( !mbSlideShowIdle &&
    2135             :             (!bRet ||
    2136             :              nNextTimeout > 1.0) )
    2137             :         {
    2138             :             UnoViewVector::const_iterator       aCurr(maViewContainer.begin());
    2139             :             const UnoViewVector::const_iterator aEnd(maViewContainer.end());
    2140             :             while( aCurr != aEnd )
    2141             :             {
    2142             :                 try
    2143             :                 {
    2144             :                     uno::Reference< presentation::XSlideShowView > xView( (*aCurr)->getUnoView(),
    2145             :                                                                           uno::UNO_QUERY_THROW );
    2146             :                     uno::Reference< util::XUpdatable >             xUpdatable( xView->getCanvas(),
    2147             :                                                                                uno::UNO_QUERY_THROW );
    2148             :                     xUpdatable->update();
    2149             :                 }
    2150             :                 catch( uno::RuntimeException& )
    2151             :                 {
    2152             :                     throw;
    2153             :                 }
    2154             :                 catch( uno::Exception& )
    2155             :                 {
    2156             :                     OSL_FAIL( OUStringToOString(
    2157             :                                     comphelper::anyToString( cppu::getCaughtException() ),
    2158             :                                     RTL_TEXTENCODING_UTF8 ).getStr() );
    2159             :                 }
    2160             : 
    2161             :                 ++aCurr;
    2162             :             }
    2163             : 
    2164             :             mbSlideShowIdle = true;
    2165             :         }
    2166             : #endif
    2167             : 
    2168           0 :         return bRet;
    2169           0 :     }
    2170             : }
    2171             : 
    2172           0 : void SlideShowImpl::notifySlideTransitionEnded( bool bPaintSlide )
    2173             : {
    2174           0 :     osl::MutexGuard const guard( m_aMutex );
    2175             : 
    2176             :     OSL_ENSURE( !isDisposed(), "### already disposed!" );
    2177             :     OSL_ENSURE( mpCurrentSlide,
    2178             :                 "notifySlideTransitionEnded(): Invalid current slide" );
    2179           0 :     if (mpCurrentSlide)
    2180             :     {
    2181           0 :         mpCurrentSlide->update_settings( !!maUserPaintColor, maUserPaintColor ? *maUserPaintColor : RGBColor(), maUserPaintStrokeWidth );
    2182             : 
    2183             :         // first init show, to give the animations
    2184             :         // the chance to register SlideStartEvents
    2185           0 :         const bool bBackgroundLayerRendered( !bPaintSlide );
    2186           0 :         mpCurrentSlide->show( bBackgroundLayerRendered );
    2187           0 :         maEventMultiplexer.notifySlideStartEvent();
    2188           0 :     }
    2189           0 : }
    2190             : 
    2191           0 : void queryAutomaticSlideTransition( uno::Reference<drawing::XDrawPage> const& xDrawPage,
    2192             :                                     double&                                   nAutomaticNextSlideTimeout,
    2193             :                                     bool&                                     bHasAutomaticNextSlide )
    2194             : {
    2195             :     // retrieve slide change parameters from XDrawPage
    2196             :     // ===============================================
    2197             : 
    2198             :     uno::Reference< beans::XPropertySet > xPropSet( xDrawPage,
    2199           0 :                                                     uno::UNO_QUERY );
    2200             : 
    2201           0 :     sal_Int32 nChange(0);
    2202           0 :     if( !xPropSet.is() ||
    2203             :         !getPropertyValue( nChange,
    2204             :                            xPropSet,
    2205             :                            OUString(
    2206           0 :                                "Change")) )
    2207             :     {
    2208             :         OSL_TRACE(
    2209             :             "queryAutomaticSlideTransition(): "
    2210             :             "Could not extract slide change mode from XDrawPage - assuming <none>\n" );
    2211             :     }
    2212             : 
    2213           0 :     bHasAutomaticNextSlide = nChange == 1;
    2214             : 
    2215           0 :     if( !xPropSet.is() ||
    2216             :         !getPropertyValue( nAutomaticNextSlideTimeout,
    2217             :                            xPropSet,
    2218             :                            OUString(
    2219           0 :                                "HighResDuration")) )
    2220             :     {
    2221             :         OSL_TRACE(
    2222             :             "queryAutomaticSlideTransition(): "
    2223             :             "Could not extract slide transition timeout from "
    2224             :             "XDrawPage - assuming 1 sec\n" );
    2225           0 :     }
    2226           0 : }
    2227             : 
    2228           0 : void SlideShowImpl::notifySlideAnimationsEnded()
    2229             : {
    2230           0 :     osl::MutexGuard const guard( m_aMutex );
    2231             : 
    2232             :     //Draw polygons above animations
    2233           0 :     mpCurrentSlide->drawPolygons();
    2234             : 
    2235             :     OSL_ENSURE( !isDisposed(), "### already disposed!" );
    2236             : 
    2237             :     // This struct will receive the (interruptable) event,
    2238             :     // that triggers the notifySlideEnded() method.
    2239           0 :     InterruptableEventPair aNotificationEvents;
    2240             : 
    2241           0 :     if( maEventMultiplexer.getAutomaticMode() )
    2242             :     {
    2243             :         OSL_ENSURE( ! mpRehearseTimingsActivity,
    2244             :                     "unexpected: RehearseTimings mode!" );
    2245             : 
    2246             :         // schedule a slide end event, with automatic mode's
    2247             :         // delay
    2248           0 :         aNotificationEvents = makeInterruptableDelay(
    2249           0 :             boost::bind<void>( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
    2250           0 :             maEventMultiplexer.getAutomaticTimeout() );
    2251             :     }
    2252             :     else
    2253             :     {
    2254             :         OSL_ENSURE( mpCurrentSlide,
    2255             :                     "notifySlideAnimationsEnded(): Invalid current slide!" );
    2256             : 
    2257           0 :         bool   bHasAutomaticNextSlide=false;
    2258           0 :         double nAutomaticNextSlideTimeout=0.0;
    2259           0 :         queryAutomaticSlideTransition(mpCurrentSlide->getXDrawPage(),
    2260             :                                       nAutomaticNextSlideTimeout,
    2261           0 :                                       bHasAutomaticNextSlide);
    2262             : 
    2263             :         // check whether slide transition should happen
    2264             :         // 'automatically'. If yes, simply schedule the
    2265             :         // specified timeout.
    2266             :         // NOTE: mbForceManualAdvance and mpRehearseTimingsActivity
    2267             :         // override any individual slide setting, to always
    2268             :         // step slides manually.
    2269           0 :         if( !mbForceManualAdvance &&
    2270           0 :             !mpRehearseTimingsActivity &&
    2271             :             bHasAutomaticNextSlide )
    2272             :         {
    2273           0 :             aNotificationEvents = makeInterruptableDelay(
    2274           0 :                 boost::bind<void>( boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
    2275           0 :                 nAutomaticNextSlideTimeout);
    2276             : 
    2277             :             // TODO(F2): Provide a mechanism to let the user override
    2278             :             // this automatic timeout via next()
    2279             :         }
    2280             :         else
    2281             :         {
    2282           0 :             if (mpRehearseTimingsActivity)
    2283           0 :                 mpRehearseTimingsActivity->start();
    2284             : 
    2285             :             // generate click event. Thus, the user must
    2286             :             // trigger the actual end of a slide. No need to
    2287             :             // generate interruptable event here, there's no
    2288             :             // timeout involved.
    2289           0 :             aNotificationEvents.mpImmediateEvent =
    2290           0 :                 makeEvent( boost::bind<void>(
    2291             :                     boost::mem_fn(&SlideShowImpl::notifySlideEnded), this, false ),
    2292           0 :                     "SlideShowImpl::notifySlideEnded");
    2293             :         }
    2294             :     }
    2295             : 
    2296             :     // register events on the queues. To make automatic slide
    2297             :     // changes interruptable, register the interruption event
    2298             :     // as a nextEffectEvent target. Note that the timeout
    2299             :     // event is optional (e.g. manual slide changes don't
    2300             :     // generate a timeout)
    2301             :     maUserEventQueue.registerNextEffectEvent(
    2302           0 :         aNotificationEvents.mpImmediateEvent );
    2303             : 
    2304           0 :     if( aNotificationEvents.mpTimeoutEvent )
    2305           0 :         maEventQueue.addEvent( aNotificationEvents.mpTimeoutEvent );
    2306             : 
    2307             :     // current slide's main sequence is over. Now should be
    2308             :     // the time to prefetch the next slide (if any), and
    2309             :     // prepare the initial slide bitmap (speeds up slide
    2310             :     // change setup time a lot). Show the wait cursor, this
    2311             :     // indeed might take some seconds.
    2312             :     {
    2313           0 :         WaitSymbolLock aLock (*this);
    2314             : 
    2315           0 :         if (! matches( mpPrefetchSlide,
    2316           0 :                        mxPrefetchSlide, mxPrefetchAnimationNode ))
    2317             :         {
    2318           0 :             mpPrefetchSlide = makeSlide( mxPrefetchSlide, mxDrawPagesSupplier,
    2319           0 :                                          mxPrefetchAnimationNode );
    2320             :         }
    2321           0 :         if (mpPrefetchSlide)
    2322             :         {
    2323             :             // ignore return value, this is just to populate
    2324             :             // Slide's internal bitmap buffer, such that the time
    2325             :             // needed to generate the slide bitmap is not spent
    2326             :             // when the slide change is requested.
    2327           0 :             mpPrefetchSlide->getCurrentSlideBitmap( *maViewContainer.begin() );
    2328           0 :         }
    2329             :     } // finally
    2330             : 
    2331             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    2332           0 :         boost::mem_fn( &presentation::XSlideShowListener::slideAnimationsEnded ) );
    2333           0 : }
    2334             : 
    2335           0 : void SlideShowImpl::notifySlideEnded (const bool bReverse)
    2336             : {
    2337           0 :     osl::MutexGuard const guard( m_aMutex );
    2338             : 
    2339             :     OSL_ENSURE( !isDisposed(), "### already disposed!" );
    2340             : 
    2341           0 :     if (mpRehearseTimingsActivity && !bReverse)
    2342             :     {
    2343           0 :         const double time = mpRehearseTimingsActivity->stop();
    2344           0 :         if (mpRehearseTimingsActivity->hasBeenClicked())
    2345             :         {
    2346             :             // save time at current drawpage:
    2347             :             uno::Reference<beans::XPropertySet> xPropSet(
    2348           0 :                 mpCurrentSlide->getXDrawPage(), uno::UNO_QUERY );
    2349             :             OSL_ASSERT( xPropSet.is() );
    2350           0 :             if (xPropSet.is())
    2351             :             {
    2352           0 :                 xPropSet->setPropertyValue(
    2353             :                     "Change",
    2354           0 :                     uno::Any( static_cast<sal_Int32>(1) ) );
    2355           0 :                 xPropSet->setPropertyValue(
    2356             :                     "Duration",
    2357           0 :                     uno::Any( static_cast<sal_Int32>(time) ) );
    2358           0 :             }
    2359             :         }
    2360             :     }
    2361             : 
    2362           0 :     if (bReverse)
    2363           0 :         maEventMultiplexer.notifySlideEndEvent();
    2364             : 
    2365           0 :     stopShow();  // MUST call that: results in
    2366             :                  // maUserEventQueue.clear(). What's more,
    2367             :                  // stopShow()'s currSlide->hide() call is
    2368             :                  // now also required, notifySlideEnded()
    2369             :                  // relies on that
    2370             :                  // unconditionally. Otherwise, genuine
    2371             :                  // shape animations (drawing layer and
    2372             :                  // GIF) will not be stopped.
    2373             : 
    2374             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    2375             :         boost::bind<void>(
    2376             :             ::boost::mem_fn(&presentation::XSlideShowListener::slideEnded),
    2377             :             _1,
    2378           0 :             bReverse));
    2379           0 : }
    2380             : 
    2381           0 : bool SlideShowImpl::notifyHyperLinkClicked( OUString const& hyperLink )
    2382             : {
    2383           0 :     osl::MutexGuard const guard( m_aMutex );
    2384             : 
    2385             :     maListenerContainer.forEach<presentation::XSlideShowListener>(
    2386             :         boost::bind( &presentation::XSlideShowListener::hyperLinkClicked,
    2387             :                      _1,
    2388           0 :                      boost::cref(hyperLink) ));
    2389           0 :     return true;
    2390             : }
    2391             : 
    2392             : /** Notification from eventmultiplexer that an animation event has occoured.
    2393             :     This will be forewarded to all registered XSlideShoeListener
    2394             :  */
    2395           0 : bool SlideShowImpl::handleAnimationEvent( const AnimationNodeSharedPtr& rNode )
    2396             : {
    2397           0 :     osl::MutexGuard const guard( m_aMutex );
    2398             : 
    2399           0 :     uno::Reference<animations::XAnimationNode> xNode( rNode->getXAnimationNode() );
    2400             : 
    2401           0 :     switch( rNode->getState() )
    2402             :     {
    2403             :     case AnimationNode::ACTIVE:
    2404             :         maListenerContainer.forEach<presentation::XSlideShowListener>(
    2405             :             boost::bind( &animations::XAnimationListener::beginEvent,
    2406             :                          _1,
    2407           0 :                          boost::cref(xNode) ));
    2408           0 :         break;
    2409             : 
    2410             :     case AnimationNode::FROZEN:
    2411             :     case AnimationNode::ENDED:
    2412             :         maListenerContainer.forEach<presentation::XSlideShowListener>(
    2413             :             boost::bind( &animations::XAnimationListener::endEvent,
    2414             :                          _1,
    2415           0 :                          boost::cref(xNode) ));
    2416           0 :         if(mpCurrentSlide->isPaintOverlayActive())
    2417           0 :            mpCurrentSlide->drawPolygons();
    2418           0 :         break;
    2419             :     default:
    2420           0 :         break;
    2421             :     }
    2422             : 
    2423           0 :     return true;
    2424             : }
    2425             : 
    2426             : //===== FrameSynchronization ==================================================
    2427             : 
    2428           1 : FrameSynchronization::FrameSynchronization (const double nFrameDuration)
    2429             :     : maTimer(),
    2430             :       mnFrameDuration(nFrameDuration),
    2431             :       mnNextFrameTargetTime(0),
    2432           1 :       mbIsActive(false)
    2433             : {
    2434           1 :     MarkCurrentFrame();
    2435           1 : }
    2436             : 
    2437           1 : void FrameSynchronization::MarkCurrentFrame()
    2438             : {
    2439           1 :     mnNextFrameTargetTime = maTimer.getElapsedTime() + mnFrameDuration;
    2440           1 : }
    2441             : 
    2442           0 : void FrameSynchronization::Synchronize()
    2443             : {
    2444           0 :     if (mbIsActive)
    2445             :     {
    2446             :         // Do busy waiting for now.
    2447           0 :         while (maTimer.getElapsedTime() < mnNextFrameTargetTime)
    2448             :             ;
    2449             :     }
    2450             : 
    2451           0 :     MarkCurrentFrame();
    2452           0 : }
    2453             : 
    2454           0 : void FrameSynchronization::Activate()
    2455             : {
    2456           0 :     mbIsActive = true;
    2457           0 : }
    2458             : 
    2459           0 : void FrameSynchronization::Deactivate()
    2460             : {
    2461           0 :     mbIsActive = false;
    2462           0 : }
    2463             : 
    2464             : } // anon namespace
    2465             : 
    2466             : namespace sdecl = comphelper::service_decl;
    2467           2 : const sdecl::ServiceDecl slideShowDecl(
    2468             :      sdecl::class_<SlideShowImpl>(),
    2469             :     "com.sun.star.comp.presentation.SlideShow",
    2470           2 :     "com.sun.star.presentation.SlideShow" );
    2471             : 
    2472             : // The C shared lib entry points
    2473           4 : COMPHELPER_SERVICEDECL_EXPORTS1(slideshow, slideShowDecl)
    2474             : 
    2475             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11