Browse Source

Add options to make AuidoProcessorEditors resizable with constraints

tags/2021-05-28
hogliux 9 years ago
parent
commit
ebb0a156a4
5 changed files with 209 additions and 16 deletions
  1. +2
    -5
      examples/audio plugin demo/Source/PluginEditor.cpp
  2. +0
    -2
      examples/audio plugin demo/Source/PluginEditor.h
  3. +23
    -6
      modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  4. +112
    -2
      modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp
  5. +72
    -1
      modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h

+ 2
- 5
examples/audio plugin demo/Source/PluginEditor.cpp View File

@@ -82,9 +82,8 @@ JuceDemoPluginAudioProcessorEditor::JuceDemoPluginAudioProcessorEditor (JuceDemo
timecodeDisplayLabel.setColour (Label::textColourId, Colours::blue); timecodeDisplayLabel.setColour (Label::textColourId, Colours::blue);
timecodeDisplayLabel.setFont (Font (Font::getDefaultMonospacedFontName(), 15.0f, Font::plain)); timecodeDisplayLabel.setFont (Font (Font::getDefaultMonospacedFontName(), 15.0f, Font::plain));
// add the triangular resizer component for the bottom-right of the UI
addAndMakeVisible (resizer = new ResizableCornerComponent (this, &resizeLimits));
resizeLimits.setSizeLimits (150, 150, 800, 300);
// set resize limits for this plug-in
setResizeLimits (400, 200, 800, 300);
// set our component's initial size to be the last one that was stored in the filter's settings // set our component's initial size to be the last one that was stored in the filter's settings
setSize (owner.lastUIWidth, setSize (owner.lastUIWidth,
@@ -120,8 +119,6 @@ void JuceDemoPluginAudioProcessorEditor::resized()
gainSlider->setBounds (sliderArea.removeFromLeft (jmin (180, sliderArea.getWidth() / 2))); gainSlider->setBounds (sliderArea.removeFromLeft (jmin (180, sliderArea.getWidth() / 2)));
delaySlider->setBounds (sliderArea.removeFromLeft (jmin (180, sliderArea.getWidth()))); delaySlider->setBounds (sliderArea.removeFromLeft (jmin (180, sliderArea.getWidth())));
resizer->setBounds (getWidth() - 16, getHeight() - 16, 16, 16);
getProcessor().lastUIWidth = getWidth(); getProcessor().lastUIWidth = getWidth();
getProcessor().lastUIHeight = getHeight(); getProcessor().lastUIHeight = getHeight();
} }


+ 0
- 2
examples/audio plugin demo/Source/PluginEditor.h View File

@@ -36,8 +36,6 @@ private:
MidiKeyboardComponent midiKeyboard; MidiKeyboardComponent midiKeyboard;
Label timecodeDisplayLabel, gainLabel, delayLabel; Label timecodeDisplayLabel, gainLabel, delayLabel;
ScopedPointer<ParameterSlider> gainSlider, delaySlider; ScopedPointer<ParameterSlider> gainSlider, delaySlider;
ScopedPointer<ResizableCornerComponent> resizer;
ComponentBoundsConstrainer resizeLimits;
//============================================================================== //==============================================================================
JuceDemoPluginAudioProcessor& getProcessor() const JuceDemoPluginAudioProcessor& getProcessor() const


+ 23
- 6
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -709,14 +709,30 @@ private:
return kResultFalse; return kResultFalse;
} }
tresult PLUGIN_API canResize() override { return kResultTrue; }
tresult PLUGIN_API canResize() override
{
if (component != nullptr)
if (AudioProcessorEditor* editor = component->pluginEditor)
return editor->isResizable();
return true;
}
tresult PLUGIN_API checkSizeConstraint (ViewRect* rectToCheck) override tresult PLUGIN_API checkSizeConstraint (ViewRect* rectToCheck) override
{ {
if (rectToCheck != nullptr && component != nullptr) if (rectToCheck != nullptr && component != nullptr)
{ {
rectToCheck->right = rectToCheck->left + component->getWidth();
rectToCheck->bottom = rectToCheck->top + component->getHeight();
// checkSizeConstraint
Rectangle<int> juceRect = Rectangle<int>::leftTopRightBottom (rectToCheck->left, rectToCheck->top,
rectToCheck->right, rectToCheck->bottom);
if (AudioProcessorEditor* editor = component->pluginEditor)
if (ComponentBoundsConstrainer* constrainer = editor->getConstrainer())
juceRect.setSize (jlimit (constrainer->getMinimumWidth(), constrainer->getMaximumWidth(), juceRect.getWidth()),
jlimit (constrainer->getMinimumHeight(), constrainer->getMaximumHeight(), juceRect.getHeight()));
rectToCheck->right = rectToCheck->left + juceRect.getWidth();
rectToCheck->bottom = rectToCheck->top + juceRect.getHeight();
return kResultTrue; return kResultTrue;
} }
@@ -730,8 +746,8 @@ private:
{ {
public: public:
ContentWrapperComponent (JuceVST3Editor& editor, AudioProcessor& plugin) ContentWrapperComponent (JuceVST3Editor& editor, AudioProcessor& plugin)
: owner (editor),
pluginEditor (plugin.createEditorIfNeeded())
: pluginEditor (plugin.createEditorIfNeeded()),
owner (editor)
{ {
setOpaque (true); setOpaque (true);
setBroughtToFrontOnMouseClick (true); setBroughtToFrontOnMouseClick (true);
@@ -802,9 +818,10 @@ private:
} }
} }
ScopedPointer<AudioProcessorEditor> pluginEditor;
private: private:
JuceVST3Editor& owner; JuceVST3Editor& owner;
ScopedPointer<AudioProcessorEditor> pluginEditor;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent)
}; };


+ 112
- 2
modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp View File

@@ -22,14 +22,16 @@
============================================================================== ==============================================================================
*/ */
AudioProcessorEditor::AudioProcessorEditor (AudioProcessor& p) noexcept : processor (p)
AudioProcessorEditor::AudioProcessorEditor (AudioProcessor& p) noexcept : processor (p), constrainer (nullptr)
{ {
initialise();
} }
AudioProcessorEditor::AudioProcessorEditor (AudioProcessor* p) noexcept : processor (*p)
AudioProcessorEditor::AudioProcessorEditor (AudioProcessor* p) noexcept : processor (*p), constrainer (nullptr)
{ {
// the filter must be valid.. // the filter must be valid..
jassert (p != nullptr); jassert (p != nullptr);
initialise();
} }
AudioProcessorEditor::~AudioProcessorEditor() AudioProcessorEditor::~AudioProcessorEditor()
@@ -37,7 +39,115 @@ AudioProcessorEditor::~AudioProcessorEditor()
// if this fails, then the wrapper hasn't called editorBeingDeleted() on the // if this fails, then the wrapper hasn't called editorBeingDeleted() on the
// filter for some reason.. // filter for some reason..
jassert (processor.getActiveEditor() != this); jassert (processor.getActiveEditor() != this);
removeComponentListener (resizeListener);
} }
void AudioProcessorEditor::setControlHighlight (ParameterControlHighlightInfo) {} void AudioProcessorEditor::setControlHighlight (ParameterControlHighlightInfo) {}
int AudioProcessorEditor::getControlParameterIndex (Component&) { return -1; } int AudioProcessorEditor::getControlParameterIndex (Component&) { return -1; }
void AudioProcessorEditor::initialise()
{
setConstrainer (&defaultConstrainer);
addComponentListener (resizeListener = new AudioProcessorEditorListener (*this));
}
//==============================================================================
void AudioProcessorEditor::setResizable (const bool shouldBeResizable)
{
if (shouldBeResizable)
{
if (resizableCorner == nullptr)
{
Component::addChildComponent (resizableCorner = new ResizableCornerComponent (this, constrainer));
resizableCorner->setAlwaysOnTop (true);
}
}
else
{
setConstrainer (&defaultConstrainer);
if (getWidth() > 0 && getHeight() > 0)
defaultConstrainer.setSizeLimits (getWidth(), getHeight(), getWidth(), getHeight());
resizableCorner = nullptr;
}
resized();
}
bool AudioProcessorEditor::isResizable() const noexcept
{
return resizableCorner != nullptr;
}
void AudioProcessorEditor::setResizeLimits (const int newMinimumWidth,
const int newMinimumHeight,
const int newMaximumWidth,
const int newMaximumHeight) noexcept
{
// if you've set up a custom constrainer then these settings won't have any effect..
jassert (constrainer == &defaultConstrainer || constrainer == nullptr);
setResizable (newMinimumWidth != newMaximumWidth || newMinimumHeight != newMaximumHeight);
if (constrainer == nullptr)
setConstrainer (&defaultConstrainer);
defaultConstrainer.setSizeLimits (newMinimumWidth, newMinimumHeight,
newMaximumWidth, newMaximumHeight);
setBoundsConstrained (getBounds());
}
void AudioProcessorEditor::setConstrainer (ComponentBoundsConstrainer* newConstrainer)
{
if (constrainer != newConstrainer)
{
constrainer = newConstrainer;
const bool shouldBeResizable = resizableCorner != nullptr;
resizableCorner = nullptr;
setResizable (shouldBeResizable);
if (isOnDesktop())
if (ComponentPeer* const peer = getPeer())
peer->setConstrainer (constrainer);
}
}
void AudioProcessorEditor::setBoundsConstrained (Rectangle<int> newBounds)
{
if (constrainer != nullptr)
constrainer->setBoundsForComponent (this, newBounds, false, false, false, false);
else
setBounds (newBounds);
}
void AudioProcessorEditor::editorResized (bool wasResized)
{
if (wasResized)
{
bool resizerHidden = false;
if (ComponentPeer* peer = getPeer())
resizerHidden = peer->isFullScreen() || peer->isKioskMode();
if (resizableCorner != nullptr)
{
resizableCorner->setVisible (! resizerHidden);
const int resizerSize = 18;
resizableCorner->setBounds (getWidth() - resizerSize,
getHeight() - resizerSize,
resizerSize, resizerSize);
}
else
{
if (getWidth() > 0 && getHeight() > 0)
defaultConstrainer.setSizeLimits (getWidth(), getHeight(),
getWidth(), getHeight());
}
}
}

+ 72
- 1
modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h View File

@@ -25,7 +25,7 @@
#ifndef JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED #ifndef JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED
#define JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED #define JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED
class AudioProcessorEditorListener;
//============================================================================== //==============================================================================
/** /**
Base class for the component that acts as the GUI for an AudioProcessor. Base class for the component that acts as the GUI for an AudioProcessor.
@@ -84,7 +84,78 @@ public:
*/ */
virtual int getControlParameterIndex (Component&); virtual int getControlParameterIndex (Component&);
//==============================================================================
/** Make the editor resizable or fixed.
@param shouldBeResizable whether it's resizable at all
@see setResizeLimits, isResizable
*/
void setResizable (bool shouldBeResizable);
/** Returns true if resizing is enabled.
@see setResizable
*/
bool isResizable() const noexcept;
/** 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.
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.
@see setResizable
*/
void setResizeLimits (int newMinimumWidth,
int newMinimumHeight,
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; }
/** Sets the bounds-constrainer object to use for resizing and dragging this window.
A pointer to the object you pass in will be kept, but it won't be deleted
by this object, so it's the caller's responsibility to manage it.
If you pass a nullptr, then no contraints will be placed on the positioning of the window.
*/
void setConstrainer (ComponentBoundsConstrainer* newConstrainer);
/** Calls the window's setBounds method, after first checking these bounds
with the current constrainer.
@see setConstrainer
*/
void setBoundsConstrained (Rectangle<int> newBounds);
ScopedPointer<ResizableCornerComponent> resizableCorner;
private: private:
//==============================================================================
struct AudioProcessorEditorListener : ComponentListener
{
AudioProcessorEditorListener (AudioProcessorEditor& audioEditor) : e (audioEditor) {}
void componentMovedOrResized (Component&, bool, bool wasResized) override { e.editorResized (wasResized); }
AudioProcessorEditor& e;
};
//==============================================================================
void initialise();
void editorResized (bool wasResized);
//==============================================================================
ScopedPointer<AudioProcessorEditorListener> resizeListener;
ComponentBoundsConstrainer defaultConstrainer;
ComponentBoundsConstrainer* constrainer;
JUCE_DECLARE_NON_COPYABLE (AudioProcessorEditor) JUCE_DECLARE_NON_COPYABLE (AudioProcessorEditor)
}; };


Loading…
Cancel
Save