bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlsAnimator.cxx
blob0d43120c134fd51fba0c9b0686465f1bb39b9a4c
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"
23 #include <boost/bind.hpp>
25 namespace sd { namespace slidesorter { namespace 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 const Animator::AnimationFunctor& rAnimation,
35 const double nStartOffset,
36 const double nDuration,
37 const double nGlobalTime,
38 const Animator::AnimationId nAnimationId,
39 const Animator::FinishFunctor& rFinishFunctor);
40 ~Animation();
41 /** Run next animation step. If animation has reached its end it is
42 expired.
44 bool Run (const double nGlobalTime);
46 /** Typically called when an animation has finished, but also from
47 Animator::Disposed(). The finish functor is called and the
48 animation is marked as expired to prevent another run.
50 void Expire();
51 bool IsExpired() { return mbIsExpired;}
53 Animator::AnimationFunctor maAnimation;
54 Animator::FinishFunctor maFinishFunctor;
55 const Animator::AnimationId mnAnimationId;
56 const double mnDuration;
57 const double mnEnd;
58 const double mnGlobalTimeAtStart;
59 bool mbIsExpired;
62 Animator::Animator (SlideSorter& rSlideSorter)
63 : mrSlideSorter(rSlideSorter),
64 maIdle(),
65 mbIsDisposed(false),
66 maAnimations(),
67 maElapsedTime(),
68 mpDrawLock(),
69 mnNextAnimationId(0)
71 maIdle.SetPriority(SchedulerPriority::REPAINT);
72 maIdle.SetIdleHdl(LINK(this,Animator,TimeoutHandler));
75 Animator::~Animator()
77 if ( ! mbIsDisposed)
79 OSL_ASSERT(mbIsDisposed);
80 Dispose();
84 void Animator::Dispose()
86 mbIsDisposed = true;
88 AnimationList aCopy (maAnimations);
89 AnimationList::const_iterator iAnimation;
90 for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
91 (*iAnimation)->Expire();
93 maIdle.Stop();
94 if (mpDrawLock)
96 mpDrawLock->Dispose();
97 mpDrawLock.reset();
101 Animator::AnimationId Animator::AddAnimation (
102 const AnimationFunctor& rAnimation,
103 const sal_Int32 nStartOffset,
104 const sal_Int32 nDuration,
105 const FinishFunctor& rFinishFunctor)
107 // When the animator is already disposed then ignore this call
108 // silently (well, we show an assertion, but do not throw an exception.)
109 OSL_ASSERT( ! mbIsDisposed);
110 if (mbIsDisposed)
111 return -1;
113 boost::shared_ptr<Animation> pAnimation (
114 new Animation(
115 rAnimation,
116 nStartOffset / 1000.0,
117 nDuration / 1000.0,
118 maElapsedTime.getElapsedTime(),
119 ++mnNextAnimationId,
120 rFinishFunctor));
121 maAnimations.push_back(pAnimation);
123 RequestNextFrame();
125 return pAnimation->mnAnimationId;
128 void Animator::RemoveAnimation (const Animator::AnimationId nId)
130 OSL_ASSERT( ! mbIsDisposed);
132 const AnimationList::iterator iAnimation (::std::find_if(
133 maAnimations.begin(),
134 maAnimations.end(),
135 ::boost::bind(
136 ::std::equal_to<Animator::AnimationId>(),
137 nId,
138 ::boost::bind(&Animation::mnAnimationId, _1))));
139 if (iAnimation != maAnimations.end())
141 OSL_ASSERT((*iAnimation)->mnAnimationId == nId);
142 (*iAnimation)->Expire();
143 maAnimations.erase(iAnimation);
146 if (maAnimations.empty())
148 // Reset the animation id when we can.
149 mnNextAnimationId = 0;
151 // No more animations => we do not have to suppress painting
152 // anymore.
153 mpDrawLock.reset();
157 void Animator::RemoveAllAnimations()
159 ::std::for_each(
160 maAnimations.begin(),
161 maAnimations.end(),
162 ::boost::bind(
163 &Animation::Expire,
164 _1));
165 maAnimations.clear();
166 mnNextAnimationId = 0;
168 // No more animations => we do not have to suppress painting
169 // anymore.
170 mpDrawLock.reset();
173 bool Animator::ProcessAnimations (const double nTime)
175 bool bExpired (false);
177 OSL_ASSERT( ! mbIsDisposed);
178 if (mbIsDisposed)
179 return bExpired;
181 AnimationList aCopy (maAnimations);
182 AnimationList::const_iterator iAnimation;
183 for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
185 bExpired |= (*iAnimation)->Run(nTime);
188 return bExpired;
191 void Animator::CleanUpAnimationList()
193 OSL_ASSERT( ! mbIsDisposed);
194 if (mbIsDisposed)
195 return;
197 AnimationList aActiveAnimations;
199 AnimationList::const_iterator iAnimation;
200 for (iAnimation=maAnimations.begin(); iAnimation!=maAnimations.end(); ++iAnimation)
202 if ( ! (*iAnimation)->IsExpired())
203 aActiveAnimations.push_back(*iAnimation);
206 maAnimations.swap(aActiveAnimations);
209 void Animator::RequestNextFrame (const double nFrameStart)
211 (void)nFrameStart;
212 if ( ! maIdle.IsActive())
214 // Prevent redraws except for the ones in TimeoutHandler. While the
215 // Animator is active it will schedule repaints regularly. Repaints
216 // in between would only lead to visual artifacts.
217 mpDrawLock.reset(new view::SlideSorterView::DrawLock(mrSlideSorter));
218 maIdle.Start();
222 IMPL_LINK_NOARG_TYPED(Animator, TimeoutHandler, Idle *, void)
224 if (mbIsDisposed)
225 return;
227 if (ProcessAnimations(maElapsedTime.getElapsedTime()))
228 CleanUpAnimationList();
230 // Unlock the draw lock. This should lead to a repaint.
231 mpDrawLock.reset();
233 if (!maAnimations.empty())
234 RequestNextFrame();
237 //===== Animator::Animation ===================================================
239 Animator::Animation::Animation (
240 const Animator::AnimationFunctor& rAnimation,
241 const double nStartOffset,
242 const double nDuration,
243 const double nGlobalTime,
244 const Animator::AnimationId nId,
245 const Animator::FinishFunctor& rFinishFunctor)
246 : maAnimation(rAnimation),
247 maFinishFunctor(rFinishFunctor),
248 mnAnimationId(nId),
249 mnDuration(nDuration),
250 mnEnd(nGlobalTime + nDuration + nStartOffset),
251 mnGlobalTimeAtStart(nGlobalTime + nStartOffset),
252 mbIsExpired(false)
254 Run(nGlobalTime);
257 Animator::Animation::~Animation()
261 bool Animator::Animation::Run (const double nGlobalTime)
263 if ( ! mbIsExpired)
265 if (mnDuration > 0)
267 if (nGlobalTime >= mnEnd)
269 maAnimation(1.0);
270 Expire();
272 else if (nGlobalTime >= mnGlobalTimeAtStart)
274 maAnimation((nGlobalTime - mnGlobalTimeAtStart) / mnDuration);
277 else if (mnDuration < 0)
279 // Animations without end have to be expired by their owner.
280 maAnimation(nGlobalTime);
284 return mbIsExpired;
287 void Animator::Animation::Expire()
289 if ( ! mbIsExpired)
291 mbIsExpired = true;
292 if (maFinishFunctor)
293 maFinishFunctor();
297 } } } // end of namespace ::sd::slidesorter::controller
299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */