summaryrefslogtreecommitdiff
path: root/sd/source/ui/slidesorter/controller/SlsAnimator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/controller/SlsAnimator.cxx')
-rwxr-xr-x[-rw-r--r--]sd/source/ui/slidesorter/controller/SlsAnimator.cxx299
1 files changed, 231 insertions, 68 deletions
diff --git a/sd/source/ui/slidesorter/controller/SlsAnimator.cxx b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx
index 56505d9756e6..28756b3766d9 100644..100755
--- a/sd/source/ui/slidesorter/controller/SlsAnimator.cxx
+++ b/sd/source/ui/slidesorter/controller/SlsAnimator.cxx
@@ -29,6 +29,7 @@
#include "controller/SlsAnimator.hxx"
#include "view/SlideSorterView.hxx"
#include "View.hxx"
+#include <boost/bind.hpp>
namespace sd { namespace slidesorter { namespace controller {
@@ -42,27 +43,32 @@ class Animator::Animation
{
public:
Animation (
- const Animator::AnimationFunction& rAnimation,
- const double nDelta);
+ const Animator::AnimationFunctor& rAnimation,
+ const double nStartOffset,
+ const double nDuration,
+ const double nGlobalTime,
+ const Animator::AnimationId nAnimationId,
+ const Animator::FinishFunctor& rFinishFunctor);
~Animation (void);
- bool Run (void);
+ /** Run next animation step. If animation has reached its end it is
+ expired.
+ */
+ bool Run (const double nGlobalTime);
+
+ /** Typically called when an animation has finished, but also from
+ Animator::Disposed(). The finish functor is called and the
+ animation is marked as expired to prevent another run.
+ */
+ void Expire (void);
bool IsExpired (void);
- Animator::AnimationFunction maAnimation;
- double mnValue;
- double mnDelta;
-};
-
-
-
-
-class Animator::DrawLock
-{
-public:
- DrawLock (View& rView);
- ~DrawLock (void);
-private:
- View& mrView;
+ Animator::AnimationFunctor maAnimation;
+ Animator::FinishFunctor maFinishFunctor;
+ const Animator::AnimationId mnAnimationId;
+ const double mnDuration;
+ const double mnEnd;
+ const double mnGlobalTimeAtStart;
+ bool mbIsExpired;
};
@@ -71,8 +77,11 @@ private:
Animator::Animator (SlideSorter& rSlideSorter)
: mrSlideSorter(rSlideSorter),
maTimer(),
+ mbIsDisposed(false),
maAnimations(),
- mpDrawLock()
+ maElapsedTime(),
+ mpDrawLock(),
+ mnNextAnimationId(0)
{
maTimer.SetTimeout(gnResolution);
maTimer.SetTimeoutHdl(LINK(this,Animator,TimeoutHandler));
@@ -83,39 +92,161 @@ Animator::Animator (SlideSorter& rSlideSorter)
Animator::~Animator (void)
{
+ if ( ! mbIsDisposed)
+ {
+ OSL_ASSERT(mbIsDisposed);
+ Dispose();
+ }
+}
+
+
+
+
+void Animator::Dispose (void)
+{
+ mbIsDisposed = true;
+
+ AnimationList aCopy (maAnimations);
+ AnimationList::const_iterator iAnimation;
+ for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
+ (*iAnimation)->Expire();
+
maTimer.Stop();
- mpDrawLock.reset();
+ if (mpDrawLock)
+ {
+ mpDrawLock->Dispose();
+ mpDrawLock.reset();
+ }
}
-void Animator::AddAnimation (
- const AnimationFunction& rAnimation,
- const sal_Int32 nDuration)
+Animator::AnimationId Animator::AddAnimation (
+ const AnimationFunctor& rAnimation,
+ const sal_Int32 nStartOffset,
+ const sal_Int32 nDuration,
+ const FinishFunctor& rFinishFunctor)
{
- const double nDelta = double(gnResolution) / double(nDuration);
- maAnimations.push_back(boost::shared_ptr<Animation>(new Animation(rAnimation, nDelta)));
+ // When the animator is already disposed then ignore this call
+ // silently (well, we show an assertion, but do not throw an exception.)
+ OSL_ASSERT( ! mbIsDisposed);
+ if (mbIsDisposed)
+ return -1;
+
+ boost::shared_ptr<Animation> pAnimation (
+ new Animation(
+ rAnimation,
+ nStartOffset / 1000.0,
+ nDuration / 1000.0,
+ maElapsedTime.getElapsedTime(),
+ ++mnNextAnimationId,
+ rFinishFunctor));
+ maAnimations.push_back(pAnimation);
+
+ RequestNextFrame();
+
+ return pAnimation->mnAnimationId;
+}
+
- // Prevent redraws except for the ones in TimeoutHandler.
- // While the Animator is active it will schedule repaints regularly.
- // Repaints in between would only lead to visual artifacts.
- mpDrawLock.reset(new DrawLock(mrSlideSorter.GetView()));
- maTimer.Start();
+
+
+Animator::AnimationId Animator::AddInfiniteAnimation (
+ const AnimationFunctor& rAnimation,
+ const double nDelta)
+{
+ (void)nDelta;
+
+ // When the animator is already disposed then ignore this call
+ // silently (well, we show an assertion, but do not throw an exception.)
+ OSL_ASSERT( ! mbIsDisposed);
+ if (mbIsDisposed)
+ return -1;
+
+ boost::shared_ptr<Animation> pAnimation (
+ new Animation(
+ rAnimation,
+ 0,
+ -1,
+ maElapsedTime.getElapsedTime(),
+ mnNextAnimationId++,
+ FinishFunctor()));
+ maAnimations.push_back(pAnimation);
+
+ RequestNextFrame();
+
+ return pAnimation->mnAnimationId;
}
-bool Animator::ServeAnimations (void)
+void Animator::RemoveAnimation (const Animator::AnimationId nId)
+{
+ OSL_ASSERT( ! mbIsDisposed);
+
+ const AnimationList::iterator iAnimation (::std::find_if(
+ maAnimations.begin(),
+ maAnimations.end(),
+ ::boost::bind(
+ ::std::equal_to<Animator::AnimationId>(),
+ nId,
+ ::boost::bind(&Animation::mnAnimationId, _1))));
+ if (iAnimation != maAnimations.end())
+ {
+ OSL_ASSERT((*iAnimation)->mnAnimationId == nId);
+ (*iAnimation)->Expire();
+ maAnimations.erase(iAnimation);
+ }
+
+ if (maAnimations.empty())
+ {
+ // Reset the animation id when we can.
+ mnNextAnimationId = 0;
+
+ // No more animations => we do not have to suppress painting
+ // anymore.
+ mpDrawLock.reset();
+ }
+}
+
+
+
+
+void Animator::RemoveAllAnimations (void)
+{
+ ::std::for_each(
+ maAnimations.begin(),
+ maAnimations.end(),
+ ::boost::bind(
+ &Animation::Expire,
+ _1));
+ maAnimations.clear();
+ mnNextAnimationId = 0;
+
+ // No more animations => we do not have to suppress painting
+ // anymore.
+ mpDrawLock.reset();
+}
+
+
+
+
+bool Animator::ProcessAnimations (const double nTime)
{
bool bExpired (false);
+ OSL_ASSERT( ! mbIsDisposed);
+ if (mbIsDisposed)
+ return bExpired;
+
+
AnimationList aCopy (maAnimations);
AnimationList::const_iterator iAnimation;
for (iAnimation=aCopy.begin(); iAnimation!=aCopy.end(); ++iAnimation)
{
- bExpired |= (*iAnimation)->Run();
+ bExpired |= (*iAnimation)->Run(nTime);
}
return bExpired;
@@ -126,6 +257,10 @@ bool Animator::ServeAnimations (void)
void Animator::CleanUpAnimationList (void)
{
+ OSL_ASSERT( ! mbIsDisposed);
+ if (mbIsDisposed)
+ return;
+
AnimationList aActiveAnimations;
AnimationList::const_iterator iAnimation;
@@ -141,19 +276,35 @@ void Animator::CleanUpAnimationList (void)
+void Animator::RequestNextFrame (const double nFrameStart)
+{
+ (void)nFrameStart;
+ if ( ! maTimer.IsActive())
+ {
+ // Prevent redraws except for the ones in TimeoutHandler. While the
+ // Animator is active it will schedule repaints regularly. Repaints
+ // in between would only lead to visual artifacts.
+ mpDrawLock.reset(new view::SlideSorterView::DrawLock(mrSlideSorter));
+ maTimer.Start();
+ }
+}
+
+
+
+
IMPL_LINK(Animator, TimeoutHandler, Timer*, EMPTYARG)
{
- if (ServeAnimations())
+ if (mbIsDisposed)
+ return 0;
+
+ if (ProcessAnimations(maElapsedTime.getElapsedTime()))
CleanUpAnimationList();
// Unlock the draw lock. This should lead to a repaint.
mpDrawLock.reset();
if (maAnimations.size() > 0)
- {
- mpDrawLock.reset(new DrawLock(mrSlideSorter.GetView()));
- maTimer.Start();
- }
+ RequestNextFrame();
return 0;
}
@@ -164,16 +315,21 @@ IMPL_LINK(Animator, TimeoutHandler, Timer*, EMPTYARG)
//===== Animator::Animation ===================================================
Animator::Animation::Animation (
- const Animator::AnimationFunction& rAnimation,
- const double nDelta)
+ const Animator::AnimationFunctor& rAnimation,
+ const double nStartOffset,
+ const double nDuration,
+ const double nGlobalTime,
+ const Animator::AnimationId nId,
+ const Animator::FinishFunctor& rFinishFunctor)
: maAnimation(rAnimation),
- mnValue(0),
- mnDelta(nDelta)
+ maFinishFunctor(rFinishFunctor),
+ mnAnimationId(nId),
+ mnDuration(nDuration),
+ mnEnd(nGlobalTime + nDuration + nStartOffset),
+ mnGlobalTimeAtStart(nGlobalTime + nStartOffset),
+ mbIsExpired(false)
{
-
- maAnimation(mnValue);
- mnValue = mnDelta;
-
+ Run(nGlobalTime);
}
@@ -186,47 +342,54 @@ Animator::Animation::~Animation (void)
-bool Animator::Animation::Run (void)
+bool Animator::Animation::Run (const double nGlobalTime)
{
- if (mnValue < 1.0)
+ if ( ! mbIsExpired)
{
- maAnimation(mnValue);
- mnValue += mnDelta;
- return false;
- }
- else
- {
- maAnimation(1.0);
- return true;
+ if (mnDuration > 0)
+ {
+ if (nGlobalTime >= mnEnd)
+ {
+ maAnimation(1.0);
+ Expire();
+ }
+ else if (nGlobalTime >= mnGlobalTimeAtStart)
+ {
+ maAnimation((nGlobalTime - mnGlobalTimeAtStart) / mnDuration);
+ }
+ }
+ else if (mnDuration < 0)
+ {
+ // Animations without end have to be expired by their owner.
+ maAnimation(nGlobalTime);
+ }
}
+
+ return mbIsExpired;
}
-bool Animator::Animation::IsExpired (void)
+void Animator::Animation::Expire (void)
{
- return mnValue >= 1.0;
+ if ( ! mbIsExpired)
+ {
+ mbIsExpired = true;
+ if (maFinishFunctor)
+ maFinishFunctor();
+ }
}
-//===== Animator::DrawLock ====================================================
-
-Animator::DrawLock::DrawLock (View& rView)
- : mrView(rView)
+bool Animator::Animation::IsExpired (void)
{
- mrView.LockRedraw(TRUE);
+ return mbIsExpired;
}
-Animator::DrawLock::~DrawLock (void)
-{
- mrView.LockRedraw(FALSE);
-}
-
-
} } } // end of namespace ::sd::slidesorter::controller