diff --git a/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp b/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp index d5d03ce29a..efe17046a3 100644 --- a/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp +++ b/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp @@ -27,11 +27,11 @@ namespace juce { //============================================================================== -class ChoicePropertyComponent::RemapperValueSource : public Value::ValueSource, - private Value::Listener +class ChoiceRemapperValueSource : public Value::ValueSource, + private Value::Listener { public: - RemapperValueSource (const Value& source, const Array& map) + ChoiceRemapperValueSource (const Value& source, const Array& map) : sourceValue (source), mappings (map) { @@ -64,17 +64,17 @@ protected: void valueChanged (Value&) override { sendChangeMessage (true); } //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSource) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoiceRemapperValueSource) }; //============================================================================== -class ChoicePropertyComponent::RemapperValueSourceWithDefault : public Value::ValueSource, - private Value::Listener +class ChoiceRemapperValueSourceWithDefault : public Value::ValueSource, + private Value::Listener { public: - RemapperValueSourceWithDefault (ValueWithDefault* vwd, const Array& map) - : valueWithDefault (vwd), - sourceValue (valueWithDefault->getPropertyAsValue()), + ChoiceRemapperValueSourceWithDefault (const ValueTreePropertyWithDefault& v, const Array& map) + : value (v), + sourceValue (value.getPropertyAsValue()), mappings (map) { sourceValue.addListener (this); @@ -82,7 +82,7 @@ public: var getValue() const override { - if (valueWithDefault != nullptr && ! valueWithDefault->isUsingDefault()) + if (! value.isUsingDefault()) { const auto target = sourceValue.getValue(); const auto equalsWithSameType = [&target] (const var& map) { return map.equalsWithSameType (target); }; @@ -101,33 +101,30 @@ public: void setValue (const var& newValue) override { - if (valueWithDefault == nullptr) - return; - auto newValueInt = static_cast (newValue); if (newValueInt == -1) { - valueWithDefault->resetToDefault(); + value.resetToDefault(); } else { auto remappedVal = mappings [newValueInt - 1]; if (! remappedVal.equalsWithSameType (sourceValue)) - *valueWithDefault = remappedVal; + value = remappedVal; } } private: void valueChanged (Value&) override { sendChangeMessage (true); } - WeakReference valueWithDefault; + ValueTreePropertyWithDefault value; Value sourceValue; Array mappings; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSourceWithDefault) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoiceRemapperValueSourceWithDefault) }; //============================================================================== @@ -155,23 +152,23 @@ ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl, : ChoicePropertyComponent (name, choiceList, correspondingValues) { refreshChoices(); - initialiseComboBox (Value (new RemapperValueSource (valueToControl, correspondingValues))); + initialiseComboBox (Value (new ChoiceRemapperValueSource (valueToControl, correspondingValues))); } -ChoicePropertyComponent::ChoicePropertyComponent (ValueWithDefault& valueToControl, +ChoicePropertyComponent::ChoicePropertyComponent (const ValueTreePropertyWithDefault& valueToControl, const String& name, const StringArray& choiceList, const Array& correspondingValues) : ChoicePropertyComponent (name, choiceList, correspondingValues) { - valueWithDefault = &valueToControl; + value = valueToControl; - auto getDefaultString = [this, correspondingValues] { return choices [correspondingValues.indexOf (valueWithDefault->getDefault())]; }; + auto getDefaultString = [this, correspondingValues] { return choices [correspondingValues.indexOf (value.getDefault())]; }; refreshChoices (getDefaultString()); - initialiseComboBox (Value (new RemapperValueSourceWithDefault (valueWithDefault, correspondingValues))); + initialiseComboBox (Value (new ChoiceRemapperValueSourceWithDefault (value, correspondingValues))); - valueWithDefault->onDefaultChange = [this, getDefaultString] + value.onDefaultChange = [this, getDefaultString] { auto selectedId = comboBox.getSelectedId(); refreshChoices (getDefaultString()); @@ -179,19 +176,19 @@ ChoicePropertyComponent::ChoicePropertyComponent (ValueWithDefault& valueToContr }; } -ChoicePropertyComponent::ChoicePropertyComponent (ValueWithDefault& valueToControl, +ChoicePropertyComponent::ChoicePropertyComponent (const ValueTreePropertyWithDefault& valueToControl, const String& name) : PropertyComponent (name), choices ({ "Enabled", "Disabled" }) { - valueWithDefault = &valueToControl; + value = valueToControl; - auto getDefaultString = [this] { return valueWithDefault->getDefault() ? "Enabled" : "Disabled"; }; + auto getDefaultString = [this] { return value.getDefault() ? "Enabled" : "Disabled"; }; refreshChoices (getDefaultString()); - initialiseComboBox (Value (new RemapperValueSourceWithDefault (valueWithDefault, { true, false }))); + initialiseComboBox (Value (new ChoiceRemapperValueSourceWithDefault (value, { true, false }))); - valueWithDefault->onDefaultChange = [this, getDefaultString] + value.onDefaultChange = [this, getDefaultString] { auto selectedId = comboBox.getSelectedId(); refreshChoices (getDefaultString()); @@ -199,12 +196,6 @@ ChoicePropertyComponent::ChoicePropertyComponent (ValueWithDefault& valueToContr }; } -ChoicePropertyComponent::~ChoicePropertyComponent() -{ - if (valueWithDefault != nullptr) - valueWithDefault->onDefaultChange = nullptr; -} - //============================================================================== void ChoicePropertyComponent::initialiseComboBox (const Value& v) { diff --git a/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h b/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h index 4b1ee39ef1..d616ce1516 100644 --- a/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h +++ b/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h @@ -79,34 +79,30 @@ public: const StringArray& choices, const Array& correspondingValues); - /** Creates the component using a ValueWithDefault object. This will add an item to the ComboBox for the + /** Creates the component using a ValueTreePropertyWithDefault object. This will add an item to the ComboBox for the default value with an ID of -1. - @param valueToControl the ValueWithDefault object that contains the Value object that the combo box will read and control. + @param valueToControl the ValueTreePropertyWithDefault object that contains the Value object that the combo box will read and control. @param propertyName the name of the property @param choices the list of possible values that the drop-down list will contain @param correspondingValues a list of values corresponding to each item in the 'choices' StringArray. These are the values that will be read and written to the valueToControl value. This array must contain the same number of items as the choices array - */ - ChoicePropertyComponent (ValueWithDefault& valueToControl, + ChoicePropertyComponent (const ValueTreePropertyWithDefault& valueToControl, const String& propertyName, const StringArray& choices, const Array& correspondingValues); - /** Creates the component using a ValueWithDefault object, adding an item to the ComboBox for the + /** Creates the component using a ValueTreePropertyWithDefault object, adding an item to the ComboBox for the default value with an ID of -1 as well as adding separate "Enabled" and "Disabled" options. This is useful for simple on/off choices that also need a default value. */ - ChoicePropertyComponent (ValueWithDefault& valueToControl, + ChoicePropertyComponent (const ValueTreePropertyWithDefault& valueToControl, const String& propertyName); - /** Destructor. */ - ~ChoicePropertyComponent() override; - //============================================================================== /** Called when the user selects an item from the combo box. @@ -138,10 +134,6 @@ protected: StringArray choices; private: - //============================================================================== - class RemapperValueSource; - class RemapperValueSourceWithDefault; - //============================================================================== void initialiseComboBox (const Value&); void refreshChoices(); @@ -150,11 +142,10 @@ private: void changeIndex(); //============================================================================== + ValueTreePropertyWithDefault value; ComboBox comboBox; bool isCustomClass = false; - WeakReference valueWithDefault; - //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoicePropertyComponent) }; diff --git a/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.cpp b/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.cpp index 2fe93e39ea..e8a872a5a0 100644 --- a/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.cpp +++ b/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.cpp @@ -111,10 +111,11 @@ class MultiChoicePropertyComponent::MultiChoiceRemapperSourceWithDefault : pu private Value::Listener { public: - MultiChoiceRemapperSourceWithDefault (ValueWithDefault* vwd, var v, int c, ToggleButton* b) - : valueWithDefault (vwd), + MultiChoiceRemapperSourceWithDefault (const ValueTreePropertyWithDefault& val, + var v, int c, ToggleButton* b) + : value (val), varToControl (v), - sourceValue (valueWithDefault->getPropertyAsValue()), + sourceValue (value.getPropertyAsValue()), maxChoices (c), buttonToControl (b) { @@ -123,16 +124,13 @@ public: var getValue() const override { - if (valueWithDefault == nullptr) - return {}; - - auto v = valueWithDefault->get(); + auto v = value.get(); if (auto* arr = v.getArray()) { if (arr->contains (varToControl)) { - updateButtonTickColour (buttonToControl, valueWithDefault->isUsingDefault()); + updateButtonTickColour (buttonToControl, value.isUsingDefault()); return true; } } @@ -142,14 +140,11 @@ public: void setValue (const var& newValue) override { - if (valueWithDefault == nullptr) - return; - - auto v = valueWithDefault->get(); + auto v = value.get(); OptionalScopedPointer> arrayToControl; - if (valueWithDefault->isUsingDefault()) + if (value.isUsingDefault()) arrayToControl.set (new Array(), true); // use an empty array so the default values are overwritten else arrayToControl.set (v.getArray(), false); @@ -160,7 +155,7 @@ public: bool newState = newValue; - if (valueWithDefault->isUsingDefault()) + if (value.isUsingDefault()) { if (auto* defaultArray = v.getArray()) { @@ -182,10 +177,10 @@ public: StringComparator c; temp.sort (c); - *valueWithDefault = temp; + value = temp; if (temp.size() == 0) - valueWithDefault->resetToDefault(); + value.resetToDefault(); } } @@ -194,7 +189,7 @@ private: void valueChanged (Value&) override { sendChangeMessage (true); } //============================================================================== - WeakReference valueWithDefault; + ValueTreePropertyWithDefault value; var varToControl; Value sourceValue; @@ -215,7 +210,7 @@ int MultiChoicePropertyComponent::getTotalButtonsHeight (int numButtons) MultiChoicePropertyComponent::MultiChoicePropertyComponent (const String& propertyName, const StringArray& choices, const Array& correspondingValues) -: PropertyComponent (propertyName, jmin (getTotalButtonsHeight (choices.size()), collapsedHeight)) + : PropertyComponent (propertyName, jmin (getTotalButtonsHeight (choices.size()), collapsedHeight)) { // The array of corresponding values must contain one value for each of the items in // the choices array! @@ -261,31 +256,25 @@ MultiChoicePropertyComponent::MultiChoicePropertyComponent (const Value& valueTo maxChoices))); } -MultiChoicePropertyComponent::MultiChoicePropertyComponent (ValueWithDefault& valueToControl, +MultiChoicePropertyComponent::MultiChoicePropertyComponent (const ValueTreePropertyWithDefault& valueToControl, const String& propertyName, const StringArray& choices, const Array& correspondingValues, int maxChoices) : MultiChoicePropertyComponent (propertyName, choices, correspondingValues) { - valueWithDefault = &valueToControl; + value = valueToControl; // The value to control must be an array! - jassert (valueWithDefault->get().isArray()); + jassert (value.get().isArray()); for (int i = 0; i < choiceButtons.size(); ++i) - choiceButtons[i]->getToggleStateValue().referTo (Value (new MultiChoiceRemapperSourceWithDefault (valueWithDefault, + choiceButtons[i]->getToggleStateValue().referTo (Value (new MultiChoiceRemapperSourceWithDefault (value, correspondingValues[i], maxChoices, choiceButtons[i]))); - valueWithDefault->onDefaultChange = [this] { repaint(); }; -} - -MultiChoicePropertyComponent::~MultiChoicePropertyComponent() -{ - if (valueWithDefault != nullptr) - valueWithDefault->onDefaultChange = nullptr; + value.onDefaultChange = [this] { repaint(); }; } void MultiChoicePropertyComponent::paint (Graphics& g) @@ -361,13 +350,10 @@ void MultiChoicePropertyComponent::lookAndFeelChanged() auto iconColour = findColour (TextEditor::backgroundColourId).contrasting(); expandButton.setColours (iconColour, iconColour.darker(), iconColour.darker()); - if (valueWithDefault != nullptr) - { - auto usingDefault = valueWithDefault->isUsingDefault(); + const auto usingDefault = value.isUsingDefault(); - for (auto* button : choiceButtons) - updateButtonTickColour (button, usingDefault); - } + for (auto* button : choiceButtons) + updateButtonTickColour (button, usingDefault); } } // namespace juce diff --git a/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h b/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h index 168ad9b6bd..a26d31740d 100644 --- a/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h +++ b/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h @@ -63,9 +63,9 @@ public: const Array& correspondingValues, int maxChoices = -1); - /** Creates the component using a ValueWithDefault object. This will select the default options. + /** Creates the component using a ValueTreePropertyWithDefault object. This will select the default options. - @param valueToControl the ValueWithDefault object that contains the Value object that the ToggleButtons will read and control. + @param valueToControl the ValueTreePropertyWithDefault object that contains the Value object that the ToggleButtons will read and control. @param propertyName the name of the property @param choices the list of possible values that will be represented @param correspondingValues a list of values corresponding to each item in the 'choices' StringArray. @@ -75,14 +75,12 @@ public: @param maxChoices the maximum number of values which can be selected at once. The default of -1 will not limit the number that can be selected */ - MultiChoicePropertyComponent (ValueWithDefault& valueToControl, + MultiChoicePropertyComponent (const ValueTreePropertyWithDefault& valueToControl, const String& propertyName, const StringArray& choices, const Array& correspondingValues, int maxChoices = -1); - ~MultiChoicePropertyComponent() override; - //============================================================================== /** Returns true if the list of options is expanded. */ bool isExpanded() const noexcept { return expanded; } @@ -100,7 +98,11 @@ public: */ void setExpanded (bool expanded) noexcept; - /** You can assign a lambda to this callback object to have it called when the MultiChoicePropertyComponent height changes. */ + /** You can assign a lambda to this callback object to have it called when the + height of this component changes in response to being expanded/collapsed. + + @see setExpanded + */ std::function onHeightChange; //============================================================================== @@ -121,8 +123,6 @@ private: void lookAndFeelChanged() override; //============================================================================== - WeakReference valueWithDefault; - static constexpr int collapsedHeight = 125; static constexpr int buttonHeight = 25; static constexpr int expandAreaHeight = 20; @@ -130,6 +130,7 @@ private: int maxHeight = 0, numHidden = 0; bool expandable = false, expanded = false; + ValueTreePropertyWithDefault value; OwnedArray choiceButtons; ShapeButton expandButton { "Expand", Colours::transparentBlack, Colours::transparentBlack, Colours::transparentBlack }; diff --git a/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp b/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp index fdc99d9138..08c8ad93db 100644 --- a/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp +++ b/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp @@ -120,38 +120,38 @@ private: }; //============================================================================== -class TextPropertyComponent::RemapperValueSourceWithDefault : public Value::ValueSource +class TextRemapperValueSourceWithDefault : public Value::ValueSource { public: - RemapperValueSourceWithDefault (ValueWithDefault* vwd) - : valueWithDefault (vwd) + TextRemapperValueSourceWithDefault (const ValueTreePropertyWithDefault& v) + : value (v) { } var getValue() const override { - if (valueWithDefault == nullptr || valueWithDefault->isUsingDefault()) + if (value.isUsingDefault()) return {}; - return valueWithDefault->get(); + return value.get(); } void setValue (const var& newValue) override { - if (valueWithDefault == nullptr) - return; - if (newValue.toString().isEmpty()) - valueWithDefault->resetToDefault(); - else - *valueWithDefault = newValue; + { + value.resetToDefault(); + return; + } + + value = newValue; } private: - WeakReference valueWithDefault; + ValueTreePropertyWithDefault value; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSourceWithDefault) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextRemapperValueSourceWithDefault) }; //============================================================================== @@ -172,27 +172,23 @@ TextPropertyComponent::TextPropertyComponent (const Value& valueToControl, const textEditor->getTextValue().referTo (valueToControl); } -TextPropertyComponent::TextPropertyComponent (ValueWithDefault& valueToControl, const String& name, +TextPropertyComponent::TextPropertyComponent (const ValueTreePropertyWithDefault& valueToControl, const String& name, int maxNumChars, bool multiLine, bool isEditable) : TextPropertyComponent (name, maxNumChars, multiLine, isEditable) { - valueWithDefault = &valueToControl; + value = valueToControl; - textEditor->getTextValue().referTo (Value (new RemapperValueSourceWithDefault (valueWithDefault))); - textEditor->setTextToDisplayWhenEmpty (valueWithDefault->getDefault(), 0.5f); + textEditor->getTextValue().referTo (Value (new TextRemapperValueSourceWithDefault (value))); + textEditor->setTextToDisplayWhenEmpty (value.getDefault(), 0.5f); - valueWithDefault->onDefaultChange = [this] + value.onDefaultChange = [this] { - textEditor->setTextToDisplayWhenEmpty (valueWithDefault->getDefault(), 0.5f); + textEditor->setTextToDisplayWhenEmpty (value.getDefault(), 0.5f); repaint(); }; } -TextPropertyComponent::~TextPropertyComponent() -{ - if (valueWithDefault != nullptr) - valueWithDefault->onDefaultChange = nullptr; -} +TextPropertyComponent::~TextPropertyComponent() {} void TextPropertyComponent::setText (const String& newText) { diff --git a/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h b/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h index e0b0292f96..5f3fe448a0 100644 --- a/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h +++ b/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h @@ -73,7 +73,7 @@ public: /** Creates a text property component with a default value. - @param valueToControl The ValueWithDefault that is controlled by the TextPropertyComponent. + @param valueToControl The ValueTreePropertyWithDefault that is controlled by the TextPropertyComponent. @param propertyName The name of the property @param maxNumChars If not zero, then this specifies the maximum allowable length of the string. If zero, then the string will have no length limit. @@ -82,13 +82,12 @@ public: @see TextEditor, setEditable */ - TextPropertyComponent (ValueWithDefault& valueToControl, + TextPropertyComponent (const ValueTreePropertyWithDefault& valueToControl, const String& propertyName, int maxNumChars, bool isMultiLine, bool isEditable = true); - /** Destructor. */ ~TextPropertyComponent() override; //============================================================================== @@ -167,22 +166,19 @@ public: virtual void textWasEdited(); private: - class RemapperValueSourceWithDefault; - class LabelComp; - friend class LabelComp; - //============================================================================== void callListeners(); void createEditor (int maxNumChars, bool isEditable); //============================================================================== - bool isMultiLine; + class LabelComp; + const bool isMultiLine; + + ValueTreePropertyWithDefault value; std::unique_ptr textEditor; ListenerList listenerList; - WeakReference valueWithDefault; - //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextPropertyComponent) };