Update git submodules
[LibreOffice.git] / slideshow / source / engine / shapes / intrinsicanimationactivity.cxx
blob86d62935dd3aa1ee351ba7bf7940d3505f932757
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
28 #include <memory>
30 namespace slideshow::internal
32 namespace {
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
43 public:
44 /** Create an IntrinsicAnimationActivity.
46 @param rContext
47 Common slideshow objects
49 @param rDrawShape
50 Shape to control the intrinsic animation for
52 @param rWakeupEvent
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.
58 @param rTimeouts
59 Vector of timeout values, to wait before the next
60 frame is shown.
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();
79 private:
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;
88 bool mbIsActive;
92 class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler
94 public:
95 explicit IntrinsicAnimationListener( IntrinsicAnimationActivity& rActivity ) :
96 mrActivity( rActivity )
98 IntrinsicAnimationListener(const IntrinsicAnimationListener&) = delete;
99 IntrinsicAnimationListener& operator=(const IntrinsicAnimationListener&) = delete;
101 private:
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) ),
121 mnCurrIndex(0),
122 mnNumLoops(nNumLoops),
123 mnLoopCount(0),
124 mbIsActive(false)
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(
136 mpListener );
139 void IntrinsicAnimationActivity::dispose()
141 end();
143 if( mpWakeupEvent )
144 mpWakeupEvent->dispose();
146 maContext.dispose();
147 mpDrawShape.reset();
148 mpWakeupEvent.reset();
149 maTimeouts.clear();
150 mnCurrIndex = 0;
152 maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler(
153 mpListener );
156 double IntrinsicAnimationActivity::calcTimeLag() const
158 return 0.0;
161 bool IntrinsicAnimationActivity::perform()
163 if( !isActive() )
164 return false;
166 DrawShapeSharedPtr pDrawShape( mpDrawShape.lock() );
167 if( !pDrawShape || !mpWakeupEvent )
169 // event or draw shape vanished, no sense living on ->
170 // commit suicide.
171 dispose();
172 return false;
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 );
187 end();
189 return false;
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
212 return mbIsActive;
215 void IntrinsicAnimationActivity::dequeued()
217 // not used here
220 void IntrinsicAnimationActivity::end()
222 // there is no dedicated end state, just become inactive:
223 mbIsActive = false;
226 bool IntrinsicAnimationActivity::enableAnimations()
228 mbIsActive = true;
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,
242 rDrawShape,
243 rWakeupEvent,
244 std::move(rTimeouts),
245 nNumLoops);
249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */