From 239dc52ce9bfbd88ca56b0fbca9951bb4484c491 Mon Sep 17 00:00:00 2001
From: Septen <gammerxpower@gmail.com>
Date: Tue, 21 Jun 2016 03:54:22 +0400
Subject: [PATCH] Parameters: added possibility to set bounds for each
 parameter. Refactoring.

---
 .../Plugins/LfpDisplayNode/LfpDisplayNode.cpp |   4 +-
 .../LfpDisplayNodeBeta/LfpDisplayNode.cpp     |   4 +-
 Source/Plugins/Rectifier/Rectifier.cpp        |   4 +-
 Source/Processors/Editors/GenericEditor.cpp   |  32 ++--
 .../GenericProcessor/GenericProcessor.cpp     |  31 ++--
 .../GenericProcessor/GenericProcessor.h       |   8 +-
 Source/Processors/Parameter/Parameter.cpp     |  50 +++++-
 Source/Processors/Parameter/Parameter.h       |  24 ++-
 .../Processors/Parameter/ParameterEditor.cpp  | 166 +++++++++++-------
 Source/Processors/Parameter/ParameterEditor.h |  11 +-
 10 files changed, 228 insertions(+), 106 deletions(-)

diff --git a/Source/Plugins/LfpDisplayNode/LfpDisplayNode.cpp b/Source/Plugins/LfpDisplayNode/LfpDisplayNode.cpp
index 222fb2b7c..9eb6172e3 100644
--- a/Source/Plugins/LfpDisplayNode/LfpDisplayNode.cpp
+++ b/Source/Plugins/LfpDisplayNode/LfpDisplayNode.cpp
@@ -142,9 +142,7 @@ void LfpDisplayNode::setParameter (int parameterIndex, float newValue)
 {
     editor->updateParameterButtons (parameterIndex);
     //Sets Parameter in parameters array for processor
-    Parameter* parameterPointer = parameters.getRawDataPointer();
-    parameterPointer = parameterPointer+parameterIndex;
-    parameterPointer->setValue (newValue, currentChannel);
+    parameters[parameterIndex]->setValue (newValue, currentChannel);
 
     //std::cout << "Saving Parameter from " << currentChannel << ", channel ";
 
diff --git a/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp b/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp
index 7b87a33e7..f410a3f10 100644
--- a/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp
+++ b/Source/Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp
@@ -146,9 +146,7 @@ void LfpDisplayNode::setParameter (int parameterIndex, float newValue)
     editor->updateParameterButtons (parameterIndex);
     //
     //Sets Parameter in parameters array for processor
-    Parameter* parameterPointer = parameters.getRawDataPointer();
-    parameterPointer += parameterIndex;
-    parameterPointer->setValue (newValue, currentChannel);
+    parameters[parameterIndex]->setValue (newValue, currentChannel);
 
     //std::cout << "Saving Parameter from " << currentChannel << ", channel ";
 
diff --git a/Source/Plugins/Rectifier/Rectifier.cpp b/Source/Plugins/Rectifier/Rectifier.cpp
index 638a22d44..e2d4c26f8 100644
--- a/Source/Plugins/Rectifier/Rectifier.cpp
+++ b/Source/Plugins/Rectifier/Rectifier.cpp
@@ -47,8 +47,8 @@ void Rectifier::setParameter (int parameterIndex, float newValue)
 
     if (currentChannel >= 0)
     {
-        Parameter& p =  parameters.getReference (parameterIndex);
-        p.setValue (newValue, currentChannel);
+        Parameter* p =  parameters[parameterIndex];
+        p->setValue (newValue, currentChannel);
     }
 }
 
diff --git a/Source/Processors/Editors/GenericEditor.cpp b/Source/Processors/Editors/GenericEditor.cpp
index 3eee68795..f933c9862 100755
--- a/Source/Processors/Editors/GenericEditor.cpp
+++ b/Source/Processors/Editors/GenericEditor.cpp
@@ -137,26 +137,36 @@ void GenericEditor::addParameterEditors(bool useDefaultParameterEditors=true)
 {
     if (useDefaultParameterEditors)
     {
+        const int xPosInitial = 2;
+        const int yPosIntiial = 23;
 
-        int maxX = 15;
-        int maxY = 30;
+        int xPos = 15;
+        int yPos = 30;
 
         // std::cout << "Adding parameter editors." << std::endl;
 
         for (int i = 0; i < getProcessor()->getNumParameters(); i++)
         {
-            ParameterEditor* p = new ParameterEditor(getProcessor(), getProcessor()->getParameterReference(i), titleFont);
+            ParameterEditor* p = new ParameterEditor(getProcessor(), getProcessor()->getParameterObject (i), titleFont);
+            p->setChannelSelector (channelSelector);
 
-            p->setChannelSelector(channelSelector);
-            int dWidth = p->desiredWidth;
-            int dHeight = p->desiredHeight;
+            if (p->hasCustomBounds())
+            {
+                p->setBounds (p->getDesiredBounds().translated (xPosInitial, yPosIntiial));
+            }
+            else
+            {
+                const int dWidth  = p->desiredWidth;
+                const int dHeight = p->desiredHeight;
+
+                p->setBounds (xPos, yPos, dWidth, dHeight);
 
-            p->setBounds(maxX, maxY, dWidth, dHeight);
-            addAndMakeVisible(p);
-            parameterEditors.add(p);
+                yPos += dHeight;
+                yPos += 10;
+            }
 
-            maxY += dHeight;
-            maxY += 10;
+            addAndMakeVisible (p);
+            parameterEditors.add (p);
         }
     }
 }
diff --git a/Source/Processors/GenericProcessor/GenericProcessor.cpp b/Source/Processors/GenericProcessor/GenericProcessor.cpp
index ad9ffd7be..138a795d2 100755
--- a/Source/Processors/GenericProcessor/GenericProcessor.cpp
+++ b/Source/Processors/GenericProcessor/GenericProcessor.cpp
@@ -75,28 +75,28 @@ void GenericProcessor::setNodeId (int id)
 }
 
 
-Parameter& GenericProcessor::getParameterByName (String name_)
+Parameter* GenericProcessor::getParameterByName (String name)
 {
     const int numParameters = getNumParameters();
     // doesn't work
     for (int i = 0; i < numParameters; ++i)
     {
-        Parameter& p =  parameters.getReference (i);
-        const String parameterName = p.getName();
+        const auto parameter = parameters[i];
+        const String parameterName = parameter->getName();
 
-        if (parameterName.compare (name_) == 0) // fails at this point
-            return p;//parameters.getReference(i);
+        if (parameterName.compare (name) == 0) // fails at this point
+            return parameter;//parameters.getReference(i);
     }
 
-    static Parameter nullParam = Parameter ("VOID", false, -1);
+    Parameter* nullParam = new Parameter ("VOID", false, -1);
 
     return nullParam;
 }
 
 
-Parameter& GenericProcessor::getParameterReference (int parameterIndex) const
+Parameter* GenericProcessor::getParameterObject (int parameterIndex) const
 {
-    return parameters.getReference (parameterIndex);
+    return parameters[parameterIndex];
 }
 
 
@@ -106,31 +106,26 @@ void GenericProcessor::setParameter (int parameterIndex, float newValue)
     std::cout << "Setting parameter" << std::endl;
 
     if (currentChannel >= 0)
-    {
-        Parameter& p =  parameters.getReference (parameterIndex);
-        p.setValue (newValue, currentChannel);
-    }
+        parameters[parameterIndex]->setValue (newValue, currentChannel);
 }
 
 
 const String GenericProcessor::getParameterName (int parameterIndex)
 {
-    Parameter& p = parameters.getReference (parameterIndex);
-    return p.getName();
+    return parameters[parameterIndex]->getName();
 }
 
 
 const String GenericProcessor::getParameterText (int parameterIndex)
 {
-    Parameter& p = parameters.getReference (parameterIndex);
-    return p.getDescription();
+    return parameters[parameterIndex]->getDescription();
 }
 
 
 var GenericProcessor::getParameterVar (int parameterIndex, int parameterChannel)
 {
-    Parameter& p = parameters.getReference (parameterIndex);
-    return p.operator[] (parameterChannel);
+    const auto parameter = parameters[parameterIndex];
+    return parameter->operator[] (parameterChannel);
 }
 
 
diff --git a/Source/Processors/GenericProcessor/GenericProcessor.h b/Source/Processors/GenericProcessor/GenericProcessor.h
index af4e1b6f3..3cadb3c92 100755
--- a/Source/Processors/GenericProcessor/GenericProcessor.h
+++ b/Source/Processors/GenericProcessor/GenericProcessor.h
@@ -451,15 +451,15 @@ public:
     int nodeId;
 
     /** An array of parameters that the user can modify.*/
-    Array<Parameter> parameters;
+    OwnedArray<Parameter> parameters;
 
-    /** Returns the parameter for a given name. 
+    /** Returns the parameter for a given name.
         It should be const method ideally, but because JUCE's getNumParameters()
         is non-const method, we can't do this one const.*/
-    Parameter& getParameterByName (String parameterName);
+    Parameter* getParameterByName (String parameterName);
 
     /** Returns the parameter for a given index.*/
-    Parameter& getParameterReference (int parameterIndex) const;
+    Parameter* getParameterObject (int parameterIndex) const;
 
     /** Save generic settings to XML (called by all processors).*/
     void saveToXml (XmlElement* parentElement);
diff --git a/Source/Processors/Parameter/Parameter.cpp b/Source/Processors/Parameter/Parameter.cpp
index 6bff3a04c..0cb030fef 100755
--- a/Source/Processors/Parameter/Parameter.cpp
+++ b/Source/Processors/Parameter/Parameter.cpp
@@ -70,9 +70,6 @@ Parameter::Parameter (const String& name,
 }
 
 
-Parameter::~Parameter() {}
-
-
 const String& Parameter::getName()          const noexcept { return m_name; }
 const String& Parameter::getDescription()   const noexcept { return m_description; }
 
@@ -88,12 +85,43 @@ bool Parameter::isBoolean()     const noexcept { return m_parameterType == PARAM
 bool Parameter::isContinuous()  const noexcept { return m_parameterType == PARAMETER_TYPE_CONTINUOUS; }
 bool Parameter::isDiscrete()    const noexcept { return m_parameterType == PARAMETER_TYPE_DISCRETE; }
 
+bool Parameter::hasCustomEditorBounds() const noexcept { return m_hasCustomEditorBounds; }
+
+const Rectangle<int>& Parameter::getEditorDesiredBounds() const noexcept { return m_editorBounds; }
+
+
+int Parameter::getEditorRecommendedWidth() const noexcept
+{
+    if (isBoolean())
+        return 120;
+    else if (isContinuous())
+        return 80;
+    else if (isDiscrete())
+        return 35 * getPossibleValues().size();
+    else
+        return 0;
+}
+
+
+int Parameter::getEditorRecommendedHeight() const noexcept
+{
+    if (isBoolean())
+        return 25;
+    else if (isContinuous())
+        return 80;
+    else if (isDiscrete())
+        return 30;
+    else
+        return 0;
+}
+
 
 void Parameter::setDescription (const String& description)
 {
     m_description = description;
 }
 
+
 void Parameter::setValue (float value, int channel)
 {
     if (isBoolean())
@@ -111,3 +139,19 @@ void Parameter::setValue (float value, int channel)
         m_values.set (channel, value);
     }
 }
+
+
+void Parameter::setEditorDesiredSize (int desiredWidth, int desiredHeight)
+{
+    m_hasCustomEditorBounds = true;
+
+    m_editorBounds.setSize (desiredWidth, desiredHeight);
+}
+
+
+void Parameter::setEditorDesiredBounds (int x, int y, int width, int height)
+{
+    m_hasCustomEditorBounds = true;
+
+    m_editorBounds.setBounds (x, y, width, height);
+}
diff --git a/Source/Processors/Parameter/Parameter.h b/Source/Processors/Parameter/Parameter.h
index 52e9e1a8d..8eb715148 100755
--- a/Source/Processors/Parameter/Parameter.h
+++ b/Source/Processors/Parameter/Parameter.h
@@ -61,8 +61,6 @@ public:
                int defaultValue, int ID,
                bool deactivateDuringAcquisition = false);
 
-    /** Destructor.*/
-    ~Parameter();
 
     /** Returns the name of the parameter.*/
     const String& getName() const noexcept;
@@ -95,12 +93,30 @@ public:
     /** Returns true if a parameter is discrete, false otherwise.*/
     bool isDiscrete() const noexcept;
 
+    /** Returns true if a user set custom bounds for the possible parameter editor, false otherwise. */
+    bool hasCustomEditorBounds() const noexcept;
+
+    /** Returns the recommended width value for the parameter editor if parameter has it. */
+    int getEditorRecommendedWidth() const noexcept;
+
+    /** Returns the recommended height value for the parameter editor if parameter has it. */
+    int getEditorRecommendedHeight() const noexcept;
+
+    /** Returns the desired bounds for editor if parameter has it. */
+    const Rectangle<int>& getEditorDesiredBounds() const noexcept;
+
     /** Sets the description of the parameter.*/
     void setDescription (const String& desc);
 
     /** Sets the value of a parameter for a given channel.*/
     void setValue (float val, int chan);
 
+    /** Sets desired size for the parameter editor. */
+    void setEditorDesiredSize (int desiredWidth, int desiredHeight);
+
+    /** Sets desired bounds for the parameter editor. */
+    void setEditorDesiredBounds (int x, int y, int width, int height);
+
     /** Certain parameters should not be changed while data acquisition is active.
          This variable indicates whether or not these parameters can be edited.*/
     bool shouldDeactivateDuringAcquisition;
@@ -119,6 +135,10 @@ private:
 
     int m_parameterId;
 
+    bool m_hasCustomEditorBounds { false };
+
+    Rectangle<int> m_editorBounds;
+
     ParameterType m_parameterType;
 
     var m_defaultValue;
diff --git a/Source/Processors/Parameter/ParameterEditor.cpp b/Source/Processors/Parameter/ParameterEditor.cpp
index 82221b289..e25dfe863 100755
--- a/Source/Processors/Parameter/ParameterEditor.cpp
+++ b/Source/Processors/Parameter/ParameterEditor.cpp
@@ -23,87 +23,103 @@
 #include "ParameterEditor.h"
 
 
-ParameterEditor::ParameterEditor (GenericProcessor* processor, Parameter& parameter, Font labelFont)
+static const int FONT_SIZE = 10;
+
+
+ParameterEditor::ParameterEditor (GenericProcessor* processor, Parameter* parameter, Font labelFont)
     : m_activationState     (true)
     , m_processor           (processor)
-    , m_parameter           (&parameter)
+    , m_parameter           (parameter)
 {
-    shouldDeactivateDuringAcquisition = parameter.shouldDeactivateDuringAcquisition;
+    shouldDeactivateDuringAcquisition = parameter->shouldDeactivateDuringAcquisition;
+
+    const bool isParameterHasCustomBounds = parameter->hasCustomEditorBounds();
 
-    if (parameter.isBoolean())
+    // Create label for parameter
+    Label* label = new Label (parameter->getName(), parameter->getName());
+    labelFont.setHeight (FONT_SIZE);
+    label->setColour (Label::textColourId, Colours::darkgrey);
+    label->setFont (labelFont);
+    m_labelsArray.add (label);
+    addAndMakeVisible (label);
+
+    if (parameter->isBoolean())
     {
-        std::cout << "Boolean parameter. Creating checkbox." << std::endl;
+        std::cout << "Boolean parameter-> Creating checkbox." << std::endl;
 
         // create checkbox
-        ParameterCheckbox* pc = new ParameterCheckbox ((bool) parameter.getDefaultValue());
-        pc->setBounds (0, 0, 12, 12);
-        pc->setName (String (parameter.getID()));
+        ParameterCheckbox* pc = new ParameterCheckbox ((bool) parameter->getDefaultValue());
+        pc->setComponentID (String (parameter->getID()));
+        pc->setName (parameter->getName());
         pc->addListener (this);
         m_checkboxArray.add (pc);
         addAndMakeVisible (pc);
 
-        Label* label = new Label (parameter.getName(), parameter.getName());
-        labelFont.setHeight (10);
-        label->setColour (Label::textColourId, Colours::darkgrey);
-        label->setFont (labelFont);
-        label->setBounds (10, 1, 100, 10);
-        m_labelsArray.add (label);
-        addAndMakeVisible (label);
-
-        desiredWidth = 120;
-        desiredHeight = 25;
+        if (isParameterHasCustomBounds)
+        {
+            const auto desiredBounds = getDesiredBounds();
+            const int checkBoxSize = desiredBounds.getHeight();
+            pc->setBounds       (0, 0, checkBoxSize, checkBoxSize);
+            label->setBounds    (checkBoxSize, 0, desiredBounds.getWidth() - checkBoxSize, checkBoxSize);
+        }
+        else
+        {
+            pc->setBounds       (0, 0, 12, 12);
+            label->setBounds    (10, 1, 100, FONT_SIZE);
+            desiredWidth = 120;
+            desiredHeight = 25;
+        }
     }
-    else if (parameter.isContinuous())
+    else if (parameter->isContinuous())
     {
-        std::cout << "Continuous parameter. Creating slider." << std::endl;
+        std::cout << "Continuous parameter-> Creating slider." << std::endl;
 
         // create slider
-        Array<var> possibleValues = parameter.getPossibleValues();
+        Array<var> possibleValues = parameter->getPossibleValues();
         ParameterSlider* ps = new ParameterSlider ((float) possibleValues[0],
                                                    (float) possibleValues[1],
-                                                   (float) parameter.getDefaultValue(),
+                                                   (float) parameter->getDefaultValue(),
                                                    labelFont);
 
-        ps->setBounds (0, 0, 80, 80);
-        ps->setName (String (parameter.getID()));
+        ps->setComponentID (String (parameter->getID()));
+        ps->setName (parameter->getName());
         ps->addListener (this);
         addAndMakeVisible (ps);
         m_sliderArray.add (ps);
 
-        Label* label = new Label (parameter.getName(), parameter.getName());
-        labelFont.setHeight (10);
-        const int width = labelFont.getStringWidth (parameter.getName());
-        label->setColour (Label::textColourId, Colours::darkgrey);
-        label->setFont (labelFont);
-        label->setBounds ((80 - width) / 2 - 5, 70, 100, 10);
-        m_labelsArray.add (label);
-        addAndMakeVisible (label);
-
-        desiredWidth = 80;
-        desiredHeight = 80;
+        const int labelWidth = labelFont.getStringWidth (parameter->getName());
+        if (isParameterHasCustomBounds)
+        {
+            const auto desiredBounds = getDesiredBounds();
+            ps->setBounds       (0, 0, desiredBounds.getWidth(), desiredBounds.getHeight());
+            label->setBounds    ( (desiredBounds.getWidth() - labelWidth) / 2, desiredBounds.getHeight() - FONT_SIZE,
+                                  labelWidth, FONT_SIZE);
+        }
+        else
+        {
+            ps->setBounds (0, 0, 80, 80);
+
+            label->setBounds ((80 - labelWidth) / 2 - 5, 70, 100, FONT_SIZE);
+
+            desiredWidth = 80;
+            desiredHeight = 80;
+        }
     }
-    else if (parameter.isDiscrete())
+    else if (parameter->isDiscrete())
     {
-        std::cout << "Discrete parameter. Creating buttons." << std::endl;
+        std::cout << "Discrete parameter-> Creating buttons." << std::endl;
 
-        // create buttons
-        Label* label = new Label (parameter.getName(), parameter.getName());
-        labelFont.setHeight (10);
-        label->setColour (Label::textColourId, Colours::darkgrey);
-        label->setFont (labelFont);
-        label->setBounds (0, 0, 100, 10);
-        m_labelsArray.add (label);
-        addAndMakeVisible (label);
 
-        Array<var> possibleValues = parameter.getPossibleValues();
+        Array<var> possibleValues = parameter->getPossibleValues();
 
-        int buttonWidth = 35;
+        const int numButtons  = possibleValues.size();
+        const int buttonWidth = isParameterHasCustomBounds ? (m_parameter->getEditorDesiredBounds().getWidth() / numButtons)
+                                                           : 35;
 
         std::cout << "Button width: " << buttonWidth << std::endl;
-        std::cout << "Default value: " << (int) parameter.getDefaultValue() << std::endl;
+        std::cout << "Default value: " << (int) parameter->getDefaultValue() << std::endl;
 
-        int i = 0;
-        for (; i < possibleValues.size(); ++i)
+        for (int i = 0; i < numButtons; ++i)
         {
             std::cout << "Creating button " << i << std::endl;
 
@@ -113,20 +129,39 @@ ParameterEditor::ParameterEditor (GenericProcessor* processor, Parameter& parame
             else if (i == possibleValues.size() - 1)
                 buttonType = RIGHT;
 
+            // create buttons
             ParameterButton* pb = new ParameterButton (possibleValues[i], buttonType, labelFont);
-            pb->setBounds (buttonWidth * i, 12, buttonWidth, 18);
-            pb->setName (String (parameter.getID()));
+            pb->setComponentID (String (parameter->getID()));
+            pb->setName (parameter->getName());
             pb->addListener (this);
             m_buttonArray.add (pb);
 
-            if (i == (int) parameter.getDefaultValue())
+            if (isParameterHasCustomBounds)
+            {
+                pb->setBounds (buttonWidth * i, 12, buttonWidth, getDesiredBounds().getHeight() - FONT_SIZE);
+            }
+            else
+            {
+                pb->setBounds (buttonWidth * i, 12, buttonWidth, 18);
+            }
+
+            if (i == (int) parameter->getDefaultValue())
                 pb->setToggleState (true, dontSendNotification);
 
             addAndMakeVisible (pb);
         }
 
-        desiredWidth = buttonWidth * i;
-        desiredHeight = 30;
+        if (isParameterHasCustomBounds)
+        {
+            label->setBounds (0, 0, getDesiredBounds().getWidth(), FONT_SIZE);
+        }
+        else
+        {
+            label->setBounds (0, 0, 100, FONT_SIZE);
+
+            desiredWidth = buttonWidth * numButtons;
+            desiredHeight = 30;
+        }
     }
 }
 
@@ -174,8 +209,9 @@ void ParameterEditor::setEnabled (bool isEnabled)
 
 void ParameterEditor::buttonClicked (Button* buttonThatWasClicked)
 {
-    std::cout << "Button name: " << buttonThatWasClicked->getName() << std::endl;
-    std::cout << "Button value: " << buttonThatWasClicked->getButtonText() << std::endl;
+    std::cout << "Button ID: "      << buttonThatWasClicked->getComponentID()   << std::endl;
+    std::cout << "Button name: "    << buttonThatWasClicked->getName()          << std::endl;
+    std::cout << "Button value: "   << buttonThatWasClicked->getButtonText()    << std::endl;
 
     ParameterButton* b = (ParameterButton*) buttonThatWasClicked;
 
@@ -186,7 +222,7 @@ void ParameterEditor::buttonClicked (Button* buttonThatWasClicked)
             for (int i = 0; i < activeChannels.size(); ++i)
             {
                 m_processor->setCurrentChannel (activeChannels[i]);
-                m_processor->setParameter (buttonThatWasClicked->getName().getIntValue(),
+                m_processor->setParameter (buttonThatWasClicked->getComponentID().getIntValue(),
                                            buttonThatWasClicked->getButtonText().getFloatValue());
             }
         }
@@ -205,7 +241,7 @@ void ParameterEditor::sliderValueChanged (Slider* sliderWhichValueHasChanged)
             for (int i = 0; i < activeChannels.size(); ++i)
             {
                 m_processor->setCurrentChannel (activeChannels[i]);
-                m_processor->setParameter (sliderWhichValueHasChanged->getName().getIntValue(),
+                m_processor->setParameter (sliderWhichValueHasChanged->getComponentID().getIntValue(),
                                            sliderWhichValueHasChanged->getValue());
             }
         }
@@ -468,3 +504,15 @@ void ParameterEditor::updateChannelSelectionUI()
         }
     }
 }
+
+
+bool ParameterEditor::hasCustomBounds() const noexcept
+{
+    return m_parameter->hasCustomEditorBounds();
+}
+
+
+const Rectangle<int>& ParameterEditor::getDesiredBounds() const noexcept
+{
+    return m_parameter->getEditorDesiredBounds();
+}
diff --git a/Source/Processors/Parameter/ParameterEditor.h b/Source/Processors/Parameter/ParameterEditor.h
index 046d342d8..004c33638 100755
--- a/Source/Processors/Parameter/ParameterEditor.h
+++ b/Source/Processors/Parameter/ParameterEditor.h
@@ -46,7 +46,14 @@ class PLUGIN_API ParameterEditor : public Component
                                  , public Slider::Listener
 {
 public:
-    ParameterEditor (GenericProcessor* proccessor, Parameter& parameter, Font labelFont);
+    ParameterEditor (GenericProcessor* proccessor, Parameter* parameter, Font labelFont);
+
+    /** Returns true if the editor should be treated as standalone and should
+        have his own custom bounds. */
+    bool hasCustomBounds() const noexcept;
+
+    /** Returns the desired bounds for editor. */
+    const Rectangle<int>& getDesiredBounds() const noexcept;
 
     void parentHierarchyChanged() override;
 
@@ -81,6 +88,8 @@ private:
     Array<int> m_sliderIdArray;
     Array<int> m_checkboxIdArray;
 
+    Rectangle<int> m_desiredBounds;
+
     enum
     {
         LEFT,
-- 
GitLab