mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
StandaloneFilterWindow: Respect editor's size constraints when adjusting size of component peer
This commit is contained in:
parent
63b6ecde4f
commit
c0b78adcda
1 changed files with 108 additions and 26 deletions
|
|
@ -709,6 +709,8 @@ public:
|
|||
: DocumentWindow (title, backgroundColour, DocumentWindow::minimiseButton | DocumentWindow::closeButton),
|
||||
optionsButton ("Options")
|
||||
{
|
||||
setConstrainer (&decoratorConstrainer);
|
||||
|
||||
#if JUCE_IOS || JUCE_ANDROID
|
||||
setTitleBarHeight (0);
|
||||
#else
|
||||
|
|
@ -725,9 +727,9 @@ public:
|
|||
|
||||
#if JUCE_IOS || JUCE_ANDROID
|
||||
setFullScreen (true);
|
||||
setContentOwned (new MainContentComponent (*this), false);
|
||||
updateContent();
|
||||
#else
|
||||
setContentOwned (new MainContentComponent (*this), true);
|
||||
updateContent();
|
||||
|
||||
const auto windowScreenBounds = [this]() -> Rectangle<int>
|
||||
{
|
||||
|
|
@ -798,7 +800,7 @@ public:
|
|||
props->removeValue ("filterState");
|
||||
|
||||
pluginHolder->createPlugin();
|
||||
setContentOwned (new MainContentComponent (*this), true);
|
||||
updateContent();
|
||||
pluginHolder->startPlaying();
|
||||
}
|
||||
|
||||
|
|
@ -839,6 +841,20 @@ public:
|
|||
std::unique_ptr<StandalonePluginHolder> pluginHolder;
|
||||
|
||||
private:
|
||||
void updateContent()
|
||||
{
|
||||
auto* content = new MainContentComponent (*this);
|
||||
decoratorConstrainer.setMainContentComponent (content);
|
||||
|
||||
#if JUCE_IOS || JUCE_ANDROID
|
||||
constexpr auto resizeAutomatically = false;
|
||||
#else
|
||||
constexpr auto resizeAutomatically = true;
|
||||
#endif
|
||||
|
||||
setContentOwned (content, resizeAutomatically);
|
||||
}
|
||||
|
||||
void buttonClicked (Button*) override
|
||||
{
|
||||
PopupMenu m;
|
||||
|
|
@ -914,6 +930,23 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
ComponentBoundsConstrainer* getEditorConstrainer() const
|
||||
{
|
||||
if (auto* e = editor.get())
|
||||
return e->getConstrainer();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BorderSize<int> computeBorder() const
|
||||
{
|
||||
const auto outer = owner.getContentComponentBorder();
|
||||
return { outer.getTop() + (shouldShowNotification ? NotificationArea::height : 0),
|
||||
outer.getLeft(),
|
||||
outer.getBottom(),
|
||||
outer.getRight() };
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class NotificationArea : public Component
|
||||
|
|
@ -975,29 +1008,6 @@ private:
|
|||
{
|
||||
const int extraHeight = shouldShowNotification ? NotificationArea::height : 0;
|
||||
const auto rect = getSizeToContainEditor();
|
||||
|
||||
if (auto* editorConstrainer = editor->getConstrainer())
|
||||
{
|
||||
const auto borders = owner.getContentComponentBorder();
|
||||
|
||||
const auto windowBorders = [&]() -> BorderSize<int>
|
||||
{
|
||||
if (auto* peer = owner.getPeer())
|
||||
if (const auto frameSize = peer->getFrameSizeIfPresent())
|
||||
return *frameSize;
|
||||
|
||||
return {};
|
||||
}();
|
||||
|
||||
const auto extraWindowWidth = borders.getLeftAndRight() + windowBorders.getLeftAndRight();
|
||||
const auto extraWindowHeight = extraHeight + borders.getTopAndBottom() + windowBorders.getTopAndBottom();
|
||||
|
||||
owner.setResizeLimits (jmax (10, editorConstrainer->getMinimumWidth() + extraWindowWidth),
|
||||
jmax (10, editorConstrainer->getMinimumHeight() + extraWindowHeight),
|
||||
editorConstrainer->getMaximumWidth() + extraWindowWidth,
|
||||
editorConstrainer->getMaximumHeight() + extraWindowHeight);
|
||||
}
|
||||
|
||||
setSize (rect.getWidth(), rect.getHeight() + extraHeight);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1046,8 +1056,80 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
|
||||
};
|
||||
|
||||
/* This custom constrainer checks with the AudioProcessorEditor (which might itself be
|
||||
constrained) to ensure that any size we choose for the standalone window will be suitable
|
||||
for the editor too.
|
||||
|
||||
Without this constrainer, attempting to resize the standalone window may set bounds on the
|
||||
peer that are unsupported by the inner editor. In this scenario, the peer will be set to a
|
||||
'bad' size, then the inner editor will be resized. The editor will check the new bounds with
|
||||
its own constrainer, and may set itself to a more suitable size. After that, the resizable
|
||||
window will see that its content component has changed size, and set the bounds of the peer
|
||||
accordingly. The end result is that the peer is resized twice in a row to different sizes,
|
||||
which can appear glitchy/flickery to the user.
|
||||
*/
|
||||
struct DecoratorConstrainer : public ComponentBoundsConstrainer
|
||||
{
|
||||
void checkBounds (Rectangle<int>& bounds,
|
||||
const Rectangle<int>& previousBounds,
|
||||
const Rectangle<int>& limits,
|
||||
bool isStretchingTop,
|
||||
bool isStretchingLeft,
|
||||
bool isStretchingBottom,
|
||||
bool isStretchingRight) override
|
||||
{
|
||||
auto* decorated = contentComponent != nullptr ? contentComponent->getEditorConstrainer()
|
||||
: nullptr;
|
||||
|
||||
if (decorated != nullptr)
|
||||
{
|
||||
const auto border = contentComponent->computeBorder();
|
||||
const auto requestedBounds = bounds;
|
||||
|
||||
border.subtractFrom (bounds);
|
||||
decorated->checkBounds (bounds,
|
||||
border.subtractedFrom (previousBounds),
|
||||
limits,
|
||||
isStretchingTop,
|
||||
isStretchingLeft,
|
||||
isStretchingBottom,
|
||||
isStretchingRight);
|
||||
border.addTo (bounds);
|
||||
bounds = bounds.withPosition (requestedBounds.getPosition());
|
||||
|
||||
if (isStretchingTop && ! isStretchingBottom)
|
||||
bounds = bounds.withBottomY (previousBounds.getBottom());
|
||||
|
||||
if (! isStretchingTop && isStretchingBottom)
|
||||
bounds = bounds.withY (previousBounds.getY());
|
||||
|
||||
if (isStretchingLeft && ! isStretchingRight)
|
||||
bounds = bounds.withRightX (previousBounds.getRight());
|
||||
|
||||
if (! isStretchingLeft && isStretchingRight)
|
||||
bounds = bounds.withX (previousBounds.getX());
|
||||
}
|
||||
else
|
||||
{
|
||||
ComponentBoundsConstrainer::checkBounds (bounds,
|
||||
previousBounds,
|
||||
limits,
|
||||
isStretchingTop,
|
||||
isStretchingLeft,
|
||||
isStretchingBottom,
|
||||
isStretchingRight);
|
||||
}
|
||||
}
|
||||
|
||||
void setMainContentComponent (MainContentComponent* in) { contentComponent = in; }
|
||||
|
||||
private:
|
||||
MainContentComponent* contentComponent = nullptr;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
TextButton optionsButton;
|
||||
DecoratorConstrainer decoratorConstrainer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StandaloneFilterWindow)
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue