1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sdext.hxx"
26 
27 #include "PresenterAnimator.hxx"
28 
29 #include "PresenterTimer.hxx"
30 #include <osl/diagnose.h>
31 #include <osl/time.h>
32 #include <vos/timer.hxx>
33 #include <boost/bind.hpp>
34 #include <boost/function.hpp>
35 
36 namespace sdext { namespace presenter {
37 
38 
39 
40 //===== PresenterAnimator =====================================================
41 
PresenterAnimator(void)42 PresenterAnimator::PresenterAnimator (void)
43     : maFutureAnimations(),
44       maActiveAnimations(),
45       mnCurrentTaskId(0),
46       mnNextTime(0)
47 {
48 }
49 
50 
51 
52 
~PresenterAnimator(void)53 PresenterAnimator::~PresenterAnimator (void)
54 {
55     PresenterTimer::CancelTask(mnCurrentTaskId);
56 }
57 
58 
59 
60 
61 
AddAnimation(const SharedPresenterAnimation & rpAnimation)62 void PresenterAnimator::AddAnimation (const SharedPresenterAnimation& rpAnimation)
63 {
64     ::osl::MutexGuard aGuard (m_aMutex);
65 
66     maFutureAnimations.insert(AnimationList::value_type(rpAnimation->GetStartTime(), rpAnimation));
67     ScheduleNextRun();
68 }
69 
70 
71 
72 
Process(void)73 void PresenterAnimator::Process (void)
74 {
75     ::osl::MutexGuard aGuard (m_aMutex);
76 
77     mnNextTime = 0;
78 
79     const sal_uInt64 nCurrentTime (GetCurrentTime());
80 
81     ActivateAnimations(nCurrentTime);
82 
83     while ( ! maActiveAnimations.empty())
84     {
85         sal_uInt64 nRequestedTime (maActiveAnimations.begin()->first);
86         SharedPresenterAnimation pAnimation (maActiveAnimations.begin()->second);
87 
88         if (nRequestedTime > nCurrentTime)
89             break;
90 
91         maActiveAnimations.erase(maActiveAnimations.begin());
92 
93         const double nTotalDuration (double(pAnimation->GetEndTime() - pAnimation->GetStartTime()));
94         double nProgress (nTotalDuration > 0 ? (nCurrentTime - pAnimation->GetStartTime()) / nTotalDuration : 1);
95         if (nProgress <= 0)
96             nProgress = 0;
97         else if (nProgress >= 1)
98             nProgress = 1;
99 
100         OSL_TRACE("running animation step at %f (requested was %f) %f\n",
101             nCurrentTime/1e6, nRequestedTime/1e6, nProgress);
102         pAnimation->Run(nProgress, nCurrentTime);
103 
104         if (nCurrentTime < pAnimation->GetEndTime())
105             maActiveAnimations.insert(
106                 AnimationList::value_type(
107                     nCurrentTime + pAnimation->GetStepDuration(),
108                     pAnimation));
109         else
110             pAnimation->RunEndCallbacks();
111     }
112 
113     ScheduleNextRun();
114 }
115 
116 
117 
118 
ActivateAnimations(const sal_uInt64 nCurrentTime)119 void PresenterAnimator::ActivateAnimations (const sal_uInt64 nCurrentTime)
120 {
121     while ( ! maFutureAnimations.empty()
122         && maFutureAnimations.begin()->first <= nCurrentTime)
123     {
124         SharedPresenterAnimation pAnimation (maFutureAnimations.begin()->second);
125         maActiveAnimations.insert(*maFutureAnimations.begin());
126         maFutureAnimations.erase(maFutureAnimations.begin());
127         pAnimation->RunStartCallbacks();
128     }
129 }
130 
131 
132 
133 
ScheduleNextRun(void)134 void PresenterAnimator::ScheduleNextRun (void)
135 {
136     sal_uInt64 nStartTime (0);
137 
138     if ( ! maActiveAnimations.empty())
139     {
140         nStartTime  = maActiveAnimations.begin()->first;
141         if ( ! maFutureAnimations.empty())
142             if (maFutureAnimations.begin()->first < nStartTime)
143                 nStartTime = maFutureAnimations.begin()->first;
144     }
145     else if ( ! maFutureAnimations.empty())
146         nStartTime = maFutureAnimations.begin()->first;
147 
148     if (nStartTime > 0)
149         ScheduleNextRun(nStartTime);
150 }
151 
152 
153 
154 
ScheduleNextRun(const sal_uInt64 nStartTime)155 void PresenterAnimator::ScheduleNextRun (const sal_uInt64 nStartTime)
156 {
157     if (mnNextTime==0 || nStartTime<mnNextTime)
158     {
159         mnNextTime = nStartTime;
160         ::vos::TTimeValue aTimeValue (GetSeconds(mnNextTime), GetNanoSeconds(mnNextTime));
161         PresenterTimer::ScheduleSingleTaskAbsolute (
162             ::boost::bind(&PresenterAnimator::Process, this),
163             aTimeValue);
164     }
165 }
166 
167 } } // end of namespace ::sdext::presenter
168