| @@ -60,5 +60,6 @@ | |||||
| #include "values/juce_ValueTree.h" | #include "values/juce_ValueTree.h" | ||||
| #include "values/juce_ValueTreeSynchroniser.h" | #include "values/juce_ValueTreeSynchroniser.h" | ||||
| #include "values/juce_CachedValue.h" | #include "values/juce_CachedValue.h" | ||||
| #include "values/juce_ValueWithDefault.h" | |||||
| #include "app_properties/juce_PropertiesFile.h" | #include "app_properties/juce_PropertiesFile.h" | ||||
| #include "app_properties/juce_ApplicationProperties.h" | #include "app_properties/juce_ApplicationProperties.h" | ||||
| @@ -0,0 +1,163 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library. | |||||
| Copyright (c) 2017 - ROLI Ltd. | |||||
| JUCE is an open source library subject to commercial or open-source | |||||
| licensing. | |||||
| By using JUCE, you agree to the terms of both the JUCE 5 End-User License | |||||
| Agreement and JUCE 5 Privacy Policy (both updated and effective as of the | |||||
| 27th April 2017). | |||||
| End User License Agreement: www.juce.com/juce-5-licence | |||||
| Privacy Policy: www.juce.com/juce-5-privacy-policy | |||||
| Or: You may also use this code under the terms of the GPL v3 (see | |||||
| www.gnu.org/licenses). | |||||
| JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER | |||||
| EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE | |||||
| DISCLAIMED. | |||||
| ============================================================================== | |||||
| */ | |||||
| namespace juce | |||||
| { | |||||
| //============================================================================== | |||||
| /** | |||||
| This class acts as a wrapper around a property inside a ValueTree. | |||||
| If the property inside the ValueTree is missing or empty the ValueWithDefault will automatically | |||||
| return a default value, which can be specified when initialising the ValueWithDefault. | |||||
| */ | |||||
| class ValueWithDefault | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** Creates an unitialised ValueWithDefault. Initialise it using one of the referTo() methods. */ | |||||
| ValueWithDefault() : undoManager (nullptr) {} | |||||
| /** Creates an ValueWithDefault object. The default value will be an empty var. */ | |||||
| ValueWithDefault (ValueTree& tree, const Identifier& propertyID, | |||||
| UndoManager* um) | |||||
| : targetTree (tree), | |||||
| targetProperty (propertyID), | |||||
| undoManager (um), | |||||
| defaultValue() | |||||
| { | |||||
| } | |||||
| /** Creates an ValueWithDefault object. The default value will be defaultToUse. */ | |||||
| ValueWithDefault (ValueTree& tree, const Identifier& propertyID, | |||||
| UndoManager* um, const var& defaultToUse) | |||||
| : targetTree (tree), | |||||
| targetProperty (propertyID), | |||||
| undoManager (um), | |||||
| defaultValue (defaultToUse) | |||||
| { | |||||
| } | |||||
| /** Creates a ValueWithDefault object from another ValueWithDefault object. */ | |||||
| ValueWithDefault (const ValueWithDefault& other) | |||||
| : targetTree (other.targetTree), | |||||
| targetProperty (other.targetProperty), | |||||
| undoManager (other.undoManager), | |||||
| defaultValue (other.defaultValue) | |||||
| { | |||||
| } | |||||
| //============================================================================== | |||||
| /** Returns the current value of the property. If the property does not exist or is empty, | |||||
| returns the default value. | |||||
| */ | |||||
| var get() const noexcept | |||||
| { | |||||
| if (isUsingDefault()) | |||||
| return defaultValue; | |||||
| return targetTree[targetProperty]; | |||||
| } | |||||
| /** Returns the current property as a Value object. */ | |||||
| Value getPropertyAsValue() { return targetTree.getPropertyAsValue (targetProperty, undoManager); } | |||||
| /** Returns the current default value. */ | |||||
| var getDefault() const { return defaultValue; } | |||||
| /** Sets the default value to a new var. */ | |||||
| void setDefault (const var& newDefault) | |||||
| { | |||||
| if (defaultValue != newDefault) | |||||
| defaultValue = newDefault; | |||||
| } | |||||
| /** Returns true if the property does not exist or is empty. */ | |||||
| bool isUsingDefault() const | |||||
| { | |||||
| return ! targetTree.hasProperty (targetProperty); | |||||
| } | |||||
| /** Resets the property to an empty var. */ | |||||
| void resetToDefault() noexcept | |||||
| { | |||||
| targetTree.removeProperty (targetProperty, nullptr); | |||||
| } | |||||
| //============================================================================== | |||||
| /** Sets the property and returns the new ValueWithDefault. This will modify the property in the referenced ValueTree. */ | |||||
| ValueWithDefault& operator= (const var& newValue) | |||||
| { | |||||
| setValue (newValue, undoManager); | |||||
| return *this; | |||||
| } | |||||
| /** Sets the property. This will actually modify the property in the referenced ValueTree. */ | |||||
| void setValue (const var& newValue, UndoManager* undoManagerToUse) | |||||
| { | |||||
| targetTree.setProperty (targetProperty, newValue, undoManagerToUse); | |||||
| } | |||||
| //============================================================================== | |||||
| /** Makes the ValueWithDefault refer to the specified property inside the given ValueTree. */ | |||||
| void referTo (ValueTree& tree, const Identifier& property, UndoManager* um) | |||||
| { | |||||
| referToWithDefault (tree, property, um, var()); | |||||
| } | |||||
| /** Makes the ValueWithDefault refer to the specified property inside the given ValueTree, | |||||
| and specifies a default value to use. | |||||
| */ | |||||
| void referTo (ValueTree& tree, const Identifier& property, UndoManager* um, const var& defaultVal) | |||||
| { | |||||
| referToWithDefault (tree, property, um, defaultVal); | |||||
| } | |||||
| //============================================================================== | |||||
| /** Returns a reference to the ValueTree containing the referenced property. */ | |||||
| ValueTree& getValueTree() noexcept { return targetTree; } | |||||
| /** Returns the property ID of the referenced property. */ | |||||
| Identifier& getPropertyID() noexcept { return targetProperty; } | |||||
| private: | |||||
| //============================================================================== | |||||
| ValueTree targetTree; | |||||
| Identifier targetProperty; | |||||
| UndoManager* undoManager; | |||||
| var defaultValue; | |||||
| //============================================================================== | |||||
| void referToWithDefault (ValueTree& v, const Identifier& i, UndoManager* um, const var& defaultVal) | |||||
| { | |||||
| targetTree = v; | |||||
| targetProperty = i; | |||||
| undoManager = um; | |||||
| defaultValue = defaultVal; | |||||
| } | |||||
| }; | |||||
| } // namespace juce | |||||
| @@ -27,30 +27,32 @@ | |||||
| namespace juce | namespace juce | ||||
| { | { | ||||
| //============================================================================== | |||||
| class ChoicePropertyComponent::RemapperValueSource : public Value::ValueSource, | class ChoicePropertyComponent::RemapperValueSource : public Value::ValueSource, | ||||
| private Value::Listener | private Value::Listener | ||||
| { | { | ||||
| public: | public: | ||||
| RemapperValueSource (const Value& source, const Array<var>& map) | RemapperValueSource (const Value& source, const Array<var>& map) | ||||
| : sourceValue (source), mappings (map) | |||||
| : sourceValue (source), | |||||
| mappings (map) | |||||
| { | { | ||||
| sourceValue.addListener (this); | sourceValue.addListener (this); | ||||
| } | } | ||||
| var getValue() const | |||||
| var getValue() const override | |||||
| { | { | ||||
| const var targetValue (sourceValue.getValue()); | |||||
| auto targetValue = sourceValue.getValue(); | |||||
| for (int i = 0; i < mappings.size(); ++i) | |||||
| if (mappings.getReference(i).equalsWithSameType (targetValue)) | |||||
| return i + 1; | |||||
| for (auto& map : mappings) | |||||
| if (map.equalsWithSameType (targetValue)) | |||||
| return mappings.indexOf (map) + 1; | |||||
| return mappings.indexOf (targetValue) + 1; | return mappings.indexOf (targetValue) + 1; | ||||
| } | } | ||||
| void setValue (const var& newValue) | |||||
| void setValue (const var& newValue) override | |||||
| { | { | ||||
| const var remappedVal (mappings [static_cast<int> (newValue) - 1]); | |||||
| auto remappedVal = mappings [static_cast<int> (newValue) - 1]; | |||||
| if (! remappedVal.equalsWithSameType (sourceValue)) | if (! remappedVal.equalsWithSameType (sourceValue)) | ||||
| sourceValue = remappedVal; | sourceValue = remappedVal; | ||||
| @@ -60,14 +62,66 @@ protected: | |||||
| Value sourceValue; | Value sourceValue; | ||||
| Array<var> mappings; | Array<var> mappings; | ||||
| void valueChanged (Value&) | |||||
| { | |||||
| sendChangeMessage (true); | |||||
| } | |||||
| void valueChanged (Value&) override { sendChangeMessage (true); } | |||||
| //============================================================================== | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSource) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSource) | ||||
| }; | }; | ||||
| //============================================================================== | |||||
| class ChoicePropertyComponent::RemapperValueSourceWithDefault : public Value::ValueSource, | |||||
| private Value::Listener | |||||
| { | |||||
| public: | |||||
| RemapperValueSourceWithDefault (const ValueWithDefault& vwd, const Array<var>& map) | |||||
| : valueWithDefault (vwd), | |||||
| sourceValue (valueWithDefault.getPropertyAsValue()), | |||||
| mappings (map) | |||||
| { | |||||
| sourceValue.addListener (this); | |||||
| } | |||||
| var getValue() const override | |||||
| { | |||||
| if (valueWithDefault.isUsingDefault()) | |||||
| return -1; | |||||
| auto targetValue = sourceValue.getValue(); | |||||
| for (auto map : mappings) | |||||
| if (map.equalsWithSameType (targetValue)) | |||||
| return mappings.indexOf (map) + 1; | |||||
| return mappings.indexOf (targetValue) + 1; | |||||
| } | |||||
| void setValue (const var& newValue) override | |||||
| { | |||||
| auto newValueInt = static_cast<int> (newValue); | |||||
| if (newValueInt == -1) | |||||
| { | |||||
| valueWithDefault.resetToDefault(); | |||||
| } | |||||
| else | |||||
| { | |||||
| auto remappedVal = mappings [newValueInt - 1]; | |||||
| if (! remappedVal.equalsWithSameType (sourceValue)) | |||||
| valueWithDefault = remappedVal; | |||||
| } | |||||
| } | |||||
| private: | |||||
| ValueWithDefault valueWithDefault; | |||||
| Value sourceValue; | |||||
| Array<var> mappings; | |||||
| void valueChanged (Value&) override { sendChangeMessage (true); } | |||||
| //============================================================================== | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSourceWithDefault) | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| ChoicePropertyComponent::ChoicePropertyComponent (const String& name) | ChoicePropertyComponent::ChoicePropertyComponent (const String& name) | ||||
| @@ -76,24 +130,54 @@ ChoicePropertyComponent::ChoicePropertyComponent (const String& name) | |||||
| { | { | ||||
| } | } | ||||
| ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl, | |||||
| const String& name, | |||||
| ChoicePropertyComponent::ChoicePropertyComponent (const String& name, | |||||
| const StringArray& choiceList, | const StringArray& choiceList, | ||||
| const Array<var>& correspondingValues) | const Array<var>& correspondingValues) | ||||
| : PropertyComponent (name), | : PropertyComponent (name), | ||||
| choices (choiceList), | |||||
| isCustomClass (false) | |||||
| choices (choiceList) | |||||
| { | { | ||||
| // The array of corresponding values must contain one value for each of the items in | // The array of corresponding values must contain one value for each of the items in | ||||
| // the choices array! | // the choices array! | ||||
| jassert (correspondingValues.size() == choices.size()); | jassert (correspondingValues.size() == choices.size()); | ||||
| ignoreUnused (correspondingValues); | |||||
| } | |||||
| ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl, | |||||
| const String& name, | |||||
| const StringArray& choiceList, | |||||
| const Array<var>& correspondingValues) | |||||
| : ChoicePropertyComponent (name, choiceList, correspondingValues) | |||||
| { | |||||
| createComboBox(); | createComboBox(); | ||||
| comboBox.getSelectedIdAsValue().referTo (Value (new RemapperValueSource (valueToControl, | comboBox.getSelectedIdAsValue().referTo (Value (new RemapperValueSource (valueToControl, | ||||
| correspondingValues))); | correspondingValues))); | ||||
| } | } | ||||
| ChoicePropertyComponent::ChoicePropertyComponent (ValueWithDefault valueToControl, | |||||
| const String& name, | |||||
| const StringArray& choiceList, | |||||
| const Array<var>& correspondingValues) | |||||
| : ChoicePropertyComponent (name, choiceList, correspondingValues) | |||||
| { | |||||
| createComboBoxWithDefault (choiceList [correspondingValues.indexOf (valueToControl.getDefault())]); | |||||
| comboBox.getSelectedIdAsValue().referTo (Value (new RemapperValueSourceWithDefault (valueToControl, | |||||
| correspondingValues))); | |||||
| } | |||||
| ChoicePropertyComponent::ChoicePropertyComponent (ValueWithDefault valueToControl, | |||||
| const String& name) | |||||
| : PropertyComponent (name), | |||||
| choices ({ "Enabled", "Disabled" }) | |||||
| { | |||||
| createComboBoxWithDefault (valueToControl.getDefault() ? "Enabled" : "Disabled"); | |||||
| comboBox.getSelectedIdAsValue().referTo (Value (new RemapperValueSourceWithDefault (valueToControl, | |||||
| { true, false }))); | |||||
| } | |||||
| ChoicePropertyComponent::~ChoicePropertyComponent() | ChoicePropertyComponent::~ChoicePropertyComponent() | ||||
| { | { | ||||
| } | } | ||||
| @@ -103,10 +187,27 @@ void ChoicePropertyComponent::createComboBox() | |||||
| { | { | ||||
| addAndMakeVisible (comboBox); | addAndMakeVisible (comboBox); | ||||
| for (int i = 0; i < choices.size(); ++i) | |||||
| for (auto choice : choices) | |||||
| { | |||||
| if (choice.isNotEmpty()) | |||||
| comboBox.addItem (choice, choices.indexOf (choice) + 1); | |||||
| else | |||||
| comboBox.addSeparator(); | |||||
| } | |||||
| comboBox.setEditableText (false); | |||||
| } | |||||
| void ChoicePropertyComponent::createComboBoxWithDefault (const String& defaultString) | |||||
| { | |||||
| addAndMakeVisible (comboBox); | |||||
| comboBox.addItem ("Default" + (defaultString.isNotEmpty() ? " (" + defaultString + ")" : ""), -1); | |||||
| for (auto choice : choices) | |||||
| { | { | ||||
| if (choices[i].isNotEmpty()) | |||||
| comboBox.addItem (choices[i], i + 1); | |||||
| if (choice.isNotEmpty()) | |||||
| comboBox.addItem (choice, choices.indexOf (choice) + 1); | |||||
| else | else | ||||
| comboBox.addSeparator(); | comboBox.addSeparator(); | ||||
| } | } | ||||
| @@ -149,7 +250,7 @@ void ChoicePropertyComponent::comboBoxChanged (ComboBox*) | |||||
| { | { | ||||
| if (isCustomClass) | if (isCustomClass) | ||||
| { | { | ||||
| const int newIndex = comboBox.getSelectedId() - 1; | |||||
| auto newIndex = comboBox.getSelectedId() - 1; | |||||
| if (newIndex != getIndex()) | if (newIndex != getIndex()) | ||||
| setIndex (newIndex); | setIndex (newIndex); | ||||
| @@ -75,6 +75,31 @@ public: | |||||
| const StringArray& choices, | const StringArray& choices, | ||||
| const Array<var>& correspondingValues); | const Array<var>& correspondingValues); | ||||
| /** Creates the component using a ValueWithDefault 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 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, | |||||
| const String& propertyName, | |||||
| const StringArray& choices, | |||||
| const Array<var>& correspondingValues); | |||||
| /** Creates the component using a ValueWithDefault 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, | |||||
| const String& propertyName); | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~ChoicePropertyComponent(); | ~ChoicePropertyComponent(); | ||||
| @@ -95,10 +120,9 @@ public: | |||||
| /** Returns the list of options. */ | /** Returns the list of options. */ | ||||
| const StringArray& getChoices() const; | const StringArray& getChoices() const; | ||||
| //============================================================================== | //============================================================================== | ||||
| /** @internal */ | /** @internal */ | ||||
| void refresh(); | |||||
| void refresh() override; | |||||
| protected: | protected: | ||||
| /** The list of options that will be shown in the combo box. | /** The list of options that will be shown in the combo box. | ||||
| @@ -110,12 +134,19 @@ protected: | |||||
| StringArray choices; | StringArray choices; | ||||
| private: | private: | ||||
| /** Delegating constructor. */ | |||||
| ChoicePropertyComponent (const String&, const StringArray&, const Array<var>&); | |||||
| ComboBox comboBox; | ComboBox comboBox; | ||||
| bool isCustomClass; | |||||
| bool isCustomClass = false; | |||||
| class RemapperValueSource; | class RemapperValueSource; | ||||
| class RemapperValueSourceWithDefault; | |||||
| void createComboBox(); | void createComboBox(); | ||||
| void comboBoxChanged (ComboBox*); | |||||
| void createComboBoxWithDefault (const String&); | |||||
| void comboBoxChanged (ComboBox*) override; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoicePropertyComponent) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoicePropertyComponent) | ||||
| }; | }; | ||||
| @@ -27,6 +27,7 @@ | |||||
| namespace juce | namespace juce | ||||
| { | { | ||||
| //============================================================================== | |||||
| class TextPropertyComponent::LabelComp : public Label, | class TextPropertyComponent::LabelComp : public Label, | ||||
| public FileDragAndDropTarget | public FileDragAndDropTarget | ||||
| { | { | ||||
| @@ -85,11 +86,66 @@ public: | |||||
| interestedInFileDrag = isInterested; | interestedInFileDrag = isInterested; | ||||
| } | } | ||||
| void setTextToDisplayWhenEmpty (const String& text, float alpha) | |||||
| { | |||||
| textToDisplayWhenEmpty = text; | |||||
| alphaToUseForEmptyText = alpha; | |||||
| } | |||||
| void paintOverChildren (Graphics& g) override | |||||
| { | |||||
| if (getText().isEmpty() && ! isBeingEdited()) | |||||
| { | |||||
| auto textArea = getBorderSize().subtractedFrom (getLocalBounds()); | |||||
| auto labelFont = owner.getLookAndFeel().getLabelFont (*this); | |||||
| g.setColour (owner.findColour (TextPropertyComponent::textColourId).withAlpha (alphaToUseForEmptyText)); | |||||
| g.setFont (labelFont); | |||||
| g.drawFittedText (textToDisplayWhenEmpty, textArea, getJustificationType(), | |||||
| jmax (1, (int) (textArea.getHeight() / labelFont.getHeight())), | |||||
| getMinimumHorizontalScale()); | |||||
| } | |||||
| } | |||||
| private: | private: | ||||
| TextPropertyComponent& owner; | TextPropertyComponent& owner; | ||||
| int maxChars; | int maxChars; | ||||
| bool isMultiline; | bool isMultiline; | ||||
| bool interestedInFileDrag = true; | bool interestedInFileDrag = true; | ||||
| String textToDisplayWhenEmpty; | |||||
| float alphaToUseForEmptyText = 0.0f; | |||||
| }; | |||||
| //============================================================================== | |||||
| class TextPropertyComponent::RemapperValueSourceWithDefault : public Value::ValueSource | |||||
| { | |||||
| public: | |||||
| RemapperValueSourceWithDefault (const ValueWithDefault& vwd) | |||||
| : valueWithDefault (vwd) | |||||
| { | |||||
| } | |||||
| var getValue() const override | |||||
| { | |||||
| return valueWithDefault.isUsingDefault() ? var() : valueWithDefault.get(); | |||||
| } | |||||
| void setValue (const var& newValue) override | |||||
| { | |||||
| if (newValue.toString().isEmpty()) | |||||
| valueWithDefault.resetToDefault(); | |||||
| else | |||||
| valueWithDefault = newValue; | |||||
| } | |||||
| private: | |||||
| ValueWithDefault valueWithDefault; | |||||
| //============================================================================== | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSourceWithDefault) | |||||
| }; | }; | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -107,13 +163,22 @@ TextPropertyComponent::TextPropertyComponent (const Value& valueToControl, | |||||
| int maxNumChars, | int maxNumChars, | ||||
| bool isMultiLine, | bool isMultiLine, | ||||
| bool isEditable) | bool isEditable) | ||||
| : PropertyComponent (name) | |||||
| : TextPropertyComponent (name, maxNumChars, isMultiLine, isEditable) | |||||
| { | { | ||||
| createEditor (maxNumChars, isMultiLine, isEditable); | |||||
| textEditor->getTextValue().referTo (valueToControl); | textEditor->getTextValue().referTo (valueToControl); | ||||
| } | } | ||||
| TextPropertyComponent::TextPropertyComponent (const ValueWithDefault& valueToControl, | |||||
| const String& name, | |||||
| int maxNumChars, | |||||
| bool isMultiLine, | |||||
| bool isEditable) | |||||
| : TextPropertyComponent (name, maxNumChars, isMultiLine, isEditable) | |||||
| { | |||||
| textEditor->getTextValue().referTo (Value (new RemapperValueSourceWithDefault (valueToControl))); | |||||
| textEditor->setTextToDisplayWhenEmpty (valueToControl.getDefault(), 0.5f); | |||||
| } | |||||
| TextPropertyComponent::~TextPropertyComponent() | TextPropertyComponent::~TextPropertyComponent() | ||||
| { | { | ||||
| } | } | ||||
| @@ -70,6 +70,23 @@ public: | |||||
| bool isMultiLine, | bool isMultiLine, | ||||
| bool isEditable = true); | bool isEditable = true); | ||||
| /** Creates a text property component with a default value. | |||||
| @param valueToControl The ValueWithDefault 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. | |||||
| @param isMultiLine Sets whether the text editor allows carriage returns. | |||||
| @param isEditable Sets whether the text editor is editable. The default is true. | |||||
| @see TextEditor, setEditable | |||||
| */ | |||||
| TextPropertyComponent (const ValueWithDefault& valueToControl, | |||||
| const String& propertyName, | |||||
| int maxNumChars, | |||||
| bool isMultiLine, | |||||
| bool isEditable = true); | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~TextPropertyComponent(); | ~TextPropertyComponent(); | ||||
| @@ -144,6 +161,8 @@ public: | |||||
| virtual void textWasEdited(); | virtual void textWasEdited(); | ||||
| private: | private: | ||||
| class RemapperValueSourceWithDefault; | |||||
| class LabelComp; | class LabelComp; | ||||
| friend class LabelComp; | friend class LabelComp; | ||||