diff options
Diffstat (limited to 'sd/source/ui/slidesorter/controller/SlsAnimator.cxx')
-rwxr-xr-x[-rw-r--r--] | sd/source/ui/slidesorter/controller/SlsAnimator.cxx | 299 |
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 |