Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : :
21 : : #include <canvas/debug.hxx>
22 : : #include <tools/diagnose_ex.h>
23 : : #include <canvas/verbosetrace.hxx>
24 : :
25 : : #include "drawshapesubsetting.hxx"
26 : : #include "subsettableshapemanager.hxx"
27 : : #include "eventqueue.hxx"
28 : : #include "eventmultiplexer.hxx"
29 : : #include "intrinsicanimationactivity.hxx"
30 : : #include "intrinsicanimationeventhandler.hxx"
31 : :
32 : : #include <boost/noncopyable.hpp>
33 : : #include <boost/enable_shared_from_this.hpp>
34 : : #include <boost/weak_ptr.hpp>
35 : :
36 : : namespace slideshow
37 : : {
38 : : namespace internal
39 : : {
40 : : /** Activity for intrinsic shape animations
41 : :
42 : : This is an Activity interface implementation for intrinsic
43 : : shape animations. Intrinsic shape animations are
44 : : animations directly within a shape, e.g. drawing layer
45 : : animations, or GIF animations.
46 : : */
47 : 0 : class IntrinsicAnimationActivity : public Activity,
48 : : public boost::enable_shared_from_this<IntrinsicAnimationActivity>,
49 : : private boost::noncopyable
50 : : {
51 : : public:
52 : : /** Create an IntrinsicAnimationActivity.
53 : :
54 : : @param rContext
55 : : Common slideshow objects
56 : :
57 : : @param rDrawShape
58 : : Shape to control the intrinsic animation for
59 : :
60 : : @param rWakeupEvent
61 : : Externally generated wakeup event, to set this
62 : : activity to sleep during inter-frame intervals. Must
63 : : come frome the outside, since wakeup event and this
64 : : object have mutual references to each other.
65 : :
66 : : @param rTimeouts
67 : : Vector of timeout values, to wait before the next
68 : : frame is shown.
69 : : */
70 : : IntrinsicAnimationActivity( const SlideShowContext& rContext,
71 : : const DrawShapeSharedPtr& rDrawShape,
72 : : const WakeupEventSharedPtr& rWakeupEvent,
73 : : const ::std::vector<double>& rTimeouts,
74 : : ::std::size_t nNumLoops,
75 : : CycleMode eCycleMode );
76 : :
77 : : virtual void dispose();
78 : : virtual double calcTimeLag() const;
79 : : virtual bool perform();
80 : : virtual bool isActive() const;
81 : : virtual void dequeued();
82 : : virtual void end();
83 : :
84 : : bool enableAnimations();
85 : :
86 : : private:
87 : : SlideShowContext maContext;
88 : : boost::weak_ptr<DrawShape> mpDrawShape;
89 : : WakeupEventSharedPtr mpWakeupEvent;
90 : : IntrinsicAnimationEventHandlerSharedPtr mpListener;
91 : : ::std::vector<double> maTimeouts;
92 : : CycleMode meCycleMode;
93 : : ::std::size_t mnCurrIndex;
94 : : ::std::size_t mnNumLoops;
95 : : ::std::size_t mnLoopCount;
96 : : bool mbIsActive;
97 : : };
98 : :
99 : : //////////////////////////////////////////////////////////////////////
100 : :
101 : 0 : class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler,
102 : : private boost::noncopyable
103 : : {
104 : : public:
105 : 0 : explicit IntrinsicAnimationListener( IntrinsicAnimationActivity& rActivity ) :
106 : 0 : mrActivity( rActivity )
107 : 0 : {}
108 : :
109 : : private:
110 : :
111 : 0 : virtual bool enableAnimations() { return mrActivity.enableAnimations(); }
112 : 0 : virtual bool disableAnimations() { mrActivity.end(); return true; }
113 : :
114 : : IntrinsicAnimationActivity& mrActivity;
115 : : };
116 : :
117 : : //////////////////////////////////////////////////////////////////////
118 : :
119 : 0 : IntrinsicAnimationActivity::IntrinsicAnimationActivity( const SlideShowContext& rContext,
120 : : const DrawShapeSharedPtr& rDrawShape,
121 : : const WakeupEventSharedPtr& rWakeupEvent,
122 : : const ::std::vector<double>& rTimeouts,
123 : : ::std::size_t nNumLoops,
124 : : CycleMode eCycleMode ) :
125 : : maContext( rContext ),
126 : : mpDrawShape( rDrawShape ),
127 : : mpWakeupEvent( rWakeupEvent ),
128 : 0 : mpListener( new IntrinsicAnimationListener(*this) ),
129 : : maTimeouts( rTimeouts ),
130 : : meCycleMode( eCycleMode ),
131 : : mnCurrIndex(0),
132 : : mnNumLoops(nNumLoops),
133 : : mnLoopCount(0),
134 : 0 : mbIsActive(false)
135 : : {
136 : 0 : ENSURE_OR_THROW( rContext.mpSubsettableShapeManager,
137 : : "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" );
138 : 0 : ENSURE_OR_THROW( rDrawShape,
139 : : "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" );
140 : 0 : ENSURE_OR_THROW( rWakeupEvent,
141 : : "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" );
142 : 0 : ENSURE_OR_THROW( !rTimeouts.empty(),
143 : : "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" );
144 : :
145 : 0 : maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler(
146 : 0 : mpListener );
147 : 0 : }
148 : :
149 : 0 : void IntrinsicAnimationActivity::dispose()
150 : : {
151 : 0 : end();
152 : :
153 : 0 : if( mpWakeupEvent )
154 : 0 : mpWakeupEvent->dispose();
155 : :
156 : 0 : maContext.dispose();
157 : 0 : mpDrawShape.reset();
158 : 0 : mpWakeupEvent.reset();
159 : 0 : maTimeouts.clear();
160 : 0 : mnCurrIndex = 0;
161 : :
162 : 0 : maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
163 : 0 : mpListener );
164 : 0 : }
165 : :
166 : 0 : double IntrinsicAnimationActivity::calcTimeLag() const
167 : : {
168 : 0 : return 0.0;
169 : : }
170 : :
171 : 0 : bool IntrinsicAnimationActivity::perform()
172 : : {
173 : 0 : if( !isActive() )
174 : 0 : return false;
175 : :
176 : 0 : DrawShapeSharedPtr pDrawShape( mpDrawShape.lock() );
177 : 0 : if( !pDrawShape || !mpWakeupEvent )
178 : : {
179 : : // event or draw shape vanished, no sense living on ->
180 : : // commit suicide.
181 : 0 : dispose();
182 : 0 : return false;
183 : : }
184 : :
185 : : // mnNumLoops == 0 means infinite looping
186 : 0 : if( mnNumLoops != 0 &&
187 : : mnLoopCount >= mnNumLoops )
188 : : {
189 : : // #i55294# After finishing the loops, display the first frame
190 : 0 : pDrawShape->setIntrinsicAnimationFrame( 0 );
191 : 0 : maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape );
192 : :
193 : 0 : end();
194 : :
195 : 0 : return false;
196 : : }
197 : :
198 : 0 : ::std::size_t nNewIndex = 0;
199 : 0 : const ::std::size_t nNumFrames(maTimeouts.size());
200 : 0 : switch( meCycleMode )
201 : : {
202 : : case CYCLE_LOOP:
203 : : {
204 : 0 : pDrawShape->setIntrinsicAnimationFrame( mnCurrIndex );
205 : :
206 : 0 : mpWakeupEvent->start();
207 : 0 : mpWakeupEvent->setNextTimeout( maTimeouts[mnCurrIndex] );
208 : :
209 : 0 : mnLoopCount += (mnCurrIndex + 1) / nNumFrames;
210 : 0 : nNewIndex = (mnCurrIndex + 1) % nNumFrames;
211 : 0 : break;
212 : : }
213 : :
214 : : case CYCLE_PINGPONGLOOP:
215 : : {
216 : : ::std::size_t nTrueIndex( mnCurrIndex < nNumFrames ?
217 : : mnCurrIndex :
218 : 0 : 2*nNumFrames - mnCurrIndex - 1 );
219 : 0 : pDrawShape->setIntrinsicAnimationFrame( nTrueIndex );
220 : :
221 : 0 : mpWakeupEvent->start();
222 : 0 : mpWakeupEvent->setNextTimeout( maTimeouts[nTrueIndex] );
223 : :
224 : 0 : mnLoopCount += (mnCurrIndex + 1) / (2*nNumFrames);
225 : 0 : nNewIndex = (mnCurrIndex + 1) % 2*nNumFrames;
226 : 0 : break;
227 : : }
228 : : }
229 : :
230 : 0 : maContext.mrEventQueue.addEvent( mpWakeupEvent );
231 : 0 : maContext.mpSubsettableShapeManager->notifyShapeUpdate( pDrawShape );
232 : 0 : mnCurrIndex = nNewIndex;
233 : :
234 : 0 : return false; // don't reinsert, WakeupEvent will perform
235 : : // that after the given timeout
236 : : }
237 : :
238 : 0 : bool IntrinsicAnimationActivity::isActive() const
239 : : {
240 : 0 : return mbIsActive;
241 : : }
242 : :
243 : 0 : void IntrinsicAnimationActivity::dequeued()
244 : : {
245 : : // not used here
246 : 0 : }
247 : :
248 : 0 : void IntrinsicAnimationActivity::end()
249 : : {
250 : : // there is no dedicated end state, just become inactive:
251 : 0 : mbIsActive = false;
252 : 0 : }
253 : :
254 : 0 : bool IntrinsicAnimationActivity::enableAnimations()
255 : : {
256 : 0 : mbIsActive = true;
257 : : return maContext.mrActivitiesQueue.addActivity(
258 : 0 : shared_from_this() );
259 : : }
260 : :
261 : : //////////////////////////////////////////////////////////////////////
262 : :
263 : 0 : ActivitySharedPtr createIntrinsicAnimationActivity(
264 : : const SlideShowContext& rContext,
265 : : const DrawShapeSharedPtr& rDrawShape,
266 : : const WakeupEventSharedPtr& rWakeupEvent,
267 : : const ::std::vector<double>& rTimeouts,
268 : : ::std::size_t nNumLoops,
269 : : CycleMode eCycleMode )
270 : : {
271 : : return ActivitySharedPtr(
272 : : new IntrinsicAnimationActivity(rContext,
273 : : rDrawShape,
274 : : rWakeupEvent,
275 : : rTimeouts,
276 : : nNumLoops,
277 : 0 : eCycleMode) );
278 : : }
279 : : }
280 : 0 : }
281 : :
282 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|