Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/setroot #96

Merged
merged 3 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions melatonin/components/fps_meter.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ namespace melatonin
class FPSMeter : public juce::Component, private juce::Timer
{
public:
explicit FPSMeter (juce::Component& o) : overlay (o)
FPSMeter ()
{
overlay.addChildComponent (this);

// don't repaint the parent
// unfortunately, on macOS, this no longer works
// See FAQ in README for more info
Expand All @@ -26,6 +24,19 @@ namespace melatonin
setInterceptsMouseClicks (false, false);
}

void setRoot (juce::Component& o)
{
overlay = &o;

overlay->addChildComponent (this);
}

void clearRoot()
{
if (overlay)
overlay->removeChildComponent (this);
}

void timerCallback() override
{
TRACE_EVENT ("component", "fps timer callback");
Expand Down Expand Up @@ -108,7 +119,7 @@ namespace melatonin
}

private:
juce::Component& overlay;
juce::Component* overlay = nullptr;
juce::Rectangle<int> bounds;
juce::Font font = juce::Font (juce::Font::getDefaultMonospacedFontName(), 16.0f, juce::Font::plain);
double lastTime = juce::Time::getMillisecondCounterHiRes();
Expand Down
34 changes: 22 additions & 12 deletions melatonin/helpers/overlay_mouse_listener.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,42 @@ namespace melatonin
class OverlayMouseListener : public juce::MouseListener
{
public:
explicit OverlayMouseListener (juce::Component& c, bool startEnabled = true) : root (c)
OverlayMouseListener()
{
// Listen to all mouse movements for all children of the root
if (startEnabled)
{
enabled = true;
root.addMouseListener (this, true);
}
}

~OverlayMouseListener() override
{
if (enabled && root)
root->removeMouseListener (this);
}

void setRoot (juce::Component& c)
{
root = &c;

if (enabled)
root.removeMouseListener (this);
root->addMouseListener (this, true);
}

void clearRoot()
{
if (enabled && root)
root->removeMouseListener (this);

root = nullptr;
}

void enable()
{
enabled = true;
root.addMouseListener (this, true);
root->addMouseListener (this, true);
}

void disable()
{
enabled = false;
root.removeMouseListener (this);
root->removeMouseListener (this);
}

void mouseEnter (const juce::MouseEvent& event) override
Expand Down Expand Up @@ -78,7 +88,7 @@ namespace melatonin

void mouseExit (const juce::MouseEvent& event) override
{
if (event.originalComponent == &root)
if (event.originalComponent == root)
{
mouseExitCallback();
}
Expand All @@ -94,7 +104,7 @@ namespace melatonin
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OverlayMouseListener)

juce::Component& root;
juce::Component* root = nullptr;
bool enabled = false;
bool isDragging { false };
};
Expand Down
27 changes: 22 additions & 5 deletions melatonin/inspector_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace melatonin
class InspectorComponent : public juce::Component
{
public:
explicit InspectorComponent (juce::Component& rootComponent, bool enabledAtStart = true) : root (rootComponent), inspectorEnabled (enabledAtStart)
explicit InspectorComponent()
{
TRACE_COMPONENT();

Expand Down Expand Up @@ -48,7 +48,6 @@ namespace melatonin
addAndMakeVisible (searchIcon);
addChildComponent (clearButton);

colorPicker.setRootComponent (&root);
colorPicker.togglePickerCallback = [this] (bool value) {
if (toggleOverlayCallback)
{
Expand Down Expand Up @@ -153,6 +152,24 @@ namespace melatonin
tree.setRootItem (nullptr);
}

void setRoot (juce::Component& r)
{
root = &r;
colorPicker.setRootComponent (root);

tree.setRootItem (nullptr);
rootItem = nullptr;

if (inspectorEnabled)
ensureTreeIsConstructed();
}

void clearRoot()
{
root = nullptr;
colorPicker.setRootComponent (nullptr);
}

void paint (juce::Graphics& g) override
{
auto mainPanelGradient = juce::ColourGradient::horizontal (colors::panelBackgroundDarker, (float) mainColumnBounds.getX(), colors::panelBackgroundLighter, (float) mainColumnBounds.getWidth());
Expand Down Expand Up @@ -185,7 +202,7 @@ namespace melatonin
tree.setRootItem (nullptr);

// construct the root item
rootItem = std::make_unique<ComponentTreeViewItem> (&root, outlineComponentCallback, selectComponentCallback);
rootItem = std::make_unique<ComponentTreeViewItem> (root, outlineComponentCallback, selectComponentCallback);
tree.setRootItem (rootItem.get());
getRoot()->setOpenness (ComponentTreeViewItem::Openness::opennessOpen);

Expand Down Expand Up @@ -354,10 +371,10 @@ namespace melatonin

private:
Component::SafePointer<Component> selectedComponent;
Component& root;
Component* root = nullptr;
juce::SharedResourcePointer<InspectorSettings> settings;
ComponentModel model;
bool inspectorEnabled;
bool inspectorEnabled = false;

juce::Rectangle<int> mainColumnBounds, topArea, searchBoxBounds, treeViewBounds;
InspectorImageButton logo { "logo" };
Expand Down
98 changes: 80 additions & 18 deletions melatonin_inspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ END_JUCE_MODULE_DECLARATION

namespace melatonin
{
class Inspector : public juce::ComponentListener, public juce::DocumentWindow
class Inspector : public juce::ComponentListener, public juce::DocumentWindow, private juce::Timer
{
public:
class InspectorKeyCommands : public juce::KeyListener
Expand Down Expand Up @@ -65,21 +65,13 @@ namespace melatonin
}
};
explicit Inspector (juce::Component& rootComponent, bool inspectorEnabledAtStart = true)
: juce::DocumentWindow ("Melatonin Inspector", colors::background, 7, true),
inspectorComponent (rootComponent),
root (rootComponent)
: juce::DocumentWindow ("Melatonin Inspector", colors::background, 7, true)
{
TRACE_COMPONENT();
root.addChildComponent (overlay);
overlay.setBounds (root.getLocalBounds());
root.addComponentListener (this);

// allow us to open/close the inspector by key command
// bit sketchy because we're modifying the source app to accept key focus
root.addKeyListener (&keyListener);
root.setWantsKeyboardFocus (true);
this->addKeyListener (&keyListener);

setRoot (rootComponent);

// needs to come before the LNF
restoreBoundsIfNeeded();

Expand All @@ -98,15 +90,48 @@ namespace melatonin

~Inspector() override
{
root.removeKeyListener (&keyListener);
clearRoot();

this->removeKeyListener (&keyListener);
root.removeComponentListener (this);

// needed, otherwise removing look and feel will save bounds
settings->props.reset();
setLookAndFeel (nullptr);
}

void setRoot (juce::Component& rootComponent)
{
clearRoot();

root = &rootComponent;

root->addChildComponent (overlay);
overlay.setBounds (root->getLocalBounds());
root->addComponentListener (this);

// allow us to open/close the inspector by key command
// bit sketchy because we're modifying the source app to accept key focus
root->addKeyListener (&keyListener);
root->setWantsKeyboardFocus (true);

fpsMeter.setRoot (*root);
overlayMouseListener.setRoot (*root);
inspectorComponent.setRoot (*root);
}

void clearRoot()
{
if (root == nullptr)
return;

root->removeKeyListener (&keyListener);
root->removeComponentListener (this);

fpsMeter.clearRoot();
overlayMouseListener.clearRoot();
inspectorComponent.clearRoot();
}

void moved() override
{
TRACE_COMPONENT();
Expand Down Expand Up @@ -288,18 +313,29 @@ namespace melatonin
toggle (!inspectorEnabled);
}

void setRootFollowsComponentUnderMouse (bool follow)
{
rootFollowsComponentUnderMouse = follow;

if (rootFollowsComponentUnderMouse)
startTimerHz (25);
else
stopTimer();
}

std::function<void()> onClose;

private:
juce::SharedResourcePointer<InspectorSettings> settings;
melatonin::InspectorLookAndFeel inspectorLookAndFeel;
melatonin::InspectorComponent inspectorComponent;
juce::Component& root;
juce::Component::SafePointer<juce::Component> root;
bool inspectorEnabled = false;
melatonin::Overlay overlay;
melatonin::FPSMeter fpsMeter { root };
melatonin::OverlayMouseListener overlayMouseListener { root, false };
melatonin::FPSMeter fpsMeter;
melatonin::OverlayMouseListener overlayMouseListener;
InspectorKeyCommands keyListener { *this };
bool rootFollowsComponentUnderMouse = false;

// Resize our overlay when the root component changes
void componentMovedOrResized (Component& rootComponent, bool wasMoved, bool wasResized) override
Expand All @@ -310,6 +346,32 @@ namespace melatonin
}
}

void componentBeingDeleted (juce::Component& component) override
{
if (&component == root)
{
clearRoot();

auto& d = juce::Desktop::getInstance();
for (int i = 0; i < d.getNumComponents(); i++)
{
if (auto c = d.getComponent (i); c != nullptr && c != this)
{
setRoot (*c);
return;
}
}
}
}

void timerCallback() override
{
for (auto ms : juce::Desktop::getInstance().getMouseSources())
if (auto c = ms.getComponentUnderMouse())
if (auto top = c->getTopLevelComponent(); top != nullptr && top != root && top != this)
setRoot (*top);
}

void setupCallbacks()
{
overlayMouseListener.outlineComponentCallback = [this] (Component* c) { this->outlineComponent (c); };
Expand All @@ -328,7 +390,7 @@ namespace melatonin
};
inspectorComponent.toggleFPSCallback = [this] (bool enable) {
if (enable)
this->fpsMeter.setBounds (root.getLocalBounds().removeFromRight (60).removeFromTop (40));
this->fpsMeter.setBounds (root->getLocalBounds().removeFromRight (60).removeFromTop (40));
this->fpsMeter.setVisible (enable);
};
}
Expand Down
Loading