Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "controller/SlsAnimator.hxx"
30 : : #include "view/SlideSorterView.hxx"
31 : : #include "View.hxx"
32 : : #include <boost/bind.hpp>
33 : :
34 : : namespace sd { namespace slidesorter { namespace controller {
35 : :
36 : : namespace {
37 : : static const sal_Int32 gnResolution = 25;
38 : : }
39 : : /** Handle one animation function by using a timer for frequent calls to
40 : : the animations operator().
41 : : */
42 : : class Animator::Animation
43 : : {
44 : : public:
45 : : Animation (
46 : : const Animator::AnimationFunctor& rAnimation,
47 : : const double nStartOffset,
48 : : const double nDuration,
49 : : const double nGlobalTime,
50 : : const Animator::AnimationId nAnimationId,
51 : : const Animator::FinishFunctor& rFinishFunctor);
52 : : ~Animation (void);
53 : : /** Run next animation step. If animation has reached its end it is
54 : : expired.
55 : : */
56 : : bool Run (const double nGlobalTime);
57 : :
58 : : /** Typically called when an animation has finished, but also from
59 : : Animator::Disposed(). The finish functor is called and the
60 : : animation is marked as expired to prevent another run.
61 : : */
62 : : void Expire (void);
63 : : bool IsExpired (void);
64 : :
65 : : Animator::AnimationFunctor maAnimation;
66 : : Animator::FinishFunctor maFinishFunctor;
67 : : const Animator::AnimationId mnAnimationId;
68 : : const double mnDuration;
69 : : const double mnEnd;
70 : : const double mnGlobalTimeAtStart;
71 : : bool mbIsExpired;
72 : : };
73 : :
74 : :
75 : :
76 : :
77 : 130 : Animator::Animator (SlideSorter& rSlideSorter)
78 : : : mrSlideSorter(rSlideSorter),
79 : : maTimer(),
80 : : mbIsDisposed(false),
81 : : maAnimations(),
82 : : maElapsedTime(),
83 : : mpDrawLock(),
84 [ + - ][ + - ]: 130 : mnNextAnimationId(0)
[ + - ]
85 : : {
86 [ + - ]: 130 : maTimer.SetTimeout(gnResolution);
87 [ + - ]: 130 : maTimer.SetTimeoutHdl(LINK(this,Animator,TimeoutHandler));
88 : 130 : }
89 : :
90 : :
91 : :
92 : :
93 [ + - ][ + - ]: 130 : Animator::~Animator (void)
[ + - ]
94 : : {
95 [ - + ]: 130 : if ( ! mbIsDisposed)
96 : : {
97 : : OSL_ASSERT(mbIsDisposed);
98 [ # # ]: 0 : Dispose();
99 : : }
100 : 130 : }
101 : :
102 : :
103 : :
104 : :
105 : 130 : void Animator::Dispose (void)
106 : : {
107 : 130 : mbIsDisposed = true;
108 : :
109 [ + - ]: 130 : AnimationList aCopy (maAnimations);
110 : 130 : AnimationList::const_iterator iAnimation;
111 [ + - ][ + - ]: 130 : for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
[ - + ]
112 [ # # ]: 0 : (*iAnimation)->Expire();
113 : :
114 [ + - ]: 130 : maTimer.Stop();
115 [ - + ]: 130 : if (mpDrawLock)
116 : : {
117 [ # # ]: 0 : mpDrawLock->Dispose();
118 [ # # ]: 0 : mpDrawLock.reset();
119 : 130 : }
120 : 130 : }
121 : :
122 : :
123 : :
124 : :
125 : 0 : Animator::AnimationId Animator::AddAnimation (
126 : : const AnimationFunctor& rAnimation,
127 : : const sal_Int32 nStartOffset,
128 : : const sal_Int32 nDuration,
129 : : const FinishFunctor& rFinishFunctor)
130 : : {
131 : : // When the animator is already disposed then ignore this call
132 : : // silently (well, we show an assertion, but do not throw an exception.)
133 : : OSL_ASSERT( ! mbIsDisposed);
134 [ # # ]: 0 : if (mbIsDisposed)
135 : 0 : return -1;
136 : :
137 : : boost::shared_ptr<Animation> pAnimation (
138 : : new Animation(
139 : : rAnimation,
140 : : nStartOffset / 1000.0,
141 : : nDuration / 1000.0,
142 : 0 : maElapsedTime.getElapsedTime(),
143 : : ++mnNextAnimationId,
144 [ # # ][ # # ]: 0 : rFinishFunctor));
[ # # ][ # # ]
145 [ # # ]: 0 : maAnimations.push_back(pAnimation);
146 : :
147 [ # # ]: 0 : RequestNextFrame();
148 : :
149 [ # # ]: 0 : return pAnimation->mnAnimationId;
150 : : }
151 : :
152 : :
153 : :
154 : :
155 : 0 : void Animator::RemoveAnimation (const Animator::AnimationId nId)
156 : : {
157 : : OSL_ASSERT( ! mbIsDisposed);
158 : :
159 : : const AnimationList::iterator iAnimation (::std::find_if(
160 : : maAnimations.begin(),
161 : : maAnimations.end(),
162 : : ::boost::bind(
163 : : ::std::equal_to<Animator::AnimationId>(),
164 : : nId,
165 [ # # ][ # # ]: 0 : ::boost::bind(&Animation::mnAnimationId, _1))));
[ # # ]
166 [ # # ][ # # ]: 0 : if (iAnimation != maAnimations.end())
167 : : {
168 : : OSL_ASSERT((*iAnimation)->mnAnimationId == nId);
169 [ # # ]: 0 : (*iAnimation)->Expire();
170 [ # # ]: 0 : maAnimations.erase(iAnimation);
171 : : }
172 : :
173 [ # # ]: 0 : if (maAnimations.empty())
174 : : {
175 : : // Reset the animation id when we can.
176 : 0 : mnNextAnimationId = 0;
177 : :
178 : : // No more animations => we do not have to suppress painting
179 : : // anymore.
180 [ # # ]: 0 : mpDrawLock.reset();
181 : : }
182 : 0 : }
183 : :
184 : :
185 : :
186 : :
187 : 130 : void Animator::RemoveAllAnimations (void)
188 : : {
189 : : ::std::for_each(
190 : : maAnimations.begin(),
191 : : maAnimations.end(),
192 : : ::boost::bind(
193 : : &Animation::Expire,
194 : 130 : _1));
195 : 130 : maAnimations.clear();
196 : 130 : mnNextAnimationId = 0;
197 : :
198 : : // No more animations => we do not have to suppress painting
199 : : // anymore.
200 : 130 : mpDrawLock.reset();
201 : 130 : }
202 : :
203 : :
204 : :
205 : :
206 : 0 : bool Animator::ProcessAnimations (const double nTime)
207 : : {
208 : 0 : bool bExpired (false);
209 : :
210 : : OSL_ASSERT( ! mbIsDisposed);
211 [ # # ]: 0 : if (mbIsDisposed)
212 : 0 : return bExpired;
213 : :
214 : :
215 [ # # ]: 0 : AnimationList aCopy (maAnimations);
216 : 0 : AnimationList::const_iterator iAnimation;
217 [ # # ][ # # ]: 0 : for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
[ # # ]
218 : : {
219 [ # # ]: 0 : bExpired |= (*iAnimation)->Run(nTime);
220 : : }
221 : :
222 : 0 : return bExpired;
223 : : }
224 : :
225 : :
226 : :
227 : :
228 : 0 : void Animator::CleanUpAnimationList (void)
229 : : {
230 : : OSL_ASSERT( ! mbIsDisposed);
231 [ # # ]: 0 : if (mbIsDisposed)
232 : 0 : return;
233 : :
234 [ # # ]: 0 : AnimationList aActiveAnimations;
235 : :
236 : 0 : AnimationList::const_iterator iAnimation;
237 [ # # ][ # # ]: 0 : for (iAnimation=maAnimations.begin(); iAnimation!=maAnimations.end(); ++iAnimation)
[ # # ]
238 : : {
239 [ # # ]: 0 : if ( ! (*iAnimation)->IsExpired())
240 [ # # ]: 0 : aActiveAnimations.push_back(*iAnimation);
241 : : }
242 : :
243 : 0 : maAnimations.swap(aActiveAnimations);
244 : : }
245 : :
246 : :
247 : :
248 : :
249 : 0 : void Animator::RequestNextFrame (const double nFrameStart)
250 : : {
251 : : (void)nFrameStart;
252 [ # # ]: 0 : if ( ! maTimer.IsActive())
253 : : {
254 : : // Prevent redraws except for the ones in TimeoutHandler. While the
255 : : // Animator is active it will schedule repaints regularly. Repaints
256 : : // in between would only lead to visual artifacts.
257 [ # # ]: 0 : mpDrawLock.reset(new view::SlideSorterView::DrawLock(mrSlideSorter));
258 : 0 : maTimer.Start();
259 : : }
260 : 0 : }
261 : :
262 : :
263 : :
264 : :
265 : 0 : IMPL_LINK_NOARG(Animator, TimeoutHandler)
266 : : {
267 [ # # ]: 0 : if (mbIsDisposed)
268 : 0 : return 0;
269 : :
270 [ # # ]: 0 : if (ProcessAnimations(maElapsedTime.getElapsedTime()))
271 : 0 : CleanUpAnimationList();
272 : :
273 : : // Unlock the draw lock. This should lead to a repaint.
274 : 0 : mpDrawLock.reset();
275 : :
276 [ # # ]: 0 : if (!maAnimations.empty())
277 : 0 : RequestNextFrame();
278 : :
279 : 0 : return 0;
280 : : }
281 : :
282 : :
283 : :
284 : :
285 : : //===== Animator::Animation ===================================================
286 : :
287 : 0 : Animator::Animation::Animation (
288 : : const Animator::AnimationFunctor& rAnimation,
289 : : const double nStartOffset,
290 : : const double nDuration,
291 : : const double nGlobalTime,
292 : : const Animator::AnimationId nId,
293 : : const Animator::FinishFunctor& rFinishFunctor)
294 : : : maAnimation(rAnimation),
295 : : maFinishFunctor(rFinishFunctor),
296 : : mnAnimationId(nId),
297 : : mnDuration(nDuration),
298 : : mnEnd(nGlobalTime + nDuration + nStartOffset),
299 : : mnGlobalTimeAtStart(nGlobalTime + nStartOffset),
300 [ # # ]: 0 : mbIsExpired(false)
301 : : {
302 [ # # ]: 0 : Run(nGlobalTime);
303 : 0 : }
304 : :
305 : :
306 : :
307 : :
308 [ # # ]: 0 : Animator::Animation::~Animation (void)
309 : : {
310 : 0 : }
311 : :
312 : :
313 : :
314 : :
315 : 0 : bool Animator::Animation::Run (const double nGlobalTime)
316 : : {
317 [ # # ]: 0 : if ( ! mbIsExpired)
318 : : {
319 [ # # ]: 0 : if (mnDuration > 0)
320 : : {
321 [ # # ]: 0 : if (nGlobalTime >= mnEnd)
322 : : {
323 : 0 : maAnimation(1.0);
324 : 0 : Expire();
325 : : }
326 [ # # ]: 0 : else if (nGlobalTime >= mnGlobalTimeAtStart)
327 : : {
328 : 0 : maAnimation((nGlobalTime - mnGlobalTimeAtStart) / mnDuration);
329 : : }
330 : : }
331 [ # # ]: 0 : else if (mnDuration < 0)
332 : : {
333 : : // Animations without end have to be expired by their owner.
334 : 0 : maAnimation(nGlobalTime);
335 : : }
336 : : }
337 : :
338 : 0 : return mbIsExpired;
339 : : }
340 : :
341 : :
342 : :
343 : :
344 : 0 : void Animator::Animation::Expire (void)
345 : : {
346 [ # # ]: 0 : if ( ! mbIsExpired)
347 : : {
348 : 0 : mbIsExpired = true;
349 [ # # ]: 0 : if (maFinishFunctor)
350 : 0 : maFinishFunctor();
351 : : }
352 : 0 : }
353 : :
354 : :
355 : :
356 : :
357 : 0 : bool Animator::Animation::IsExpired (void)
358 : : {
359 : 0 : return mbIsExpired;
360 : : }
361 : :
362 : :
363 : :
364 : :
365 [ + - ][ + - ]: 75 : } } } // end of namespace ::sd::slidesorter::controller
366 : :
367 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|