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 (¶meter) + , 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