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 <comphelper/diagnose_ex.hxx>
23 #include <subsettableshapemanager.hxx>
24 #include <eventqueue.hxx>
25 #include "intrinsicanimationactivity.hxx"
26 #include <intrinsicanimationeventhandler.hxx>
30 namespace slideshow::internal
34 /** Activity for intrinsic shape animations
36 This is an Activity interface implementation for intrinsic
37 shape animations. Intrinsic shape animations are
38 animations directly within a shape, e.g. drawing layer
39 animations, or GIF animations.
41 class IntrinsicAnimationActivity
: public Activity
44 /** Create an IntrinsicAnimationActivity.
47 Common slideshow objects
50 Shape to control the intrinsic animation for
53 Externally generated wakeup event, to set this
54 activity to sleep during inter-frame intervals. Must
55 come from the outside, since wakeup event and this
56 object have mutual references to each other.
59 Vector of timeout values, to wait before the next
62 IntrinsicAnimationActivity( const SlideShowContext
& rContext
,
63 const DrawShapeSharedPtr
& rDrawShape
,
64 const WakeupEventSharedPtr
& rWakeupEvent
,
65 ::std::vector
<double>&& rTimeouts
,
66 ::std::size_t nNumLoops
);
67 IntrinsicAnimationActivity(const IntrinsicAnimationActivity
&) = delete;
68 IntrinsicAnimationActivity
& operator=(const IntrinsicAnimationActivity
&) = delete;
70 virtual void dispose() override
;
71 virtual double calcTimeLag() const override
;
72 virtual bool perform() override
;
73 virtual bool isActive() const override
;
74 virtual void dequeued() override
;
75 virtual void end() override
;
77 bool enableAnimations();
80 SlideShowContext maContext
;
81 std::weak_ptr
<DrawShape
> mpDrawShape
;
82 WakeupEventSharedPtr mpWakeupEvent
;
83 IntrinsicAnimationEventHandlerSharedPtr mpListener
;
84 ::std::vector
<double> maTimeouts
;
85 ::std::size_t mnCurrIndex
;
86 ::std::size_t mnNumLoops
;
87 ::std::size_t mnLoopCount
;
92 class IntrinsicAnimationListener
: public IntrinsicAnimationEventHandler
95 explicit IntrinsicAnimationListener( IntrinsicAnimationActivity
& rActivity
) :
96 mrActivity( rActivity
)
98 IntrinsicAnimationListener(const IntrinsicAnimationListener
&) = delete;
99 IntrinsicAnimationListener
& operator=(const IntrinsicAnimationListener
&) = delete;
103 virtual bool enableAnimations() override
{ return mrActivity
.enableAnimations(); }
104 virtual bool disableAnimations() override
{ mrActivity
.end(); return true; }
106 IntrinsicAnimationActivity
& mrActivity
;
111 IntrinsicAnimationActivity::IntrinsicAnimationActivity( const SlideShowContext
& rContext
,
112 const DrawShapeSharedPtr
& rDrawShape
,
113 const WakeupEventSharedPtr
& rWakeupEvent
,
114 ::std::vector
<double>&& rTimeouts
,
115 ::std::size_t nNumLoops
) :
116 maContext( rContext
),
117 mpDrawShape( rDrawShape
),
118 mpWakeupEvent( rWakeupEvent
),
119 mpListener( std::make_shared
<IntrinsicAnimationListener
>(*this) ),
120 maTimeouts( std::move(rTimeouts
) ),
122 mnNumLoops(nNumLoops
),
126 ENSURE_OR_THROW( rContext
.mpSubsettableShapeManager
,
127 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid shape manager" );
128 ENSURE_OR_THROW( rDrawShape
,
129 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid draw shape" );
130 ENSURE_OR_THROW( rWakeupEvent
,
131 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Invalid wakeup event" );
132 ENSURE_OR_THROW( !maTimeouts
.empty(),
133 "IntrinsicAnimationActivity::IntrinsicAnimationActivity(): Empty timeout vector" );
135 maContext
.mpSubsettableShapeManager
->addIntrinsicAnimationHandler(
139 void IntrinsicAnimationActivity::dispose()
144 mpWakeupEvent
->dispose();
148 mpWakeupEvent
.reset();
152 maContext
.mpSubsettableShapeManager
->removeIntrinsicAnimationHandler(
156 double IntrinsicAnimationActivity::calcTimeLag() const
161 bool IntrinsicAnimationActivity::perform()
166 DrawShapeSharedPtr
pDrawShape( mpDrawShape
.lock() );
167 if( !pDrawShape
|| !mpWakeupEvent
)
169 // event or draw shape vanished, no sense living on ->
175 const ::std::size_t nNumFrames(maTimeouts
.size());
177 // mnNumLoops == 0 means infinite looping
178 if( mnNumLoops
!= 0 &&
179 mnLoopCount
>= mnNumLoops
)
181 // #i55294# After finishing the loops, display the last frame
182 // powerpoint 2013 and firefox etc show the last frame when
183 // the animation ends
184 pDrawShape
->setIntrinsicAnimationFrame(nNumFrames
- 1);
185 maContext
.mpSubsettableShapeManager
->notifyShapeUpdate( pDrawShape
);
192 ::std::size_t nNewIndex
= 0;
194 pDrawShape
->setIntrinsicAnimationFrame( mnCurrIndex
);
196 mpWakeupEvent
->start();
197 mpWakeupEvent
->setNextTimeout( maTimeouts
[mnCurrIndex
] );
199 mnLoopCount
+= (mnCurrIndex
+ 1) / nNumFrames
;
200 nNewIndex
= (mnCurrIndex
+ 1) % nNumFrames
;
202 maContext
.mrEventQueue
.addEvent( mpWakeupEvent
);
203 maContext
.mpSubsettableShapeManager
->notifyShapeUpdate( pDrawShape
);
204 mnCurrIndex
= nNewIndex
;
206 return false; // don't reinsert, WakeupEvent will perform
207 // that after the given timeout
210 bool IntrinsicAnimationActivity::isActive() const
215 void IntrinsicAnimationActivity::dequeued()
220 void IntrinsicAnimationActivity::end()
222 // there is no dedicated end state, just become inactive:
226 bool IntrinsicAnimationActivity::enableAnimations()
229 return maContext
.mrActivitiesQueue
.addActivity( std::dynamic_pointer_cast
<Activity
>(shared_from_this()) );
234 ActivitySharedPtr
createIntrinsicAnimationActivity(
235 const SlideShowContext
& rContext
,
236 const DrawShapeSharedPtr
& rDrawShape
,
237 const WakeupEventSharedPtr
& rWakeupEvent
,
238 ::std::vector
<double>&& rTimeouts
,
239 sal_uInt32 nNumLoops
)
241 return std::make_shared
<IntrinsicAnimationActivity
>(rContext
,
244 std::move(rTimeouts
),
249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */