mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Add options to make AuidoProcessorEditors resizable with constraints
This commit is contained in:
parent
25f8faf8d3
commit
ebb0a156a4
5 changed files with 209 additions and 16 deletions
|
|
@ -82,9 +82,8 @@ JuceDemoPluginAudioProcessorEditor::JuceDemoPluginAudioProcessorEditor (JuceDemo
|
|||
timecodeDisplayLabel.setColour (Label::textColourId, Colours::blue);
|
||||
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
|
||||
setSize (owner.lastUIWidth,
|
||||
|
|
@ -120,8 +119,6 @@ void JuceDemoPluginAudioProcessorEditor::resized()
|
|||
gainSlider->setBounds (sliderArea.removeFromLeft (jmin (180, sliderArea.getWidth() / 2)));
|
||||
delaySlider->setBounds (sliderArea.removeFromLeft (jmin (180, sliderArea.getWidth())));
|
||||
|
||||
resizer->setBounds (getWidth() - 16, getHeight() - 16, 16, 16);
|
||||
|
||||
getProcessor().lastUIWidth = getWidth();
|
||||
getProcessor().lastUIHeight = getHeight();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@ private:
|
|||
MidiKeyboardComponent midiKeyboard;
|
||||
Label timecodeDisplayLabel, gainLabel, delayLabel;
|
||||
ScopedPointer<ParameterSlider> gainSlider, delaySlider;
|
||||
ScopedPointer<ResizableCornerComponent> resizer;
|
||||
ComponentBoundsConstrainer resizeLimits;
|
||||
|
||||
//==============================================================================
|
||||
JuceDemoPluginAudioProcessor& getProcessor() const
|
||||
|
|
|
|||
|
|
@ -709,14 +709,30 @@ private:
|
|||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -730,8 +746,8 @@ private:
|
|||
{
|
||||
public:
|
||||
ContentWrapperComponent (JuceVST3Editor& editor, AudioProcessor& plugin)
|
||||
: owner (editor),
|
||||
pluginEditor (plugin.createEditorIfNeeded())
|
||||
: pluginEditor (plugin.createEditorIfNeeded()),
|
||||
owner (editor)
|
||||
{
|
||||
setOpaque (true);
|
||||
setBroughtToFrontOnMouseClick (true);
|
||||
|
|
@ -802,9 +818,10 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
ScopedPointer<AudioProcessorEditor> pluginEditor;
|
||||
|
||||
private:
|
||||
JuceVST3Editor& owner;
|
||||
ScopedPointer<AudioProcessorEditor> pluginEditor;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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..
|
||||
jassert (p != nullptr);
|
||||
initialise();
|
||||
}
|
||||
|
||||
AudioProcessorEditor::~AudioProcessorEditor()
|
||||
|
|
@ -37,7 +39,115 @@ AudioProcessorEditor::~AudioProcessorEditor()
|
|||
// if this fails, then the wrapper hasn't called editorBeingDeleted() on the
|
||||
// filter for some reason..
|
||||
jassert (processor.getActiveEditor() != this);
|
||||
removeComponentListener (resizeListener);
|
||||
}
|
||||
|
||||
void AudioProcessorEditor::setControlHighlight (ParameterControlHighlightInfo) {}
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#ifndef JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED
|
||||
#define JUCE_AUDIOPROCESSOREDITOR_H_INCLUDED
|
||||
|
||||
|
||||
class AudioProcessorEditorListener;
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for the component that acts as the GUI for an AudioProcessor.
|
||||
|
|
@ -84,7 +84,78 @@ public:
|
|||
*/
|
||||
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:
|
||||
//==============================================================================
|
||||
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)
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue