1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <canvas/debug.hxx>
22 #include <tools/diagnose_ex.h>
23 #include <canvas/verbosetrace.hxx>
25 #include "drawshapesubsetting.hxx"
26 #include "subsettableshapemanager.hxx"
27 #include "eventqueue.hxx"
28 #include "eventmultiplexer.hxx"
29 #include "intrinsicanimationactivity.hxx"
30 #include "intrinsicanimationeventhandler.hxx"
32 #include <boost/noncopyable.hpp>
33 #include <boost/enable_shared_from_this.hpp>
34 #include <boost/weak_ptr.hpp>
40 /** Activity for intrinsic shape animations
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.
47 class IntrinsicAnimationActivity
: public Activity
,
48 public boost::enable_shared_from_this
<IntrinsicAnimationActivity
>,
49 private boost::noncopyable
52 /** Create an IntrinsicAnimationActivity.
55 Common slideshow objects
58 Shape to control the intrinsic animation for
61 Externally generated wakeup event, to set this
62 activity to sleep during inter-frame intervals. Must
63 come from the outside, since wakeup event and this
64 object have mutual references to each other.
67 Vector of timeout values, to wait before the next
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
);
77 virtual void dispose() SAL_OVERRIDE
;
78 virtual double calcTimeLag() const SAL_OVERRIDE
;
79 virtual bool perform() SAL_OVERRIDE
;
80 virtual bool isActive() const SAL_OVERRIDE
;
81 virtual void dequeued() SAL_OVERRIDE
;
82 virtual void end() SAL_OVERRIDE
;
84 bool enableAnimations();
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
;
101 class IntrinsicAnimationListener
: public IntrinsicAnimationEventHandler
,
102 private boost::noncopyable
105 explicit IntrinsicAnimationListener( IntrinsicAnimationActivity
& rActivity
) :
106 mrActivity( rActivity
)
111 virtual bool enableAnimations() SAL_OVERRIDE
{ return mrActivity
.enableAnimations(); }
112 virtual bool disableAnimations() SAL_OVERRIDE
{ mrActivity
.end(); return true; }
114 IntrinsicAnimationActivity
& mrActivity
;
119 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 mpListener( new IntrinsicAnimationListener(*this) ),
129 maTimeouts( rTimeouts
),
130 meCycleMode( eCycleMode
),
132 mnNumLoops(nNumLoops
),
136 ENSURE_OR_THROW( rContext
.mpSubsettableShapeManager
,
137 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" );
138 ENSURE_OR_THROW( rDrawShape
,
139 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" );
140 ENSURE_OR_THROW( rWakeupEvent
,
141 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" );
142 ENSURE_OR_THROW( !rTimeouts
.empty(),
143 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" );
145 maContext
.mpSubsettableShapeManager
->addIntrinsicAnimationHandler(
149 void IntrinsicAnimationActivity::dispose()
154 mpWakeupEvent
->dispose();
158 mpWakeupEvent
.reset();
162 maContext
.mpSubsettableShapeManager
->removeIntrinsicAnimationHandler(
166 double IntrinsicAnimationActivity::calcTimeLag() const
171 bool IntrinsicAnimationActivity::perform()
176 DrawShapeSharedPtr
pDrawShape( mpDrawShape
.lock() );
177 if( !pDrawShape
|| !mpWakeupEvent
)
179 // event or draw shape vanished, no sense living on ->
185 // mnNumLoops == 0 means infinite looping
186 if( mnNumLoops
!= 0 &&
187 mnLoopCount
>= mnNumLoops
)
189 // #i55294# After finishing the loops, display the first frame
190 pDrawShape
->setIntrinsicAnimationFrame( 0 );
191 maContext
.mpSubsettableShapeManager
->notifyShapeUpdate( pDrawShape
);
198 ::std::size_t nNewIndex
= 0;
199 const ::std::size_t nNumFrames(maTimeouts
.size());
200 switch( meCycleMode
)
204 pDrawShape
->setIntrinsicAnimationFrame( mnCurrIndex
);
206 mpWakeupEvent
->start();
207 mpWakeupEvent
->setNextTimeout( maTimeouts
[mnCurrIndex
] );
209 mnLoopCount
+= (mnCurrIndex
+ 1) / nNumFrames
;
210 nNewIndex
= (mnCurrIndex
+ 1) % nNumFrames
;
214 case CYCLE_PINGPONGLOOP
:
216 ::std::size_t nTrueIndex( mnCurrIndex
< nNumFrames
?
218 2*nNumFrames
- mnCurrIndex
- 1 );
219 pDrawShape
->setIntrinsicAnimationFrame( nTrueIndex
);
221 mpWakeupEvent
->start();
222 mpWakeupEvent
->setNextTimeout( maTimeouts
[nTrueIndex
] );
224 mnLoopCount
+= (mnCurrIndex
+ 1) / (2*nNumFrames
);
225 nNewIndex
= (mnCurrIndex
+ 1) % 2*nNumFrames
;
230 maContext
.mrEventQueue
.addEvent( mpWakeupEvent
);
231 maContext
.mpSubsettableShapeManager
->notifyShapeUpdate( pDrawShape
);
232 mnCurrIndex
= nNewIndex
;
234 return false; // don't reinsert, WakeupEvent will perform
235 // that after the given timeout
238 bool IntrinsicAnimationActivity::isActive() const
243 void IntrinsicAnimationActivity::dequeued()
248 void IntrinsicAnimationActivity::end()
250 // there is no dedicated end state, just become inactive:
254 bool IntrinsicAnimationActivity::enableAnimations()
257 return maContext
.mrActivitiesQueue
.addActivity(
258 shared_from_this() );
263 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
)
271 return ActivitySharedPtr(
272 new IntrinsicAnimationActivity(rContext
,
282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */