| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2015 - ROLI Ltd.
 - 
 -    Permission is granted to use this software under the terms of either:
 -    a) the GPL v2 (or any later version)
 -    b) the Affero GPL v3
 - 
 -    Details of these licenses can be found 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.juce.com for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - class DropShadower::ShadowWindow  : public Component
 - {
 - public:
 -     ShadowWindow (Component* comp, const DropShadow& ds)
 -         : target (comp), shadow (ds)
 -     {
 -         setVisible (true);
 -         setInterceptsMouseClicks (false, false);
 - 
 -         if (comp->isOnDesktop())
 -         {
 -             setSize (1, 1); // to keep the OS happy by not having zero-size windows
 -             addToDesktop (ComponentPeer::windowIgnoresMouseClicks
 -                             | ComponentPeer::windowIsTemporary
 -                             | ComponentPeer::windowIgnoresKeyPresses);
 -         }
 -         else if (Component* const parent = comp->getParentComponent())
 -         {
 -             parent->addChildComponent (this);
 -         }
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         if (Component* c = target)
 -             shadow.drawForRectangle (g, getLocalArea (c, c->getLocalBounds()));
 -     }
 - 
 -     void resized() override
 -     {
 -         repaint();  // (needed for correct repainting)
 -     }
 - 
 -     float getDesktopScaleFactor() const override
 -     {
 -         if (target != nullptr)
 -             return target->getDesktopScaleFactor();
 - 
 -         return Component::getDesktopScaleFactor();
 -     }
 - 
 - private:
 -     WeakReference<Component> target;
 -     DropShadow shadow;
 - 
 -     JUCE_DECLARE_NON_COPYABLE (ShadowWindow)
 - };
 - 
 - 
 - //==============================================================================
 - DropShadower::DropShadower (const DropShadow& ds)
 -    : owner (nullptr), shadow (ds), reentrant (false)
 - {
 - }
 - 
 - DropShadower::~DropShadower()
 - {
 -     if (owner != nullptr)
 -     {
 -         owner->removeComponentListener (this);
 -         owner = nullptr;
 -     }
 - 
 -     updateParent();
 - 
 -     reentrant = true;
 -     shadowWindows.clear();
 - }
 - 
 - void DropShadower::setOwner (Component* componentToFollow)
 - {
 -     if (componentToFollow != owner)
 -     {
 -         if (owner != nullptr)
 -             owner->removeComponentListener (this);
 - 
 -         // (the component can't be null)
 -         jassert (componentToFollow != nullptr);
 - 
 -         owner = componentToFollow;
 -         jassert (owner != nullptr);
 - 
 -         updateParent();
 -         owner->addComponentListener (this);
 - 
 -         updateShadows();
 -     }
 - }
 - 
 - void DropShadower::updateParent()
 - {
 -     if (Component* p = lastParentComp)
 -         p->removeComponentListener (this);
 - 
 -     lastParentComp = owner != nullptr ? owner->getParentComponent() : nullptr;
 - 
 -     if (Component* p = lastParentComp)
 -         p->addComponentListener (this);
 - }
 - 
 - void DropShadower::componentMovedOrResized (Component& c, bool /*wasMoved*/, bool /*wasResized*/)
 - {
 -     if (owner == &c)
 -         updateShadows();
 - }
 - 
 - void DropShadower::componentBroughtToFront (Component& c)
 - {
 -     if (owner == &c)
 -         updateShadows();
 - }
 - 
 - void DropShadower::componentChildrenChanged (Component&)
 - {
 -     updateShadows();
 - }
 - 
 - void DropShadower::componentParentHierarchyChanged (Component& c)
 - {
 -     if (owner == &c)
 -     {
 -         updateParent();
 -         updateShadows();
 -     }
 - }
 - 
 - void DropShadower::componentVisibilityChanged (Component& c)
 - {
 -     if (owner == &c)
 -         updateShadows();
 - }
 - 
 - void DropShadower::updateShadows()
 - {
 -     if (reentrant)
 -         return;
 - 
 -     const ScopedValueSetter<bool> setter (reentrant, true, false);
 - 
 -     if (owner == nullptr)
 -     {
 -         shadowWindows.clear();
 -         return;
 -     }
 - 
 -     if (owner->isShowing()
 -          && owner->getWidth() > 0 && owner->getHeight() > 0
 -          && (Desktop::canUseSemiTransparentWindows() || owner->getParentComponent() != nullptr))
 -     {
 -         while (shadowWindows.size() < 4)
 -             shadowWindows.add (new ShadowWindow (owner, shadow));
 - 
 -         const int shadowEdge = jmax (shadow.offset.x, shadow.offset.y) + shadow.radius;
 -         const int x = owner->getX();
 -         const int y = owner->getY() - shadowEdge;
 -         const int w = owner->getWidth();
 -         const int h = owner->getHeight() + shadowEdge + shadowEdge;
 - 
 -         for (int i = 4; --i >= 0;)
 -         {
 -             // there seem to be rare situations where the dropshadower may be deleted by
 -             // callbacks during this loop, so use a weak ref to watch out for this..
 -             WeakReference<Component> sw (shadowWindows[i]);
 - 
 -             if (sw != nullptr)
 -                 sw->setAlwaysOnTop (owner->isAlwaysOnTop());
 - 
 -             if (sw != nullptr)
 -             {
 -                 switch (i)
 -                 {
 -                     case 0: sw->setBounds (x - shadowEdge, y, shadowEdge, h); break;
 -                     case 1: sw->setBounds (x + w, y, shadowEdge, h); break;
 -                     case 2: sw->setBounds (x, y, w, shadowEdge); break;
 -                     case 3: sw->setBounds (x, owner->getBottom(), w, shadowEdge); break;
 -                     default: break;
 -                 }
 -             }
 - 
 -             if (sw != nullptr)
 -                 sw->toBehind (i == 3 ? owner : shadowWindows.getUnchecked (i + 1));
 - 
 -             if (sw == nullptr)
 -                 return;
 -         }
 -     }
 -     else
 -     {
 -         shadowWindows.clear();
 -     }
 - }
 
 
  |