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