xref: /AOO41X/main/slideshow/source/engine/shapes/intrinsicanimationactivity.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_slideshow.hxx"
30 
31 #include <canvas/debug.hxx>
32 #include <tools/diagnose_ex.h>
33 #include <canvas/verbosetrace.hxx>
34 
35 #include "drawshapesubsetting.hxx"
36 #include "subsettableshapemanager.hxx"
37 #include "eventqueue.hxx"
38 #include "eventmultiplexer.hxx"
39 #include "intrinsicanimationactivity.hxx"
40 #include "intrinsicanimationeventhandler.hxx"
41 
42 #include <boost/noncopyable.hpp>
43 #include <boost/enable_shared_from_this.hpp>
44 #include <boost/weak_ptr.hpp>
45 
46 namespace slideshow
47 {
48     namespace internal
49     {
50         /** Activity for intrinsic shape animations
51 
52         	This is an Activity interface implementation for intrinsic
53         	shape animations. Intrinsic shape animations are
54         	animations directly within a shape, e.g. drawing layer
55         	animations, or GIF animations.
56          */
57         class IntrinsicAnimationActivity : public Activity,
58                                            public boost::enable_shared_from_this<IntrinsicAnimationActivity>,
59                                            private boost::noncopyable
60         {
61         public:
62             /** Create an IntrinsicAnimationActivity.
63 
64             	@param rContext
65                 Common slideshow objects
66 
67                 @param rDrawShape
68                 Shape to control the intrinsic animation for
69 
70                 @param rWakeupEvent
71                 Externally generated wakeup event, to set this
72                 activity to sleep during inter-frame intervals. Must
73                 come frome the outside, since wakeup event and this
74                 object have mutual references to each other.
75 
76                 @param rTimeouts
77                 Vector of timeout values, to wait before the next
78                 frame is shown.
79              */
80             IntrinsicAnimationActivity( const SlideShowContext& 		rContext,
81                                         const DrawShapeSharedPtr&		rDrawShape,
82                                         const WakeupEventSharedPtr&		rWakeupEvent,
83                                         const ::std::vector<double>&	rTimeouts,
84                                         ::std::size_t                   nNumLoops,
85                                         CycleMode                       eCycleMode );
86 
87             virtual void dispose();
88             virtual double calcTimeLag() const;
89             virtual bool perform();
90             virtual bool isActive() const;
91             virtual void dequeued();
92             virtual void end();
93 
94             bool enableAnimations();
95 
96         private:
97             SlideShowContext                        maContext;
98             boost::weak_ptr<DrawShape>              mpDrawShape;
99             WakeupEventSharedPtr                    mpWakeupEvent;
100             IntrinsicAnimationEventHandlerSharedPtr mpListener;
101             ::std::vector<double>                   maTimeouts;
102             CycleMode                               meCycleMode;
103             ::std::size_t                           mnCurrIndex;
104             ::std::size_t                           mnNumLoops;
105             ::std::size_t                           mnLoopCount;
106             bool                                    mbIsActive;
107         };
108 
109         //////////////////////////////////////////////////////////////////////
110 
111         class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler,
112                                            private boost::noncopyable
113         {
114         public:
115             explicit IntrinsicAnimationListener( IntrinsicAnimationActivity& rActivity ) :
116                 mrActivity( rActivity )
117             {}
118 
119         private:
120 
121             virtual bool enableAnimations() { return mrActivity.enableAnimations(); }
122             virtual bool disableAnimations() { mrActivity.end(); return true; }
123 
124             IntrinsicAnimationActivity& mrActivity;
125         };
126 
127         //////////////////////////////////////////////////////////////////////
128 
129         IntrinsicAnimationActivity::IntrinsicAnimationActivity( const SlideShowContext& 		rContext,
130                                                                 const DrawShapeSharedPtr&		rDrawShape,
131                                                                 const WakeupEventSharedPtr&		rWakeupEvent,
132                                                                 const ::std::vector<double>&	rTimeouts,
133                                                                 ::std::size_t                   nNumLoops,
134                                                                 CycleMode                       eCycleMode ) :
135             maContext( rContext ),
136             mpDrawShape( rDrawShape ),
137             mpWakeupEvent( rWakeupEvent ),
138             mpListener( new IntrinsicAnimationListener(*this) ),
139             maTimeouts( rTimeouts ),
140             meCycleMode( eCycleMode ),
141             mnCurrIndex(0),
142             mnNumLoops(nNumLoops),
143             mnLoopCount(0),
144             mbIsActive(false)
145         {
146             ENSURE_OR_THROW( rContext.mpSubsettableShapeManager,
147                               "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" );
148             ENSURE_OR_THROW( rDrawShape,
149                               "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" );
150             ENSURE_OR_THROW( rWakeupEvent,
151                               "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" );
152             ENSURE_OR_THROW( !rTimeouts.empty(),
153                               "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" );
154 
155             maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
156                 mpListener );
157         }
158 
159         void IntrinsicAnimationActivity::dispose()
160         {
161             end();
162 
163             if( mpWakeupEvent )
164                 mpWakeupEvent->dispose();
165 
166             maContext.dispose();
167             mpDrawShape.reset();
168             mpWakeupEvent.reset();
169             maTimeouts.clear();
170             mnCurrIndex = 0;
171 
172             maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
173                 mpListener );
174         }
175 
176         double IntrinsicAnimationActivity::calcTimeLag() const
177         {
178             return 0.0;
179         }
180 
181         bool IntrinsicAnimationActivity::perform()
182         {
183             if( !isActive() )
184                 return false;
185 
186             DrawShapeSharedPtr pDrawShape( mpDrawShape.lock() );
187             if( !pDrawShape || !mpWakeupEvent )
188             {
189                 // event or draw shape vanished, no sense living on ->
190                 // commit suicide.
191                 dispose();
192                 return false;
193             }
194 
195             // mnNumLoops == 0 means infinite looping
196             if( mnNumLoops != 0 &&
197                 mnLoopCount >= mnNumLoops )
198             {
199                 // #i55294# After finishing the loops, display the first frame
200                 pDrawShape->setIntrinsicAnimationFrame( 0 );
201                 maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape );
202 
203                 end();
204 
205                 return false;
206             }
207 
208             ::std::size_t       nNewIndex = 0;
209             const ::std::size_t nNumFrames(maTimeouts.size());
210             switch( meCycleMode )
211             {
212                 case CYCLE_LOOP:
213                 {
214                     pDrawShape->setIntrinsicAnimationFrame( mnCurrIndex );
215 
216                     mpWakeupEvent->start();
217                     mpWakeupEvent->setNextTimeout( maTimeouts[mnCurrIndex] );
218 
219                     mnLoopCount += (mnCurrIndex + 1) / nNumFrames;
220                     nNewIndex = (mnCurrIndex + 1) % nNumFrames;
221                     break;
222                 }
223 
224                 case CYCLE_PINGPONGLOOP:
225                 {
226                     ::std::size_t nTrueIndex( mnCurrIndex < nNumFrames ?
227                                               mnCurrIndex :
228                                               2*nNumFrames - mnCurrIndex - 1 );
229                     pDrawShape->setIntrinsicAnimationFrame( nTrueIndex );
230 
231                     mpWakeupEvent->start();
232                     mpWakeupEvent->setNextTimeout( maTimeouts[nTrueIndex] );
233 
234                     mnLoopCount += (mnCurrIndex + 1) / (2*nNumFrames);
235                     nNewIndex = (mnCurrIndex + 1) % 2*nNumFrames;
236                     break;
237                 }
238             }
239 
240             maContext.mrEventQueue.addEvent( mpWakeupEvent );
241             maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape );
242             mnCurrIndex = nNewIndex;
243 
244             return false; // don't reinsert, WakeupEvent will perform
245                           // that after the given timeout
246         }
247 
248         bool IntrinsicAnimationActivity::isActive() const
249         {
250             return mbIsActive;
251         }
252 
253         void IntrinsicAnimationActivity::dequeued()
254         {
255             // not used here
256         }
257 
258         void IntrinsicAnimationActivity::end()
259         {
260             // there is no dedicated end state, just become inactive:
261             mbIsActive = false;
262         }
263 
264         bool IntrinsicAnimationActivity::enableAnimations()
265         {
266             mbIsActive = true;
267             return maContext.mrActivitiesQueue.addActivity(
268                 shared_from_this() );
269         }
270 
271         //////////////////////////////////////////////////////////////////////
272 
273         ActivitySharedPtr createIntrinsicAnimationActivity(
274             const SlideShowContext& 		rContext,
275             const DrawShapeSharedPtr&		rDrawShape,
276             const WakeupEventSharedPtr&		rWakeupEvent,
277             const ::std::vector<double>&	rTimeouts,
278             ::std::size_t                   nNumLoops,
279             CycleMode                       eCycleMode )
280         {
281             return ActivitySharedPtr(
282                 new IntrinsicAnimationActivity(rContext,
283                                                rDrawShape,
284                                                rWakeupEvent,
285                                                rTimeouts,
286                                                nNumLoops,
287                                                eCycleMode) );
288         }
289     }
290 }
291