diff --git a/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp b/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp index d2929f805d..7393f25766 100644 --- a/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp +++ b/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp @@ -27,6 +27,11 @@ class ComponentAnimator::AnimationTask public: AnimationTask (Component* c) noexcept : component (c) {} + ~AnimationTask() + { + masterReference.clear(); + } + void reset (const Rectangle& finalBounds, float finalAlpha, int millisecondsToSpendMoving, @@ -63,14 +68,15 @@ public: bool useTimeslice (const int elapsed) { - if (Component* const c = proxy != nullptr ? static_cast (proxy) - : static_cast (component)) + if (auto* c = proxy != nullptr ? static_cast (proxy) + : static_cast (component)) { msElapsed += elapsed; double newProgress = msElapsed / (double) msTotal; if (newProgress >= 0 && newProgress < 1.0) { + const WeakReference weakRef (this); newProgress = timeToDistance (newProgress); const double delta = (newProgress - lastProgress) / (1.0 - lastProgress); jassert (newProgress >= lastProgress); @@ -99,6 +105,11 @@ public: } } + // Check whether the animation was cancelled/deleted during + // a callback during the setBounds method + if (weakRef.wasObjectDeleted()) + return false; + if (isChangingAlpha) { alpha += (destAlpha - alpha) * delta; @@ -129,9 +140,8 @@ public: } //============================================================================== - class ProxyComponent : public Component + struct ProxyComponent : public Component { - public: ProxyComponent (Component& c) { setWantsKeyboardFocus (false); @@ -140,15 +150,15 @@ public: setAlpha (c.getAlpha()); setInterceptsMouseClicks (false, false); - if (Component* const parent = c.getParentComponent()) + if (auto* parent = c.getParentComponent()) parent->addAndMakeVisible (this); else if (c.isOnDesktop() && c.getPeer() != nullptr) addToDesktop (c.getPeer()->getStyleFlags() | ComponentPeer::windowIgnoresKeyPresses); else jassertfalse; // seem to be trying to animate a component that's not visible.. - const float scale = (float) Desktop::getInstance().getDisplays() - .getDisplayContaining (getScreenBounds().getCentre()).scale; + auto scale = (float) Desktop::getInstance().getDisplays() + .getDisplayContaining (getScreenBounds().getCentre()).scale; image = c.createComponentSnapshot (c.getLocalBounds(), false, scale); @@ -169,6 +179,9 @@ public: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProxyComponent) }; + WeakReference::Master masterReference; + friend class WeakReference; + WeakReference component; ScopedPointer proxy; @@ -187,6 +200,8 @@ private: : 0.5 * (startSpeed + 0.5 * (midSpeed - startSpeed)) + (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed)); } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimationTask) }; //============================================================================== @@ -216,7 +231,7 @@ void ComponentAnimator::animateComponent (Component* const component, if (component != nullptr) { - AnimationTask* at = findTaskFor (component); + auto* at = findTaskFor (component); if (at == nullptr) { @@ -273,7 +288,7 @@ void ComponentAnimator::cancelAllAnimations (const bool moveComponentsToTheirFin void ComponentAnimator::cancelAnimation (Component* const component, const bool moveComponentToItsFinalPosition) { - if (AnimationTask* const at = findTaskFor (component)) + if (auto* at = findTaskFor (component)) { if (moveComponentToItsFinalPosition) at->moveToFinalDestination(); @@ -287,7 +302,7 @@ Rectangle ComponentAnimator::getComponentDestination (Component* const comp { jassert (component != nullptr); - if (AnimationTask* const at = findTaskFor (component)) + if (auto* at = findTaskFor (component)) return at->destination; return component->getBounds(); @@ -305,18 +320,18 @@ bool ComponentAnimator::isAnimating() const noexcept void ComponentAnimator::timerCallback() { - const uint32 timeNow = Time::getMillisecondCounter(); + auto timeNow = Time::getMillisecondCounter(); - if (lastTime == 0 || lastTime == timeNow) + if (lastTime == 0) lastTime = timeNow; - const int elapsed = (int) (timeNow - lastTime); + auto elapsed = (int) (timeNow - lastTime); - for (int i = tasks.size(); --i >= 0;) + for (auto* task : Array (tasks.begin(), tasks.size())) { - if (! tasks.getUnchecked(i)->useTimeslice (elapsed)) + if (tasks.contains (task) && ! task->useTimeslice (elapsed)) { - tasks.remove (i); + tasks.removeObject (task); sendChangeMessage(); } }