|
- /*
- ==============================================================================
-
- This file is part of the JUCE library - "Jules' Utility Class Extensions"
- Copyright 2004-9 by Raw Material Software Ltd.
-
- ------------------------------------------------------------------------------
-
- JUCE can be redistributed and/or modified under the terms of the GNU General
- Public License (Version 2), as published by the Free Software Foundation.
- A copy of the license is included in the JUCE distribution, or can be found
- online at www.gnu.org/licenses.
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.rawmaterialsoftware.com/juce for more information.
-
- ==============================================================================
- */
-
- #include "../../../core/juce_StandardHeader.h"
-
- BEGIN_JUCE_NAMESPACE
-
- #include "juce_ComponentAnimator.h"
- #include "../../../core/juce_Time.h"
-
-
- //==============================================================================
- class ComponentAnimator::AnimationTask
- {
- public:
- AnimationTask (Component* const comp)
- : component (comp)
- {
- }
-
- Component::SafePointer<Component> component;
- Rectangle<int> destination;
- int msElapsed, msTotal;
- double startSpeed, midSpeed, endSpeed, lastProgress;
- double left, top, right, bottom;
-
- bool useTimeslice (const int elapsed)
- {
- if (component == 0)
- return false;
-
- msElapsed += elapsed;
- double newProgress = msElapsed / (double) msTotal;
-
- if (newProgress >= 0 && newProgress < 1.0)
- {
- newProgress = timeToDistance (newProgress);
- const double delta = (newProgress - lastProgress) / (1.0 - lastProgress);
- jassert (newProgress >= lastProgress);
- lastProgress = newProgress;
-
- left += (destination.getX() - left) * delta;
- top += (destination.getY() - top) * delta;
- right += (destination.getRight() - right) * delta;
- bottom += (destination.getBottom() - bottom) * delta;
-
- if (delta < 1.0)
- {
- const Rectangle<int> newBounds (roundToInt (left),
- roundToInt (top),
- roundToInt (right - left),
- roundToInt (bottom - top));
-
- if (newBounds != destination)
- {
- component->setBounds (newBounds);
- return true;
- }
- }
- }
-
- component->setBounds (destination);
- return false;
- }
-
- void moveToFinalDestination()
- {
- if (component != 0)
- component->setBounds (destination);
- }
-
- private:
- inline double timeToDistance (const double time) const
- {
- return (time < 0.5) ? time * (startSpeed + time * (midSpeed - startSpeed))
- : 0.5 * (startSpeed + 0.5 * (midSpeed - startSpeed))
- + (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed));
- }
- };
-
- //==============================================================================
- ComponentAnimator::ComponentAnimator()
- : lastTime (0)
- {
- }
-
- ComponentAnimator::~ComponentAnimator()
- {
- cancelAllAnimations (false);
- jassert (tasks.size() == 0);
- }
-
- //==============================================================================
- ComponentAnimator::AnimationTask* ComponentAnimator::findTaskFor (Component* const component) const
- {
- for (int i = tasks.size(); --i >= 0;)
- if (component == tasks.getUnchecked(i)->component.getComponent())
- return tasks.getUnchecked(i);
-
- return 0;
- }
-
- void ComponentAnimator::animateComponent (Component* const component,
- const Rectangle<int>& finalPosition,
- const int millisecondsToSpendMoving,
- const double startSpeed,
- const double endSpeed)
- {
- if (component != 0)
- {
- AnimationTask* at = findTaskFor (component);
-
- if (at == 0)
- {
- at = new AnimationTask (component);
- tasks.add (at);
- sendChangeMessage (this);
- }
-
- at->msElapsed = 0;
- at->lastProgress = 0;
- at->msTotal = jmax (1, millisecondsToSpendMoving);
- at->destination = finalPosition;
-
- // the speeds must be 0 or greater!
- jassert (startSpeed >= 0 && endSpeed >= 0)
-
- const double invTotalDistance = 4.0 / (startSpeed + endSpeed + 2.0);
- at->startSpeed = jmax (0.0, startSpeed * invTotalDistance);
- at->midSpeed = invTotalDistance;
- at->endSpeed = jmax (0.0, endSpeed * invTotalDistance);
-
- at->left = component->getX();
- at->top = component->getY();
- at->right = component->getRight();
- at->bottom = component->getBottom();
-
- if (! isTimerRunning())
- {
- lastTime = Time::getMillisecondCounter();
- startTimer (1000 / 50);
- }
- }
- }
-
- void ComponentAnimator::cancelAllAnimations (const bool moveComponentsToTheirFinalPositions)
- {
- for (int i = tasks.size(); --i >= 0;)
- {
- AnimationTask* const at = tasks.getUnchecked(i);
-
- if (moveComponentsToTheirFinalPositions)
- at->moveToFinalDestination();
-
- delete at;
- tasks.remove (i);
- sendChangeMessage (this);
- }
- }
-
- void ComponentAnimator::cancelAnimation (Component* const component,
- const bool moveComponentToItsFinalPosition)
- {
- AnimationTask* const at = findTaskFor (component);
-
- if (at != 0)
- {
- if (moveComponentToItsFinalPosition)
- at->moveToFinalDestination();
-
- tasks.removeValue (at);
- delete at;
- sendChangeMessage (this);
- }
- }
-
- const Rectangle<int> ComponentAnimator::getComponentDestination (Component* const component)
- {
- AnimationTask* const at = findTaskFor (component);
-
- if (at != 0)
- return at->destination;
- else if (component != 0)
- return component->getBounds();
-
- return Rectangle<int>();
- }
-
- bool ComponentAnimator::isAnimating (Component* component) const
- {
- return findTaskFor (component) != 0;
- }
-
- void ComponentAnimator::timerCallback()
- {
- const uint32 timeNow = Time::getMillisecondCounter();
-
- if (lastTime == 0 || lastTime == timeNow)
- lastTime = timeNow;
-
- const int elapsed = timeNow - lastTime;
-
- for (int i = tasks.size(); --i >= 0;)
- {
- AnimationTask* const at = tasks.getUnchecked(i);
-
- if (! at->useTimeslice (elapsed))
- {
- tasks.remove (i);
- delete at;
- sendChangeMessage (this);
- }
- }
-
- lastTime = timeNow;
-
- if (tasks.size() == 0)
- stopTimer();
- }
-
-
- END_JUCE_NAMESPACE
|