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