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 .
20 #include <controller/SlsAnimator.hxx>
21 #include <view/SlideSorterView.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
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
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.
49 bool IsExpired() { return mbIsExpired
;}
51 Animator::AnimationFunctor
const maAnimation
;
52 Animator::FinishFunctor
const maFinishFunctor
;
53 const Animator::AnimationId mnAnimationId
;
54 const double mnDuration
;
56 const double mnGlobalTimeAtStart
;
60 Animator::Animator (SlideSorter
& rSlideSorter
)
61 : mrSlideSorter(rSlideSorter
),
62 maIdle("sd slidesorter controller Animator"),
69 maIdle
.SetPriority(TaskPriority::REPAINT
);
70 maIdle
.SetInvokeHandler(LINK(this,Animator
,TimeoutHandler
));
77 OSL_ASSERT(mbIsDisposed
);
82 void Animator::Dispose()
86 AnimationList
aCopy (maAnimations
);
87 for (const auto& rxAnimation
: aCopy
)
88 rxAnimation
->Expire();
93 mpDrawLock
->Dispose();
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
);
108 std::shared_ptr
<Animation
> pAnimation (
113 maElapsedTime
.getElapsedTime(),
116 maAnimations
.push_back(pAnimation
);
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(),
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
150 void Animator::RemoveAllAnimations()
152 for (auto const& it
: maAnimations
)
156 maAnimations
.clear();
157 mnNextAnimationId
= 0;
159 // No more animations => we do not have to suppress painting
164 bool Animator::ProcessAnimations (const double nTime
)
166 bool bExpired (false);
168 OSL_ASSERT( ! mbIsDisposed
);
172 AnimationList
aCopy (maAnimations
);
173 for (const auto& rxAnimation
: aCopy
)
175 bExpired
|= rxAnimation
->Run(nTime
);
181 void Animator::CleanUpAnimationList()
183 OSL_ASSERT( ! mbIsDisposed
);
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
));
210 IMPL_LINK_NOARG(Animator
, TimeoutHandler
, Timer
*, void)
215 if (ProcessAnimations(maElapsedTime
.getElapsedTime()))
216 CleanUpAnimationList();
218 // Unlock the draw lock. This should lead to a repaint.
221 if (!maAnimations
.empty())
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
),
237 mnDuration(nDuration
),
238 mnEnd(nGlobalTime
+ nDuration
+ nStartOffset
),
239 mnGlobalTimeAtStart(nGlobalTime
+ nStartOffset
),
245 bool Animator::Animation::Run (const double nGlobalTime
)
251 if (nGlobalTime
>= mnEnd
)
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
);
271 void Animator::Animation::Expire()
281 } } } // end of namespace ::sd::slidesorter::controller
283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */