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>
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
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
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.
50 bool IsExpired() const { return mbIsExpired
;}
52 Animator::AnimationFunctor maAnimation
;
53 Animator::FinishFunctor maFinishFunctor
;
54 const Animator::AnimationId mnAnimationId
;
55 const double mnDuration
;
57 const double mnGlobalTimeAtStart
;
61 Animator::Animator (SlideSorter
& rSlideSorter
)
62 : mrSlideSorter(rSlideSorter
),
63 maIdle("sd slidesorter controller Animator"),
67 maIdle
.SetPriority(TaskPriority::REPAINT
);
68 maIdle
.SetInvokeHandler(LINK(this,Animator
,TimeoutHandler
));
75 OSL_ASSERT(mbIsDisposed
);
80 void Animator::Dispose()
84 AnimationList
aCopy (maAnimations
);
85 for (const auto& rxAnimation
: aCopy
)
86 rxAnimation
->Expire();
91 mpDrawLock
->Dispose();
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
);
106 std::shared_ptr
<Animation
> pAnimation
=
107 std::make_shared
<Animation
>(
111 maElapsedTime
.getElapsedTime(),
114 maAnimations
.push_back(pAnimation
);
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(),
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
148 void Animator::RemoveAllAnimations()
150 for (auto const& it
: maAnimations
)
154 maAnimations
.clear();
155 mnNextAnimationId
= 0;
157 // No more animations => we do not have to suppress painting
162 bool Animator::ProcessAnimations (const double nTime
)
164 bool bExpired (false);
166 OSL_ASSERT( ! mbIsDisposed
);
170 AnimationList
aCopy (maAnimations
);
171 for (const auto& rxAnimation
: aCopy
)
173 bExpired
|= rxAnimation
->Run(nTime
);
179 void Animator::CleanUpAnimationList()
181 OSL_ASSERT( ! mbIsDisposed
);
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
));
208 IMPL_LINK_NOARG(Animator
, TimeoutHandler
, Timer
*, void)
213 if (ProcessAnimations(maElapsedTime
.getElapsedTime()))
214 CleanUpAnimationList();
216 // Unlock the draw lock. This should lead to a repaint.
219 if (!maAnimations
.empty())
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
)),
235 mnDuration(nDuration
),
236 mnEnd(nGlobalTime
+ nDuration
+ nStartOffset
),
237 mnGlobalTimeAtStart(nGlobalTime
+ nStartOffset
),
243 bool Animator::Animation::Run (const double nGlobalTime
)
249 if (nGlobalTime
>= mnEnd
)
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
);
269 void Animator::Animation::Expire()
279 } // end of namespace ::sd::slidesorter::controller
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */