FR: ComponentAnimator lambda callbacks


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
    AnimationTask (Component* c, std::function<void()> stopCallback) noexcept  : 
        component (c), 
        stopAnimationCallback( std::move(stopCallback) )
    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);

            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);          
            if( callback ) callback();

    lastTime = timeNow;

    if (tasks.size() == 0)

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.


There are a few places the API could be updated to use newer C++ features now that our set of supported platforms is slowly getting younger. This is one of them! We’ll be doing a tidy up sometime after the next big release.


bump! Any news of this being added to the development tip?


No news sorry. It’s in our backlog but I’m afraid it’s low priority, so estimating when it might get done is very difficult.


@matkatmusic that would be very cool, and I believe that you can speed up things if you provide your changes as a pull request in github: at that point it will probably be only a few code reviews away from being integrated