tdf#154285 Check upper bound of arguments in SbRtl_Minute function
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlsAnimator.cxx
blobeb04eceb7831ad88f74c6d191cb0df8561f37e2e
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 <utility>
22 #include <view/SlideSorterView.hxx>
23 #include <osl/diagnose.h>
25 namespace sd::slidesorter::controller {
27 /** Handle one animation function by using a timer for frequent calls to
28 the animations operator().
30 class Animator::Animation
32 public:
33 Animation (
34 Animator::AnimationFunctor aAnimation,
35 const double nStartOffset,
36 const double nDuration,
37 const double nGlobalTime,
38 const Animator::AnimationId nAnimationId,
39 Animator::FinishFunctor aFinishFunctor);
40 /** Run next animation step. If animation has reached its end it is
41 expired.
43 bool Run (const double nGlobalTime);
45 /** Typically called when an animation has finished, but also from
46 Animator::Disposed(). The finish functor is called and the
47 animation is marked as expired to prevent another run.
49 void Expire();
50 bool IsExpired() const { return mbIsExpired;}
52 Animator::AnimationFunctor maAnimation;
53 Animator::FinishFunctor maFinishFunctor;
54 const Animator::AnimationId mnAnimationId;
55 const double mnDuration;
56 const double mnEnd;
57 const double mnGlobalTimeAtStart;
58 bool mbIsExpired;
61 Animator::Animator (SlideSorter& rSlideSorter)
62 : mrSlideSorter(rSlideSorter),
63 maIdle("sd slidesorter controller Animator"),
64 mbIsDisposed(false),
65 mnNextAnimationId(0)
67 maIdle.SetPriority(TaskPriority::REPAINT);
68 maIdle.SetInvokeHandler(LINK(this,Animator,TimeoutHandler));
71 Animator::~Animator()
73 if ( ! mbIsDisposed)
75 OSL_ASSERT(mbIsDisposed);
76 Dispose();
80 void Animator::Dispose()
82 mbIsDisposed = true;
84 AnimationList aCopy (maAnimations);
85 for (const auto& rxAnimation : aCopy)
86 rxAnimation->Expire();
88 maIdle.Stop();
89 if (mpDrawLock)
91 mpDrawLock->Dispose();
92 mpDrawLock.reset();
96 Animator::AnimationId Animator::AddAnimation (
97 const AnimationFunctor& rAnimation,
98 const FinishFunctor& rFinishFunctor)
100 // When the animator is already disposed then ignore this call
101 // silently (well, we show an assertion, but do not throw an exception.)
102 OSL_ASSERT( ! mbIsDisposed);
103 if (mbIsDisposed)
104 return -1;
106 std::shared_ptr<Animation> pAnimation =
107 std::make_shared<Animation>(
108 rAnimation,
110 300 / 1000.0,
111 maElapsedTime.getElapsedTime(),
112 ++mnNextAnimationId,
113 rFinishFunctor);
114 maAnimations.push_back(pAnimation);
116 RequestNextFrame();
118 return pAnimation->mnAnimationId;
121 void Animator::RemoveAnimation (const Animator::AnimationId nId)
123 OSL_ASSERT( ! mbIsDisposed);
125 const AnimationList::iterator iAnimation (::std::find_if(
126 maAnimations.begin(),
127 maAnimations.end(),
128 [nId] (std::shared_ptr<Animation> const& pAnim)
129 { return nId == pAnim->mnAnimationId; }));
130 if (iAnimation != maAnimations.end())
132 OSL_ASSERT((*iAnimation)->mnAnimationId == nId);
133 (*iAnimation)->Expire();
134 maAnimations.erase(iAnimation);
137 if (maAnimations.empty())
139 // Reset the animation id when we can.
140 mnNextAnimationId = 0;
142 // No more animations => we do not have to suppress painting
143 // anymore.
144 mpDrawLock.reset();
148 void Animator::RemoveAllAnimations()
150 for (auto const& it : maAnimations)
152 it->Expire();
154 maAnimations.clear();
155 mnNextAnimationId = 0;
157 // No more animations => we do not have to suppress painting
158 // anymore.
159 mpDrawLock.reset();
162 bool Animator::ProcessAnimations (const double nTime)
164 bool bExpired (false);
166 OSL_ASSERT( ! mbIsDisposed);
167 if (mbIsDisposed)
168 return bExpired;
170 AnimationList aCopy (maAnimations);
171 for (const auto& rxAnimation : aCopy)
173 bExpired |= rxAnimation->Run(nTime);
176 return bExpired;
179 void Animator::CleanUpAnimationList()
181 OSL_ASSERT( ! mbIsDisposed);
182 if (mbIsDisposed)
183 return;
185 AnimationList aActiveAnimations;
187 for (const auto& rxAnimation : maAnimations)
189 if ( ! rxAnimation->IsExpired())
190 aActiveAnimations.push_back(rxAnimation);
193 maAnimations.swap(aActiveAnimations);
196 void Animator::RequestNextFrame ()
198 if ( ! maIdle.IsActive())
200 // Prevent redraws except for the ones in TimeoutHandler. While the
201 // Animator is active it will schedule repaints regularly. Repaints
202 // in between would only lead to visual artifacts.
203 mpDrawLock.reset(new view::SlideSorterView::DrawLock(mrSlideSorter));
204 maIdle.Start();
208 IMPL_LINK_NOARG(Animator, TimeoutHandler, Timer *, void)
210 if (mbIsDisposed)
211 return;
213 if (ProcessAnimations(maElapsedTime.getElapsedTime()))
214 CleanUpAnimationList();
216 // Unlock the draw lock. This should lead to a repaint.
217 mpDrawLock.reset();
219 if (!maAnimations.empty())
220 RequestNextFrame();
223 //===== Animator::Animation ===================================================
225 Animator::Animation::Animation (
226 Animator::AnimationFunctor aAnimation,
227 const double nStartOffset,
228 const double nDuration,
229 const double nGlobalTime,
230 const Animator::AnimationId nId,
231 Animator::FinishFunctor aFinishFunctor)
232 : maAnimation(std::move(aAnimation)),
233 maFinishFunctor(std::move(aFinishFunctor)),
234 mnAnimationId(nId),
235 mnDuration(nDuration),
236 mnEnd(nGlobalTime + nDuration + nStartOffset),
237 mnGlobalTimeAtStart(nGlobalTime + nStartOffset),
238 mbIsExpired(false)
240 Run(nGlobalTime);
243 bool Animator::Animation::Run (const double nGlobalTime)
245 if ( ! mbIsExpired)
247 if (mnDuration > 0)
249 if (nGlobalTime >= mnEnd)
251 maAnimation(1.0);
252 Expire();
254 else if (nGlobalTime >= mnGlobalTimeAtStart)
256 maAnimation((nGlobalTime - mnGlobalTimeAtStart) / mnDuration);
259 else if (mnDuration < 0)
261 // Animations without end have to be expired by their owner.
262 maAnimation(nGlobalTime);
266 return mbIsExpired;
269 void Animator::Animation::Expire()
271 if ( ! mbIsExpired)
273 mbIsExpired = true;
274 if (maFinishFunctor)
275 maFinishFunctor();
279 } // end of namespace ::sd::slidesorter::controller
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */