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 <tools/diagnose_ex.h>
23 #include "drawshapesubsetting.hxx"
24 #include "subsettableshapemanager.hxx"
25 #include "eventqueue.hxx"
26 #include "eventmultiplexer.hxx"
27 #include "intrinsicanimationactivity.hxx"
28 #include "intrinsicanimationeventhandler.hxx"
36 /** Activity for intrinsic shape animations
38 This is an Activity interface implementation for intrinsic
39 shape animations. Intrinsic shape animations are
40 animations directly within a shape, e.g. drawing layer
41 animations, or GIF animations.
43 class IntrinsicAnimationActivity
: public Activity
46 /** Create an IntrinsicAnimationActivity.
49 Common slideshow objects
52 Shape to control the intrinsic animation for
55 Externally generated wakeup event, to set this
56 activity to sleep during inter-frame intervals. Must
57 come from the outside, since wakeup event and this
58 object have mutual references to each other.
61 Vector of timeout values, to wait before the next
64 IntrinsicAnimationActivity( const SlideShowContext
& rContext
,
65 const DrawShapeSharedPtr
& rDrawShape
,
66 const WakeupEventSharedPtr
& rWakeupEvent
,
67 const ::std::vector
<double>& rTimeouts
,
68 ::std::size_t nNumLoops
,
69 CycleMode eCycleMode
);
70 IntrinsicAnimationActivity(const IntrinsicAnimationActivity
&) = delete;
71 IntrinsicAnimationActivity
& operator=(const IntrinsicAnimationActivity
&) = delete;
73 virtual void dispose() override
;
74 virtual double calcTimeLag() const override
;
75 virtual bool perform() override
;
76 virtual bool isActive() const override
;
77 virtual void dequeued() override
;
78 virtual void end() override
;
80 bool enableAnimations();
83 SlideShowContext maContext
;
84 std::weak_ptr
<DrawShape
> mpDrawShape
;
85 WakeupEventSharedPtr mpWakeupEvent
;
86 IntrinsicAnimationEventHandlerSharedPtr mpListener
;
87 ::std::vector
<double> maTimeouts
;
88 CycleMode meCycleMode
;
89 ::std::size_t mnCurrIndex
;
90 ::std::size_t mnNumLoops
;
91 ::std::size_t mnLoopCount
;
96 class IntrinsicAnimationListener
: public IntrinsicAnimationEventHandler
99 explicit IntrinsicAnimationListener( IntrinsicAnimationActivity
& rActivity
) :
100 mrActivity( rActivity
)
102 IntrinsicAnimationListener(const IntrinsicAnimationListener
&) = delete;
103 IntrinsicAnimationListener
& operator=(const IntrinsicAnimationListener
&) = delete;
107 virtual bool enableAnimations() override
{ return mrActivity
.enableAnimations(); }
108 virtual bool disableAnimations() override
{ mrActivity
.end(); return true; }
110 IntrinsicAnimationActivity
& mrActivity
;
114 IntrinsicAnimationActivity::IntrinsicAnimationActivity( const SlideShowContext
& rContext
,
115 const DrawShapeSharedPtr
& rDrawShape
,
116 const WakeupEventSharedPtr
& rWakeupEvent
,
117 const ::std::vector
<double>& rTimeouts
,
118 ::std::size_t nNumLoops
,
119 CycleMode eCycleMode
) :
120 maContext( rContext
),
121 mpDrawShape( rDrawShape
),
122 mpWakeupEvent( rWakeupEvent
),
123 mpListener( new IntrinsicAnimationListener(*this) ),
124 maTimeouts( rTimeouts
),
125 meCycleMode( eCycleMode
),
127 mnNumLoops(nNumLoops
),
131 ENSURE_OR_THROW( rContext
.mpSubsettableShapeManager
,
132 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" );
133 ENSURE_OR_THROW( rDrawShape
,
134 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" );
135 ENSURE_OR_THROW( rWakeupEvent
,
136 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" );
137 ENSURE_OR_THROW( !rTimeouts
.empty(),
138 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" );
140 maContext
.mpSubsettableShapeManager
->addIntrinsicAnimationHandler(
144 void IntrinsicAnimationActivity::dispose()
149 mpWakeupEvent
->dispose();
153 mpWakeupEvent
.reset();
157 maContext
.mpSubsettableShapeManager
->removeIntrinsicAnimationHandler(
161 double IntrinsicAnimationActivity::calcTimeLag() const
166 bool IntrinsicAnimationActivity::perform()
171 DrawShapeSharedPtr
pDrawShape( mpDrawShape
.lock() );
172 if( !pDrawShape
|| !mpWakeupEvent
)
174 // event or draw shape vanished, no sense living on ->
180 // mnNumLoops == 0 means infinite looping
181 if( mnNumLoops
!= 0 &&
182 mnLoopCount
>= mnNumLoops
)
184 // #i55294# After finishing the loops, display the first frame
185 pDrawShape
->setIntrinsicAnimationFrame( 0 );
186 maContext
.mpSubsettableShapeManager
->notifyShapeUpdate( pDrawShape
);
193 ::std::size_t nNewIndex
= 0;
194 const ::std::size_t nNumFrames(maTimeouts
.size());
195 switch( meCycleMode
)
199 pDrawShape
->setIntrinsicAnimationFrame( mnCurrIndex
);
201 mpWakeupEvent
->start();
202 mpWakeupEvent
->setNextTimeout( maTimeouts
[mnCurrIndex
] );
204 mnLoopCount
+= (mnCurrIndex
+ 1) / nNumFrames
;
205 nNewIndex
= (mnCurrIndex
+ 1) % nNumFrames
;
209 case CYCLE_PINGPONGLOOP
:
211 ::std::size_t nTrueIndex( mnCurrIndex
< nNumFrames
?
213 2*nNumFrames
- mnCurrIndex
- 1 );
214 pDrawShape
->setIntrinsicAnimationFrame( nTrueIndex
);
216 mpWakeupEvent
->start();
217 mpWakeupEvent
->setNextTimeout( maTimeouts
[nTrueIndex
] );
219 mnLoopCount
+= (mnCurrIndex
+ 1) / (2*nNumFrames
);
220 nNewIndex
= (mnCurrIndex
+ 1) % 2*nNumFrames
;
225 maContext
.mrEventQueue
.addEvent( mpWakeupEvent
);
226 maContext
.mpSubsettableShapeManager
->notifyShapeUpdate( pDrawShape
);
227 mnCurrIndex
= nNewIndex
;
229 return false; // don't reinsert, WakeupEvent will perform
230 // that after the given timeout
233 bool IntrinsicAnimationActivity::isActive() const
238 void IntrinsicAnimationActivity::dequeued()
243 void IntrinsicAnimationActivity::end()
245 // there is no dedicated end state, just become inactive:
249 bool IntrinsicAnimationActivity::enableAnimations()
252 return maContext
.mrActivitiesQueue
.addActivity( std::dynamic_pointer_cast
<Activity
>(shared_from_this()) );
257 ActivitySharedPtr
createIntrinsicAnimationActivity(
258 const SlideShowContext
& rContext
,
259 const DrawShapeSharedPtr
& rDrawShape
,
260 const WakeupEventSharedPtr
& rWakeupEvent
,
261 const ::std::vector
<double>& rTimeouts
,
262 ::std::size_t nNumLoops
,
263 CycleMode eCycleMode
)
265 return ActivitySharedPtr(
266 new IntrinsicAnimationActivity(rContext
,
276 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */