1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sdext.hxx"
30 
31 #include "PresenterAnimator.hxx"
32 
33 #include "PresenterTimer.hxx"
34 #include <osl/diagnose.h>
35 #include <osl/time.h>
36 #include <vos/timer.hxx>
37 #include <boost/bind.hpp>
38 #include <boost/function.hpp>
39 
40 namespace sdext { namespace presenter {
41 
42 
43 
44 //===== PresenterAnimator =====================================================
45 
46 PresenterAnimator::PresenterAnimator (void)
47     : maFutureAnimations(),
48       maActiveAnimations(),
49       mnCurrentTaskId(0),
50       mnNextTime(0)
51 {
52 }
53 
54 
55 
56 
57 PresenterAnimator::~PresenterAnimator (void)
58 {
59     PresenterTimer::CancelTask(mnCurrentTaskId);
60 }
61 
62 
63 
64 
65 
66 void PresenterAnimator::AddAnimation (const SharedPresenterAnimation& rpAnimation)
67 {
68     ::osl::MutexGuard aGuard (m_aMutex);
69 
70     maFutureAnimations.insert(AnimationList::value_type(rpAnimation->GetStartTime(), rpAnimation));
71     ScheduleNextRun();
72 }
73 
74 
75 
76 
77 void PresenterAnimator::Process (void)
78 {
79     ::osl::MutexGuard aGuard (m_aMutex);
80 
81     mnNextTime = 0;
82 
83     const sal_uInt64 nCurrentTime (GetCurrentTime());
84 
85     ActivateAnimations(nCurrentTime);
86 
87     while ( ! maActiveAnimations.empty())
88     {
89         sal_uInt64 nRequestedTime (maActiveAnimations.begin()->first);
90         SharedPresenterAnimation pAnimation (maActiveAnimations.begin()->second);
91 
92         if (nRequestedTime > nCurrentTime)
93             break;
94 
95         maActiveAnimations.erase(maActiveAnimations.begin());
96 
97         const double nTotalDuration (double(pAnimation->GetEndTime() - pAnimation->GetStartTime()));
98         double nProgress (nTotalDuration > 0 ? (nCurrentTime - pAnimation->GetStartTime()) / nTotalDuration : 1);
99         if (nProgress <= 0)
100             nProgress = 0;
101         else if (nProgress >= 1)
102             nProgress = 1;
103 
104         OSL_TRACE("running animation step at %f (requested was %f) %f\n",
105             nCurrentTime/1e6, nRequestedTime/1e6, nProgress);
106         pAnimation->Run(nProgress, nCurrentTime);
107 
108         if (nCurrentTime < pAnimation->GetEndTime())
109             maActiveAnimations.insert(
110                 AnimationList::value_type(
111                     nCurrentTime + pAnimation->GetStepDuration(),
112                     pAnimation));
113         else
114             pAnimation->RunEndCallbacks();
115     }
116 
117     ScheduleNextRun();
118 }
119 
120 
121 
122 
123 void PresenterAnimator::ActivateAnimations (const sal_uInt64 nCurrentTime)
124 {
125     while ( ! maFutureAnimations.empty()
126         && maFutureAnimations.begin()->first <= nCurrentTime)
127     {
128         SharedPresenterAnimation pAnimation (maFutureAnimations.begin()->second);
129         maActiveAnimations.insert(*maFutureAnimations.begin());
130         maFutureAnimations.erase(maFutureAnimations.begin());
131         pAnimation->RunStartCallbacks();
132     }
133 }
134 
135 
136 
137 
138 void PresenterAnimator::ScheduleNextRun (void)
139 {
140     sal_uInt64 nStartTime (0);
141 
142     if ( ! maActiveAnimations.empty())
143     {
144         nStartTime  = maActiveAnimations.begin()->first;
145         if ( ! maFutureAnimations.empty())
146             if (maFutureAnimations.begin()->first < nStartTime)
147                 nStartTime = maFutureAnimations.begin()->first;
148     }
149     else if ( ! maFutureAnimations.empty())
150         nStartTime = maFutureAnimations.begin()->first;
151 
152     if (nStartTime > 0)
153         ScheduleNextRun(nStartTime);
154 }
155 
156 
157 
158 
159 void PresenterAnimator::ScheduleNextRun (const sal_uInt64 nStartTime)
160 {
161     if (mnNextTime==0 || nStartTime<mnNextTime)
162     {
163         mnNextTime = nStartTime;
164         ::vos::TTimeValue aTimeValue (GetSeconds(mnNextTime), GetNanoSeconds(mnNextTime));
165         PresenterTimer::ScheduleSingleTaskAbsolute (
166             ::boost::bind(&PresenterAnimator::Process, this),
167             aTimeValue);
168     }
169 }
170 
171 } } // end of namespace ::sdext::presenter
172