bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlsAnimator.cxx
blob3b0b183801f6539e0d047d479fc41b12f8a63f47
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 .
20 #include <controller/SlsAnimator.hxx>
21 #include <view/SlideSorterView.hxx>
22 #include <View.hxx>
24 namespace sd { namespace slidesorter { namespace controller {
26 /** Handle one animation function by using a timer for frequent calls to
27 the animations operator().
29 class Animator::Animation
31 public:
32 Animation (
33 const Animator::AnimationFunctor& rAnimation,
34 const double nStartOffset,
35 const double nDuration,
36 const double nGlobalTime,
37 const Animator::AnimationId nAnimationId,
38 const Animator::FinishFunctor& rFinishFunctor);
39 /** Run next animation step. If animation has reached its end it is
40 expired.
42 bool Run (const double nGlobalTime);
44 /** Typically called when an animation has finished, but also from
45 Animator::Disposed(). The finish functor is called and the
46 animation is marked as expired to prevent another run.
48 void Expire();
49 bool IsExpired() { return mbIsExpired;}
51 Animator::AnimationFunctor const maAnimation;
52 Animator::FinishFunctor const maFinishFunctor;
53 const Animator::AnimationId mnAnimationId;
54 const double mnDuration;
55 const double mnEnd;
56 const double mnGlobalTimeAtStart;
57 bool mbIsExpired;
60 Animator::Animator (SlideSorter& rSlideSorter)
61 : mrSlideSorter(rSlideSorter),
62 maIdle("sd slidesorter controller Animator"),
63 mbIsDisposed(false),
64 maAnimations(),
65 maElapsedTime(),
66 mpDrawLock(),
67 mnNextAnimationId(0)
69 maIdle.SetPriority(TaskPriority::REPAINT);
70 maIdle.SetInvokeHandler(LINK(this,Animator,TimeoutHandler));
73 Animator::~Animator()
75 if ( ! mbIsDisposed)
77 OSL_ASSERT(mbIsDisposed);
78 Dispose();
82 void Animator::Dispose()
84 mbIsDisposed = true;
86 AnimationList aCopy (maAnimations);
87 for (const auto& rxAnimation : aCopy)
88 rxAnimation->Expire();
90 maIdle.Stop();
91 if (mpDrawLock)
93 mpDrawLock->Dispose();
94 mpDrawLock.reset();
98 Animator::AnimationId Animator::AddAnimation (
99 const AnimationFunctor& rAnimation,
100 const FinishFunctor& rFinishFunctor)
102 // When the animator is already disposed then ignore this call
103 // silently (well, we show an assertion, but do not throw an exception.)
104 OSL_ASSERT( ! mbIsDisposed);
105 if (mbIsDisposed)
106 return -1;
108 std::shared_ptr<Animation> pAnimation (
109 new Animation(
110 rAnimation,
112 300 / 1000.0,
113 maElapsedTime.getElapsedTime(),
114 ++mnNextAnimationId,
115 rFinishFunctor));
116 maAnimations.push_back(pAnimation);
118 RequestNextFrame();
120 return pAnimation->mnAnimationId;
123 void Animator::RemoveAnimation (const Animator::AnimationId nId)
125 OSL_ASSERT( ! mbIsDisposed);
127 const AnimationList::iterator iAnimation (::std::find_if(
128 maAnimations.begin(),
129 maAnimations.end(),
130 [nId] (std::shared_ptr<Animation> const& pAnim)
131 { return nId == pAnim->mnAnimationId; }));
132 if (iAnimation != maAnimations.end())
134 OSL_ASSERT((*iAnimation)->mnAnimationId == nId);
135 (*iAnimation)->Expire();
136 maAnimations.erase(iAnimation);
139 if (maAnimations.empty())
141 // Reset the animation id when we can.
142 mnNextAnimationId = 0;
144 // No more animations => we do not have to suppress painting
145 // anymore.
146 mpDrawLock.reset();
150 void Animator::RemoveAllAnimations()
152 for (auto const& it : maAnimations)
154 it->Expire();
156 maAnimations.clear();
157 mnNextAnimationId = 0;
159 // No more animations => we do not have to suppress painting
160 // anymore.
161 mpDrawLock.reset();
164 bool Animator::ProcessAnimations (const double nTime)
166 bool bExpired (false);
168 OSL_ASSERT( ! mbIsDisposed);
169 if (mbIsDisposed)
170 return bExpired;
172 AnimationList aCopy (maAnimations);
173 for (const auto& rxAnimation : aCopy)
175 bExpired |= rxAnimation->Run(nTime);
178 return bExpired;
181 void Animator::CleanUpAnimationList()
183 OSL_ASSERT( ! mbIsDisposed);
184 if (mbIsDisposed)
185 return;
187 AnimationList aActiveAnimations;
189 for (const auto& rxAnimation : maAnimations)
191 if ( ! rxAnimation->IsExpired())
192 aActiveAnimations.push_back(rxAnimation);
195 maAnimations.swap(aActiveAnimations);
198 void Animator::RequestNextFrame ()
200 if ( ! maIdle.IsActive())
202 // Prevent redraws except for the ones in TimeoutHandler. While the
203 // Animator is active it will schedule repaints regularly. Repaints
204 // in between would only lead to visual artifacts.
205 mpDrawLock.reset(new view::SlideSorterView::DrawLock(mrSlideSorter));
206 maIdle.Start();
210 IMPL_LINK_NOARG(Animator, TimeoutHandler, Timer *, void)
212 if (mbIsDisposed)
213 return;
215 if (ProcessAnimations(maElapsedTime.getElapsedTime()))
216 CleanUpAnimationList();
218 // Unlock the draw lock. This should lead to a repaint.
219 mpDrawLock.reset();
221 if (!maAnimations.empty())
222 RequestNextFrame();
225 //===== Animator::Animation ===================================================
227 Animator::Animation::Animation (
228 const Animator::AnimationFunctor& rAnimation,
229 const double nStartOffset,
230 const double nDuration,
231 const double nGlobalTime,
232 const Animator::AnimationId nId,
233 const Animator::FinishFunctor& rFinishFunctor)
234 : maAnimation(rAnimation),
235 maFinishFunctor(rFinishFunctor),
236 mnAnimationId(nId),
237 mnDuration(nDuration),
238 mnEnd(nGlobalTime + nDuration + nStartOffset),
239 mnGlobalTimeAtStart(nGlobalTime + nStartOffset),
240 mbIsExpired(false)
242 Run(nGlobalTime);
245 bool Animator::Animation::Run (const double nGlobalTime)
247 if ( ! mbIsExpired)
249 if (mnDuration > 0)
251 if (nGlobalTime >= mnEnd)
253 maAnimation(1.0);
254 Expire();
256 else if (nGlobalTime >= mnGlobalTimeAtStart)
258 maAnimation((nGlobalTime - mnGlobalTimeAtStart) / mnDuration);
261 else if (mnDuration < 0)
263 // Animations without end have to be expired by their owner.
264 maAnimation(nGlobalTime);
268 return mbIsExpired;
271 void Animator::Animation::Expire()
273 if ( ! mbIsExpired)
275 mbIsExpired = true;
276 if (maFinishFunctor)
277 maFinishFunctor();
281 } } } // end of namespace ::sd::slidesorter::controller
283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */