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

Generated by: LCOV version 1.10