From 5a59c92b200c1c42c5e2f34186e1567c57d22d2f Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 5 Mar 2021 18:04:16 +0000 Subject: [PATCH] AudioProcessorEditor: Allow editors to have a corner resizer without being resizable by the host and clarified the documentation regarding this and the editor's constrainer --- .../processors/juce_AudioProcessorEditor.cpp | 71 +++++++------------ .../processors/juce_AudioProcessorEditor.h | 50 ++++++++----- 2 files changed, 55 insertions(+), 66 deletions(-) diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp index b980441c94..7db87b2858 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp @@ -73,38 +73,24 @@ void AudioProcessorEditor::initialise() // END SECTION A - resizable = false; - - attachConstrainer (&defaultConstrainer); + setConstrainer (&defaultConstrainer); resizeListener.reset (new AudioProcessorEditorListener (*this)); addComponentListener (resizeListener.get()); } //============================================================================== -void AudioProcessorEditor::setResizable (const bool shouldBeResizable, const bool useBottomRightCornerResizer) +void AudioProcessorEditor::setResizable (bool allowHostToResize, bool useBottomRightCornerResizer) { - if (shouldBeResizable != resizable) - { - resizable = shouldBeResizable; - - if (! resizable && constrainer == &defaultConstrainer) - { - auto width = getWidth(); - auto height = getHeight(); - - if (width > 0 && height > 0) - defaultConstrainer.setSizeLimits (width, height, width, height); - } - } + resizableByHost = allowHostToResize; - bool shouldHaveCornerResizer = (useBottomRightCornerResizer && shouldBeResizable); + const auto hasResizableCorner = (resizableCorner.get() != nullptr); - if (shouldHaveCornerResizer != (resizableCorner != nullptr)) + if (useBottomRightCornerResizer != hasResizableCorner) { - if (shouldHaveCornerResizer) + if (useBottomRightCornerResizer) attachResizableCornerComponent(); else - resizableCorner.reset(); + resizableCorner = nullptr; } } @@ -113,19 +99,23 @@ void AudioProcessorEditor::setResizeLimits (int newMinimumWidth, int newMaximumWidth, int newMaximumHeight) noexcept { - // if you've set up a custom constrainer then these settings won't have any effect.. - jassert (constrainer == &defaultConstrainer || constrainer == nullptr); + if (constrainer != nullptr && constrainer != &defaultConstrainer) + { + // if you've set up a custom constrainer then these settings won't have any effect.. + jassertfalse; + return; + } - const bool shouldEnableResize = (newMinimumWidth != newMaximumWidth || newMinimumHeight != newMaximumHeight); - const bool shouldHaveCornerResizer = (shouldEnableResize != resizable || resizableCorner != nullptr); + resizableByHost = (newMinimumWidth != newMaximumWidth || newMinimumHeight != newMaximumHeight); - setResizable (shouldEnableResize, shouldHaveCornerResizer); + defaultConstrainer.setSizeLimits (newMinimumWidth, newMinimumHeight, + newMaximumWidth, newMaximumHeight); if (constrainer == nullptr) setConstrainer (&defaultConstrainer); - defaultConstrainer.setSizeLimits (newMinimumWidth, newMinimumHeight, - newMaximumWidth, newMaximumHeight); + if (resizableCorner != nullptr) + attachResizableCornerComponent(); setBoundsConstrained (getBounds()); } @@ -134,29 +124,21 @@ void AudioProcessorEditor::setConstrainer (ComponentBoundsConstrainer* newConstr { if (constrainer != newConstrainer) { - if (newConstrainer != nullptr) - resizable = (newConstrainer->getMinimumWidth() != newConstrainer->getMaximumWidth() - || newConstrainer->getMinimumHeight() != newConstrainer->getMaximumHeight()); + constrainer = newConstrainer; + updatePeer(); - attachConstrainer (newConstrainer); + if (constrainer != nullptr) + resizableByHost = (newConstrainer->getMinimumWidth() != newConstrainer->getMaximumWidth() + || newConstrainer->getMinimumHeight() != newConstrainer->getMaximumHeight()); if (resizableCorner != nullptr) attachResizableCornerComponent(); } } -void AudioProcessorEditor::attachConstrainer (ComponentBoundsConstrainer* newConstrainer) -{ - if (constrainer != newConstrainer) - { - constrainer = newConstrainer; - updatePeer(); - } -} - void AudioProcessorEditor::attachResizableCornerComponent() { - resizableCorner.reset (new ResizableCornerComponent (this, constrainer)); + resizableCorner = std::make_unique (this, constrainer); Component::addChildComponent (resizableCorner.get()); resizableCorner->setAlwaysOnTop (true); editorResized (true); @@ -194,11 +176,6 @@ void AudioProcessorEditor::editorResized (bool wasResized) getHeight() - resizerSize, resizerSize, resizerSize); } - - if (! resizable) - if (auto w = getWidth()) - if (auto h = getHeight()) - defaultConstrainer.setSizeLimits (w, h, w, h); } } diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h index ff694b78fc..c925540c90 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h @@ -54,12 +54,12 @@ public: /** Destructor. */ ~AudioProcessorEditor() override; - //============================================================================== /** The AudioProcessor that this editor represents. */ AudioProcessor& processor; /** Returns a pointer to the processor that this editor represents. + This method is here to support legacy code, but it's easier to just use the AudioProcessorEditor::processor member variable directly to get this object. */ @@ -76,6 +76,7 @@ public: /** Some types of plugin can call this to suggest that the control for a particular parameter should be highlighted. + Currently only AAX plugins will call this, and implementing it is optional. */ virtual void setControlHighlight (ParameterControlHighlightInfo); @@ -117,36 +118,45 @@ public: virtual void setScaleFactor (float newScale); //============================================================================== - /** Marks the host's editor window as resizable - - @param allowHostToResize whether the editor's parent window can be resized - by the user or the host. Even if this is false, you - can still resize your window yourself by calling - setBounds (for example, when a user clicks on a button - in your editor to drop out a panel) which will bypass any - resizable/constraints checks. If you are using - your own corner resizer than this will also bypass - any checks. - @param useBottomRightCornerResizer + /** Sets whether the editor is resizable by the host and/or user. + + @param allowHostToResize whether the editor's parent window can be resized + by the host. Even if this is false, you can still + resize your window yourself by calling setBounds + (for example, when a user clicks on a button in + your editor to drop out a panel) which will bypass + any resizable/constraints checks. + @param useBottomRightCornerResizer if this is true, a ResizableCornerComponent will be + added to the editor's bottom-right to allow the user + to resize the editor regardless of the value of + `allowHostToResize`. + @see setResizeLimits, isResizable */ void setResizable (bool allowHostToResize, bool useBottomRightCornerResizer); - /** Returns true if the host is allowed to resize editor's parent window + /** Returns true if the host is allowed to resize the editor's parent window. @see setResizable */ - bool isResizable() const noexcept { return resizable; } + bool isResizable() const noexcept { return resizableByHost; } /** This sets the maximum and minimum sizes for the window. If the window's current size is outside these limits, it will be resized to make sure it's within them. + If you pass in a different minimum and maximum size, this will mark the editor + as resizable by the host. + A direct call to setBounds() will bypass any constraint checks, but when the window is dragged by the user or resized by other indirect means, the constrainer will limit the numbers involved. + Note that if you have set a custom constrainer for this editor then this will have + no effect, and if you have removed the constrainer with `setConstrainer (nullptr);` + then this will re-add the default constrainer with the new limits. + @see setResizable */ void setResizeLimits (int newMinimumWidth, @@ -154,8 +164,8 @@ public: int newMaximumWidth, int newMaximumHeight) noexcept; - /** Returns the bounds constrainer object that this window is using. + You can access this to change its properties. */ ComponentBoundsConstrainer* getConstrainer() noexcept { return constrainer; } @@ -176,11 +186,14 @@ public: */ void setBoundsConstrained (Rectangle newBounds); + /** The ResizableCornerComponent which is currently being used by this editor, + or nullptr if it does not have one. + */ std::unique_ptr resizableCorner; private: //============================================================================== - struct AudioProcessorEditorListener : ComponentListener + struct AudioProcessorEditorListener : public ComponentListener { AudioProcessorEditorListener (AudioProcessorEditor& e) : ed (e) {} @@ -198,14 +211,13 @@ private: void initialise(); void editorResized (bool wasResized); void updatePeer(); - void attachConstrainer (ComponentBoundsConstrainer*); void attachResizableCornerComponent(); //============================================================================== std::unique_ptr resizeListener; - bool resizable; + bool resizableByHost = false; ComponentBoundsConstrainer defaultConstrainer; - ComponentBoundsConstrainer* constrainer = {}; + ComponentBoundsConstrainer* constrainer = nullptr; Component::SafePointer splashScreen; AffineTransform hostScaleTransform;