mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Add FocusOutline class for indicating Component keyboard focus
This commit is contained in:
parent
0e24c9557e
commit
461192b355
14 changed files with 416 additions and 32 deletions
|
|
@ -190,10 +190,13 @@ private:
|
|||
ButtonsComponent()
|
||||
{
|
||||
addAndMakeVisible (radioButtons);
|
||||
|
||||
textButton.setHasFocusOutline (true);
|
||||
addAndMakeVisible (textButton);
|
||||
|
||||
shapeButton.setShape (getJUCELogoPath(), false, true, false);
|
||||
shapeButton.onClick = [] { AlertWindow::showMessageBoxAsync (MessageBoxIconType::InfoIcon, "Alert", "This is an AlertWindow"); };
|
||||
shapeButton.setHasFocusOutline (true);
|
||||
addAndMakeVisible (shapeButton);
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +220,7 @@ private:
|
|||
{
|
||||
b.setRadioGroupId (1);
|
||||
b.setButtonText ("Button " + String (index++));
|
||||
b.setHasFocusOutline (true);
|
||||
addAndMakeVisible (b);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1475,6 +1475,23 @@ public:
|
|||
*/
|
||||
virtual std::unique_ptr<ComponentTraverser> createKeyboardFocusTraverser();
|
||||
|
||||
/** Use this to indicate that the component should have an outline drawn around it
|
||||
when it has keyboard focus.
|
||||
|
||||
If this is set to true, then when the component gains keyboard focus the
|
||||
LookAndFeel::createFocusOutlineForComponent() method will be used to draw an outline
|
||||
around it.
|
||||
|
||||
@see FocusOutline, hasFocusOutline
|
||||
*/
|
||||
void setHasFocusOutline (bool hasFocusOutline) noexcept { flags.hasFocusOutlineFlag = hasFocusOutline; }
|
||||
|
||||
/** Returns true if this component should have a focus outline.
|
||||
|
||||
@see FocusOutline, setHasFocusOutline
|
||||
*/
|
||||
bool hasFocusOutline() const noexcept { return flags.hasFocusOutlineFlag; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the component (and all its parents) are enabled.
|
||||
|
||||
|
|
@ -2548,6 +2565,7 @@ private:
|
|||
bool isKeyboardFocusContainerFlag : 1;
|
||||
bool childKeyboardFocusedFlag : 1;
|
||||
bool dontFocusOnMouseClickFlag : 1;
|
||||
bool hasFocusOutlineFlag : 1;
|
||||
bool alwaysOnTopFlag : 1;
|
||||
bool bufferToImageFlag : 1;
|
||||
bool bringToFrontOnClickFlag : 1;
|
||||
|
|
|
|||
|
|
@ -189,6 +189,24 @@ void Desktop::addFocusChangeListener (FocusChangeListener* l) { focusListen
|
|||
void Desktop::removeFocusChangeListener (FocusChangeListener* l) { focusListeners.remove (l); }
|
||||
void Desktop::triggerFocusCallback() { triggerAsyncUpdate(); }
|
||||
|
||||
void Desktop::updateFocusOutline()
|
||||
{
|
||||
if (auto* currentFocus = Component::getCurrentlyFocusedComponent())
|
||||
{
|
||||
if (currentFocus->hasFocusOutline())
|
||||
{
|
||||
focusOutline = currentFocus->getLookAndFeel().createFocusOutlineForComponent (*currentFocus);
|
||||
|
||||
if (focusOutline != nullptr)
|
||||
focusOutline->setOwner (currentFocus);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
focusOutline = nullptr;
|
||||
}
|
||||
|
||||
void Desktop::handleAsyncUpdate()
|
||||
{
|
||||
// The component may be deleted during this operation, but we'll use a SafePointer rather than a
|
||||
|
|
@ -197,6 +215,8 @@ void Desktop::handleAsyncUpdate()
|
|||
{
|
||||
l.globalFocusChanged (currentFocus.get());
|
||||
});
|
||||
|
||||
updateFocusOutline();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -436,6 +436,8 @@ private:
|
|||
std::unique_ptr<LookAndFeel> defaultLookAndFeel;
|
||||
WeakReference<LookAndFeel> currentLookAndFeel;
|
||||
|
||||
std::unique_ptr<FocusOutline> focusOutline;
|
||||
|
||||
Component* kioskModeComponent = nullptr;
|
||||
Rectangle<int> kioskComponentOriginalBounds;
|
||||
bool kioskModeReentrant = false;
|
||||
|
|
@ -458,6 +460,7 @@ private:
|
|||
void setKioskComponent (Component*, bool shouldBeEnabled, bool allowMenusAndBars);
|
||||
|
||||
void triggerFocusCallback();
|
||||
void updateFocusOutline();
|
||||
void handleAsyncUpdate() override;
|
||||
|
||||
static Point<float> getMousePositionFloat();
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ namespace juce
|
|||
#include "application/juce_Application.cpp"
|
||||
#include "misc/juce_BubbleComponent.cpp"
|
||||
#include "misc/juce_DropShadower.cpp"
|
||||
#include "misc/juce_FocusOutline.cpp"
|
||||
#include "misc/juce_JUCESplashScreen.cpp"
|
||||
|
||||
#include "layout/juce_FlexBox.cpp"
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ namespace juce
|
|||
|
||||
class FlexBox;
|
||||
class Grid;
|
||||
class FocusOutline;
|
||||
|
||||
#if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX
|
||||
Image createSnapshotOfNativeWindow (void* nativeWindowHandle);
|
||||
|
|
@ -259,6 +260,7 @@ namespace juce
|
|||
#include "menus/juce_BurgerMenuComponent.h"
|
||||
#include "buttons/juce_ToolbarButton.h"
|
||||
#include "misc/juce_DropShadower.h"
|
||||
#include "misc/juce_FocusOutline.h"
|
||||
#include "misc/juce_JUCESplashScreen.h"
|
||||
#include "widgets/juce_TreeView.h"
|
||||
#include "windows/juce_TopLevelWindow.h"
|
||||
|
|
|
|||
|
|
@ -153,7 +153,9 @@ public:
|
|||
Colour findColour (int colourId) const noexcept;
|
||||
|
||||
/** Registers a colour to be used for a particular purpose.
|
||||
|
||||
For more details, see the comments for findColour().
|
||||
|
||||
@see findColour, Component::findColour, Component::setColour
|
||||
*/
|
||||
void setColour (int colourId, Colour colour) noexcept;
|
||||
|
|
@ -165,22 +167,27 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** Returns the typeface that should be used for a given font.
|
||||
|
||||
The default implementation just does what you'd expect it to, but you can override
|
||||
this if you want to intercept fonts and use your own custom typeface object.
|
||||
|
||||
@see setDefaultTypeface
|
||||
*/
|
||||
virtual Typeface::Ptr getTypefaceForFont (const Font&);
|
||||
|
||||
/** Allows you to supply a default typeface that will be returned as the default
|
||||
sans-serif font.
|
||||
|
||||
Instead of a typeface object, you can specify a typeface by name using the
|
||||
setDefaultSansSerifTypefaceName() method.
|
||||
|
||||
You can perform more complex typeface substitutions by overloading
|
||||
getTypefaceForFont() but this lets you easily set a global typeface.
|
||||
*/
|
||||
void setDefaultSansSerifTypeface (Typeface::Ptr newDefaultTypeface);
|
||||
|
||||
/** Allows you to change the default sans-serif font.
|
||||
|
||||
If you need to supply your own Typeface object for any of the default fonts, rather
|
||||
than just supplying the name (e.g. if you want to use an embedded font), then
|
||||
you can instead call setDefaultSansSerifTypeface() with an object to use.
|
||||
|
|
@ -188,39 +195,64 @@ public:
|
|||
void setDefaultSansSerifTypefaceName (const String& newName);
|
||||
|
||||
//==============================================================================
|
||||
/** Override this to get the chance to swap a component's mouse cursor for a
|
||||
customised one.
|
||||
/** Sets whether native alert windows (if available) or standard JUCE AlertWindows
|
||||
drawn with AlertWindow::LookAndFeelMethods will be used.
|
||||
|
||||
@see isUsingNativeAlertWindows
|
||||
*/
|
||||
virtual MouseCursor getMouseCursorFor (Component&);
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a new graphics context object. */
|
||||
virtual std::unique_ptr<LowLevelGraphicsContext> createGraphicsContext (const Image& imageToRenderOn,
|
||||
Point<int> origin,
|
||||
const RectangleList<int>& initialClip);
|
||||
|
||||
void setUsingNativeAlertWindows (bool shouldUseNativeAlerts);
|
||||
|
||||
/** Returns true if native alert windows will be used (if available).
|
||||
|
||||
The default setting for this is false.
|
||||
|
||||
@see setUsingNativeAlertWindows
|
||||
*/
|
||||
bool isUsingNativeAlertWindows();
|
||||
|
||||
//==============================================================================
|
||||
/** Draws a small image that spins to indicate that something's happening.
|
||||
|
||||
This method should use the current time to animate itself, so just keep
|
||||
repainting it every so often.
|
||||
*/
|
||||
virtual void drawSpinningWaitAnimation (Graphics&, const Colour& colour,
|
||||
int x, int y, int w, int h) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a tick shape for use in yes/no boxes, etc. */
|
||||
virtual Path getTickShape (float height) = 0;
|
||||
|
||||
/** Returns a cross shape for use in yes/no boxes, etc. */
|
||||
virtual Path getCrossShape (float height) = 0;
|
||||
|
||||
//==============================================================================
|
||||
virtual DropShadower* createDropShadowerForComponent (Component*) = 0;
|
||||
/** Creates a drop-shadower for a given component, if required.
|
||||
|
||||
@see DropShadower
|
||||
*/
|
||||
virtual std::unique_ptr<DropShadower> createDropShadowerForComponent (Component&) = 0;
|
||||
|
||||
/** Creates a focus outline for a given component, if required.
|
||||
|
||||
@see FocusOutline
|
||||
*/
|
||||
virtual std::unique_ptr<FocusOutline> createFocusOutlineForComponent (Component&) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Plays the system's default 'beep' noise, to alert the user about something very important. */
|
||||
/** Override this to get the chance to swap a component's mouse cursor for a
|
||||
customised one.
|
||||
|
||||
@see MouseCursor
|
||||
*/
|
||||
virtual MouseCursor getMouseCursorFor (Component&);
|
||||
|
||||
/** Creates a new graphics context object. */
|
||||
virtual std::unique_ptr<LowLevelGraphicsContext> createGraphicsContext (const Image& imageToRenderOn,
|
||||
Point<int> origin,
|
||||
const RectangleList<int>& initialClip);
|
||||
|
||||
/** Plays the system's default 'beep' noise, to alert the user about something
|
||||
very important. This is only supported on some platforms.
|
||||
*/
|
||||
virtual void playAlertSound();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -2056,9 +2056,28 @@ int LookAndFeel_V2::getDefaultMenuBarHeight()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
DropShadower* LookAndFeel_V2::createDropShadowerForComponent (Component*)
|
||||
std::unique_ptr<DropShadower> LookAndFeel_V2::createDropShadowerForComponent (Component&)
|
||||
{
|
||||
return new DropShadower (DropShadow (Colours::black.withAlpha (0.4f), 10, Point<int> (0, 2)));
|
||||
return std::make_unique<DropShadower> (DropShadow (Colours::black.withAlpha (0.4f), 10, Point<int> (0, 2)));
|
||||
}
|
||||
|
||||
std::unique_ptr<FocusOutline> LookAndFeel_V2::createFocusOutlineForComponent (Component&)
|
||||
{
|
||||
struct WindowProperties : public FocusOutline::OutlineWindowProperties
|
||||
{
|
||||
Rectangle<int> getOutlineBounds (Component& c) override
|
||||
{
|
||||
return c.getScreenBounds();
|
||||
}
|
||||
|
||||
void drawOutline (Graphics& g, int width, int height) override
|
||||
{
|
||||
g.setColour (Colours::yellow.withAlpha (0.6f));
|
||||
g.drawRoundedRectangle ({ (float) width, (float) height }, 3.0f, 3.0f);
|
||||
}
|
||||
};
|
||||
|
||||
return std::make_unique<FocusOutline> (std::make_unique<WindowProperties>());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -299,7 +299,8 @@ public:
|
|||
bool positionTitleBarButtonsOnLeft) override;
|
||||
|
||||
//==============================================================================
|
||||
DropShadower* createDropShadowerForComponent (Component*) override;
|
||||
std::unique_ptr<DropShadower> createDropShadowerForComponent (Component&) override;
|
||||
std::unique_ptr<FocusOutline> createFocusOutlineForComponent (Component&) override;
|
||||
|
||||
//==============================================================================
|
||||
void drawStretchableLayoutResizerBar (Graphics&, int w, int h, bool isVerticalBar,
|
||||
|
|
|
|||
|
|
@ -55,17 +55,8 @@ public:
|
|||
/** Attaches the DropShadower to the component you want to shadow. */
|
||||
void setOwner (Component* componentToFollow);
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class ShadowWindow;
|
||||
|
||||
WeakReference<Component> owner;
|
||||
OwnedArray<Component> shadowWindows;
|
||||
DropShadow shadow;
|
||||
bool reentrant = false;
|
||||
WeakReference<Component> lastParentComp;
|
||||
|
||||
void componentMovedOrResized (Component&, bool, bool) override;
|
||||
void componentBroughtToFront (Component&) override;
|
||||
void componentChildrenChanged (Component&) override;
|
||||
|
|
@ -75,6 +66,14 @@ private:
|
|||
void updateParent();
|
||||
void updateShadows();
|
||||
|
||||
class ShadowWindow;
|
||||
|
||||
WeakReference<Component> owner;
|
||||
OwnedArray<Component> shadowWindows;
|
||||
DropShadow shadow;
|
||||
bool reentrant = false;
|
||||
WeakReference<Component> lastParentComp;
|
||||
|
||||
class ParentVisibilityChangedListener;
|
||||
std::unique_ptr<ParentVisibilityChangedListener> visibilityChangedListener;
|
||||
|
||||
|
|
|
|||
185
modules/juce_gui_basics/misc/juce_FocusOutline.cpp
Normal file
185
modules/juce_gui_basics/misc/juce_FocusOutline.cpp
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
struct OutlineWindowComponent : public Component
|
||||
{
|
||||
OutlineWindowComponent (Component* c, FocusOutline::OutlineWindowProperties& p)
|
||||
: target (c), props (p)
|
||||
{
|
||||
setVisible (true);
|
||||
setInterceptsMouseClicks (false, false);
|
||||
|
||||
if (target->isOnDesktop())
|
||||
{
|
||||
setSize (1, 1);
|
||||
addToDesktop (ComponentPeer::windowIgnoresMouseClicks
|
||||
| ComponentPeer::windowIsTemporary
|
||||
| ComponentPeer::windowIgnoresKeyPresses);
|
||||
}
|
||||
else if (auto* parent = target->getParentComponent())
|
||||
{
|
||||
auto targetIndex = parent->getIndexOfChildComponent (target);
|
||||
parent->addChildComponent (this, targetIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
if (target != nullptr)
|
||||
props.drawOutline (g, getWidth(), getHeight());
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
|
||||
float getDesktopScaleFactor() const override
|
||||
{
|
||||
return target != nullptr ? target->getDesktopScaleFactor()
|
||||
: Component::getDesktopScaleFactor();
|
||||
}
|
||||
|
||||
private:
|
||||
WeakReference<Component> target;
|
||||
FocusOutline::OutlineWindowProperties& props;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (OutlineWindowComponent)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
FocusOutline::FocusOutline (std::unique_ptr<OutlineWindowProperties> props)
|
||||
: properties (std::move (props))
|
||||
{
|
||||
}
|
||||
|
||||
FocusOutline::~FocusOutline()
|
||||
{
|
||||
if (owner != nullptr)
|
||||
owner->removeComponentListener (this);
|
||||
|
||||
if (lastParentComp != nullptr)
|
||||
lastParentComp->removeComponentListener (this);
|
||||
}
|
||||
|
||||
void FocusOutline::setOwner (Component* componentToFollow)
|
||||
{
|
||||
if (componentToFollow != owner)
|
||||
{
|
||||
if (owner != nullptr)
|
||||
owner->removeComponentListener (this);
|
||||
|
||||
owner = componentToFollow;
|
||||
|
||||
if (owner != nullptr)
|
||||
owner->addComponentListener (this);
|
||||
|
||||
updateParent();
|
||||
updateOutlineWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void FocusOutline::componentMovedOrResized (Component& c, bool, bool)
|
||||
{
|
||||
if (owner == &c)
|
||||
updateOutlineWindow();
|
||||
}
|
||||
|
||||
void FocusOutline::componentBroughtToFront (Component& c)
|
||||
{
|
||||
if (owner == &c)
|
||||
updateOutlineWindow();
|
||||
}
|
||||
|
||||
void FocusOutline::componentParentHierarchyChanged (Component& c)
|
||||
{
|
||||
if (owner == &c)
|
||||
{
|
||||
updateParent();
|
||||
updateOutlineWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void FocusOutline::componentVisibilityChanged (Component& c)
|
||||
{
|
||||
if (owner == &c)
|
||||
updateOutlineWindow();
|
||||
}
|
||||
|
||||
void FocusOutline::updateParent()
|
||||
{
|
||||
lastParentComp = (owner != nullptr ? owner->getParentComponent()
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
void FocusOutline::updateOutlineWindow()
|
||||
{
|
||||
if (reentrant)
|
||||
return;
|
||||
|
||||
const ScopedValueSetter<bool> setter (reentrant, true);
|
||||
|
||||
if (owner == nullptr)
|
||||
{
|
||||
outlineWindow = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (owner->isShowing()
|
||||
&& owner->getWidth() > 0 && owner->getHeight() > 0)
|
||||
{
|
||||
if (outlineWindow == nullptr)
|
||||
outlineWindow = std::make_unique<OutlineWindowComponent> (owner, *properties);
|
||||
|
||||
WeakReference<Component> deletionChecker (outlineWindow.get());
|
||||
|
||||
outlineWindow->setAlwaysOnTop (owner->isAlwaysOnTop());
|
||||
|
||||
if (deletionChecker == nullptr)
|
||||
return;
|
||||
|
||||
const auto windowBounds = [this]
|
||||
{
|
||||
const auto bounds = properties->getOutlineBounds (*owner);
|
||||
|
||||
if (lastParentComp != nullptr)
|
||||
return lastParentComp->getLocalArea (nullptr, bounds);
|
||||
|
||||
return bounds;
|
||||
}();
|
||||
|
||||
outlineWindow->setBounds (windowBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
outlineWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
100
modules/juce_gui_basics/misc/juce_FocusOutline.h
Normal file
100
modules/juce_gui_basics/misc/juce_FocusOutline.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
Adds a focus outline to a component.
|
||||
|
||||
This object creates and manages a component that sits on top of a target
|
||||
component. It will track the position of the target component and will be
|
||||
brought to the front with the tracked component.
|
||||
|
||||
Use the Component::setHasFocusOutline() method to indicate that a component
|
||||
should have a focus outline drawn around it, and when it receives keyboard
|
||||
focus one of these objects will be created using the
|
||||
LookAndFeel::createFocusOutlineForComponent() method. You can override this
|
||||
method in your own LookAndFeel classes to draw a custom outline if required.
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API FocusOutline : private ComponentListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Defines the focus outline window properties.
|
||||
|
||||
Pass an instance of one of these to the FocusOutline constructor to control
|
||||
the bounds for the outline window and how it is drawn.
|
||||
*/
|
||||
struct JUCE_API OutlineWindowProperties
|
||||
{
|
||||
virtual ~OutlineWindowProperties() = default;
|
||||
|
||||
/** Return the bounds for the outline window in screen coordinates. */
|
||||
virtual Rectangle<int> getOutlineBounds (Component& focusedComponent) = 0;
|
||||
|
||||
/** This method will be called to draw the focus outline. */
|
||||
virtual void drawOutline (Graphics&, int width, int height) = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a FocusOutline.
|
||||
|
||||
Call setOwner to attach it to a component.
|
||||
*/
|
||||
FocusOutline (std::unique_ptr<OutlineWindowProperties> props);
|
||||
|
||||
/** Destructor. */
|
||||
~FocusOutline() override;
|
||||
|
||||
/** Attaches the outline to a component. */
|
||||
void setOwner (Component* componentToFollow);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void componentMovedOrResized (Component&, bool, bool) override;
|
||||
void componentBroughtToFront (Component&) override;
|
||||
void componentParentHierarchyChanged (Component&) override;
|
||||
void componentVisibilityChanged (Component&) override;
|
||||
|
||||
void updateOutlineWindow();
|
||||
void updateParent();
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<OutlineWindowProperties> properties;
|
||||
|
||||
WeakReference<Component> owner;
|
||||
std::unique_ptr<Component> outlineWindow;
|
||||
WeakReference<Component> lastParentComp;
|
||||
|
||||
bool reentrant = false;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FocusOutline)
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
|
|
@ -2452,7 +2452,7 @@ private:
|
|||
if (! component.isCurrentlyModal() && (styleFlags & windowHasDropShadow) != 0
|
||||
&& ((! hasTitleBar()) || SystemStats::getOperatingSystemType() < SystemStats::WinVista))
|
||||
{
|
||||
shadower.reset (component.getLookAndFeel().createDropShadowerForComponent (&component));
|
||||
shadower = component.getLookAndFeel().createDropShadowerForComponent (component);
|
||||
|
||||
if (shadower != nullptr)
|
||||
shadower->setOwner (&component);
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ TopLevelWindow::TopLevelWindow (const String& name, const bool shouldAddToDeskto
|
|||
|
||||
TopLevelWindow::~TopLevelWindow()
|
||||
{
|
||||
shadower.reset();
|
||||
shadower = nullptr;
|
||||
TopLevelWindowManager::getInstance()->removeWindow (this);
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +213,7 @@ void TopLevelWindow::setDropShadowEnabled (const bool useShadow)
|
|||
|
||||
if (isOnDesktop())
|
||||
{
|
||||
shadower.reset();
|
||||
shadower = nullptr;
|
||||
Component::addToDesktop (getDesktopWindowStyleFlags());
|
||||
}
|
||||
else
|
||||
|
|
@ -222,7 +222,7 @@ void TopLevelWindow::setDropShadowEnabled (const bool useShadow)
|
|||
{
|
||||
if (shadower == nullptr)
|
||||
{
|
||||
shadower.reset (getLookAndFeel().createDropShadowerForComponent (this));
|
||||
shadower = getLookAndFeel().createDropShadowerForComponent (*this);
|
||||
|
||||
if (shadower != nullptr)
|
||||
shadower->setOwner (this);
|
||||
|
|
@ -230,7 +230,7 @@ void TopLevelWindow::setDropShadowEnabled (const bool useShadow)
|
|||
}
|
||||
else
|
||||
{
|
||||
shadower.reset();
|
||||
shadower = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -257,7 +257,7 @@ void TopLevelWindow::recreateDesktopWindow()
|
|||
|
||||
void TopLevelWindow::addToDesktop()
|
||||
{
|
||||
shadower.reset();
|
||||
shadower = nullptr;
|
||||
Component::addToDesktop (getDesktopWindowStyleFlags());
|
||||
setDropShadowEnabled (isDropShadowEnabled()); // force an update to clear away any fake shadows if necessary.
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue