Skip to content

Commit 0af0dbb

Browse files
authored
Merge pull request #1155 from kushview/embed-from-window
Re-Embed from Plugin Window
2 parents fb4dde0 + d09cd1f commit 0af0dbb

11 files changed

Lines changed: 91 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Change Log
22

3+
## [1.2.x]
4+
5+
### Fixed
6+
- Blocks embedded in the graph return to their embedded state when the plugin window is closed.
7+
38
## [1.2.0]
49

510
### Added

CLAUDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Copilot Instructions for Element
22

3+
## Role
4+
5+
You are an expert in JUCE and in desktop audio application UI. Element is a JUCE application: prefer JUCE's own idioms and classes over hand-rolled equivalents, respect the message-thread / audio-thread split, and consult the JUCE API docs and source in `build/_deps/juce-src/modules/` rather than assuming an API's behaviour. Apply the same expert eye to UI work — component lifetime, layout in `resized()`, `LookAndFeel` usage, and keeping the graph editor's visual state in sync with the underlying `ValueTree` model.
6+
37
## General Conventions
48

59
- **Always check documentation**: Before making assumptions about APIs, libraries, or tools, consult the official documentation first.

include/element/element.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ extern "C" {
1717
#ifdef _WIN32
1818
// windows exports
1919
#if defined(EL_SHARED_BUILD)
20-
#define EL_API __declspec(dllexport)
20+
#define EL_API __declspec (dllexport)
2121
#pragma warning(disable : 4251)
2222
#elif defined(EL_SHARED)
23-
#define EL_API __declspec(dllimport)
23+
#define EL_API __declspec (dllimport)
2424
#pragma warning(disable : 4251)
2525
#endif
26-
#define EL_PLUGIN_EXPORT EL_EXTERN __declspec(dllexport)
26+
#define EL_PLUGIN_EXPORT EL_EXTERN __declspec (dllexport)
2727
#else
2828
#if defined(EL_SHARED) || defined(EL_SHARED_BUILD)
2929
#define EL_API __attribute__ ((visibility ("default")))

include/element/porttype.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class PortType {
101101
inline bool operator!= (const ID& id) const { return (type != id); }
102102
inline bool operator== (const PortType& t) const { return (type == t.type); }
103103
inline bool operator!= (const PortType& t) const { return (type != t.type); }
104-
inline bool operator<(const PortType& t) const { return (type < t.type); }
104+
inline bool operator< (const PortType& t) const { return (type < t.type); }
105105

106106
inline operator int() const { return (int) this->type; }
107107

include/element/tags.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ static const juce::Identifier controllers = "controllers";
102102
static const juce::Identifier collapsed = "collapsed";
103103
static const juce::Identifier delayCompensation = "delayCompensation";
104104
static const juce::Identifier displayMode = "displayMode";
105+
static const juce::Identifier lastDisplayMode = "lastDisplayMode";
105106
static const juce::Identifier enabled = "enabled";
106107
static const juce::Identifier gain = "gain";
107108
static const juce::Identifier graphs = "graphs";

include/element/version.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class Version {
9595
inline bool operator== (const Version& o) const noexcept { return _hex == o._hex; }
9696
inline bool operator!= (const Version& o) const noexcept { return _hex != o._hex; }
9797
inline bool operator> (const Version& o) const noexcept { return _hex > o._hex; }
98-
inline bool operator<(const Version& o) const noexcept { return _hex < o._hex; }
98+
inline bool operator< (const Version& o) const noexcept { return _hex < o._hex; }
9999
inline bool operator>= (const Version& o) const noexcept { return _hex >= o._hex; }
100100
inline bool operator<= (const Version& o) const noexcept { return _hex <= o._hex; }
101101

src/engine/clapprovider.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,7 @@ class CLAPHost final : public CLAPBaseHost
389389
pfds.reserve (fds.size());
390390
for (const auto& f : fds)
391391
{
392-
struct pollfd p
393-
{
394-
};
392+
struct pollfd p {};
395393
p.fd = f.first;
396394
if (f.second & CLAP_POSIX_FD_READ)
397395
p.events |= POLLIN;

src/filesystemwatcher.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,7 @@ class FileSystemWatcher::Impl
140140
CFArrayRef paths { nullptr };
141141
dispatch_queue_t queue { nullptr };
142142
FSEventStreamRef stream { nullptr };
143-
struct FSEventStreamContext context
144-
{
145-
};
143+
struct FSEventStreamContext context {};
146144
};
147145
#endif
148146

src/services/guiservice.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ void GuiService::showPluginWindowsFor (const Node& node, const bool recursive, c
590590
{
591591
if (! node.isGraph())
592592
{
593-
if (force || (bool) node.getProperty ("windowVisible", false))
593+
if (force || (bool) node.getProperty (tags::windowVisible, false))
594594
presentPluginWindow (node, force);
595595
return;
596596
}
@@ -613,7 +613,17 @@ void GuiService::presentPluginWindow (const Node& node, const bool focus)
613613

614614
auto* window = windowManager->getPluginWindowFor (node);
615615
if (! window)
616+
{
617+
// Flag the window visible up front. A graph block embedding this node's editor
618+
// watches this property and releases the editor synchronously, freeing the node's
619+
// single editor slot so the window can create the node's real UI instead of
620+
// falling back to a generic one.
621+
Node target (node);
622+
target.setProperty (tags::windowVisible, true);
616623
window = windowManager->createPluginWindowFor (node);
624+
if (window == nullptr)
625+
target.setProperty (tags::windowVisible, false);
626+
}
617627

618628
if (window != nullptr)
619629
{

src/ui/block.cpp

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@ BlockComponent::BlockComponent (const Node& graph_, const Node& node_, const boo
216216
auto blockData = node.getBlockValueTree();
217217
displayModeValue = blockData.getPropertyAsValue (tags::displayMode, nullptr);
218218
displayModeValue.addListener (this);
219+
220+
// Updates synchronously: GuiService flags the window visible before building it, and
221+
// this block has to give up its embedded editor before the window creates its own.
222+
windowVisibleValue = node.getPropertyAsValue (tags::windowVisible, true);
223+
windowVisibleValue.addListener (this);
224+
if (! (bool) node.getProperty (tags::windowVisible, false))
225+
blockData.removeProperty (tags::lastDisplayMode, nullptr);
226+
219227
const auto idm = getDisplayModeFromString (displayModeValue.getValue());
220228
setDisplayModeInternal (idm, false);
221229
if (idm == Embed)
@@ -263,6 +271,7 @@ BlockComponent::~BlockComponent() noexcept
263271
nodeName.removeListener (this);
264272
hiddenPorts.removeListener (this);
265273
displayModeValue.removeListener (this);
274+
windowVisibleValue.removeListener (this);
266275
deleteAllPins();
267276
}
268277

@@ -384,6 +393,27 @@ void BlockComponent::setDisplayMode (DisplayMode mode)
384393
setDisplayModeInternal (mode, false);
385394
}
386395

396+
void BlockComponent::stashDisplayModeForWindow()
397+
{
398+
if (displayMode != Embed)
399+
return;
400+
401+
node.getBlockValueTree().setProperty (
402+
tags::lastDisplayMode, getDisplayModeKey (displayMode), nullptr);
403+
setDisplayMode (Small);
404+
}
405+
406+
void BlockComponent::restoreDisplayModeAfterWindow()
407+
{
408+
auto blockData = node.getBlockValueTree();
409+
const auto stashed = blockData.getProperty (tags::lastDisplayMode).toString();
410+
if (stashed.isEmpty())
411+
return;
412+
413+
blockData.removeProperty (tags::lastDisplayMode, nullptr);
414+
setDisplayMode (getDisplayModeFromString (stashed));
415+
}
416+
387417
void BlockComponent::setPortAlignment (PortAlignment newAlign)
388418
{
389419
node.getBlockValueTree().setProperty (
@@ -427,7 +457,14 @@ void BlockComponent::valueChanged (Value& value)
427457
{
428458
update (false, false);
429459
}
430-
else if (nodeObject.refersToSameSourceAs (nodeObject))
460+
else if (windowVisibleValue.refersToSameSourceAs (value))
461+
{
462+
if ((bool) value.getValue())
463+
stashDisplayModeForWindow();
464+
else
465+
restoreDisplayModeAfterWindow();
466+
}
467+
else if (nodeObject.refersToSameSourceAs (value))
431468
{
432469
willRemoveConn.disconnect();
433470
clearEmbedded();
@@ -752,10 +789,7 @@ void BlockComponent::makeEditorActive()
752789
}
753790
else if (node.isValid())
754791
{
755-
if (displayMode == Embed)
756-
{
757-
setDisplayMode (Small);
758-
}
792+
stashDisplayModeForWindow();
759793
ViewHelpers::presentPluginWindow (this, node);
760794
}
761795
}
@@ -1361,12 +1395,15 @@ void BlockComponent::addDisplaySubmenu (PopupMenu& menuToAddTo)
13611395
const auto m = static_cast<BlockComponent::DisplayMode> (i);
13621396
const bool enabled = m == BlockComponent::Embed ? detail::supportsEmbed (node) : true;
13631397
dMenu.addItem (BlockComponent::getDisplayModeName (m), enabled, mode == m, [this, block, m]() {
1398+
// Choosing a mode explicitly abandons any mode stashed for a plugin window.
13641399
auto b = block;
1400+
b.removeProperty (tags::lastDisplayMode, nullptr);
13651401
b.setProperty (tags::displayMode, BlockComponent::getDisplayModeKey (m), nullptr);
13661402
forEachSibling ([m] (BlockComponent& sibling) {
13671403
if (! sibling.isSelected())
13681404
return;
13691405
auto sb = sibling.node.getBlockValueTree();
1406+
sb.removeProperty (tags::lastDisplayMode, nullptr);
13701407
sb.setProperty (tags::displayMode, BlockComponent::getDisplayModeKey (m), nullptr);
13711408
});
13721409

0 commit comments

Comments
 (0)