Right now, ComponentAnimator relies on sendChangeMessage()
to notify listeners when it starts animating, and when it stops animating.
it would be pretty useful if we could attach a lambda callback for each component that is being animated.
the AnimationTask class can just have one member added and initialized in the constructor:
class ComponentAnimator::AnimationTask
{
public:
AnimationTask (Component* c, std::function<void()> stopCallback) noexcept :
component (c),
stopAnimationCallback( std::move(stopCallback) )
{}
//...snip
std::function<void()> stopAnimationCallback;
and for when it starts:
void ComponentAnimator::animateComponent (Component* const component,
const Rectangle<int>& finalBounds,
const float finalAlpha,
const int millisecondsToSpendMoving,
const bool useProxyComponent,
const double startSpeed,
const double endSpeed,
std::function<void()> startAnimationCallback,
std::function<void()> stopAnimationCallback)
{
// the speeds must be 0 or greater!
jassert (startSpeed >= 0 && endSpeed >= 0);
if (component != nullptr)
{
auto* at = findTaskFor (component);
if (at == nullptr)
{
at = new AnimationTask (component, stopAnimationCallback);
tasks.add (at);
sendChangeMessage();
if( startAnimationCallback ) startAnimationCallback();
}
at->reset (finalBounds, finalAlpha, millisecondsToSpendMoving,
useProxyComponent, startSpeed, endSpeed);
if (! isTimerRunning())
{
lastTime = Time::getMillisecondCounter();
startTimerHz (50);
}
}
}
something like this for when it stops being animated:
void ComponentAnimator::timerCallback()
{
auto timeNow = Time::getMillisecondCounter();
if (lastTime == 0)
lastTime = timeNow;
auto elapsed = (int) (timeNow - lastTime);
for (auto* task : Array<AnimationTask*> (tasks.begin(), tasks.size()))
{
if (tasks.contains (task) && ! task->useTimeslice (elapsed))
{
std::function<void()> callback;
if( task->stopAnimationCallback ) callback = task->stopAnimationCallback;
tasks.removeObject (task);
sendChangeMessage();
if( callback ) callback();
}
}
lastTime = timeNow;
if (tasks.size() == 0)
stopTimer();
}
This would be a much cleaner way to do stuff when animations start or end, compared to inheriting from ChangeListener, and checking if the ChangeBroadcaster was the Desktop::getInstance().getAnimator() in the changeListenerCallback.