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