git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
86
deps/juce/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.cpp
vendored
Normal file
86
deps/juce/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.cpp
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
BooleanPropertyComponent::BooleanPropertyComponent (const String& name,
|
||||
const String& buttonTextWhenTrue,
|
||||
const String& buttonTextWhenFalse)
|
||||
: PropertyComponent (name),
|
||||
onText (buttonTextWhenTrue),
|
||||
offText (buttonTextWhenFalse)
|
||||
{
|
||||
addAndMakeVisible (button);
|
||||
button.setClickingTogglesState (false);
|
||||
button.onClick = [this] { setState (! getState()); };
|
||||
}
|
||||
|
||||
BooleanPropertyComponent::BooleanPropertyComponent (const Value& valueToControl,
|
||||
const String& name,
|
||||
const String& buttonText)
|
||||
: PropertyComponent (name),
|
||||
onText (buttonText),
|
||||
offText (buttonText)
|
||||
{
|
||||
addAndMakeVisible (button);
|
||||
button.setClickingTogglesState (false);
|
||||
button.setButtonText (buttonText);
|
||||
button.getToggleStateValue().referTo (valueToControl);
|
||||
button.setClickingTogglesState (true);
|
||||
}
|
||||
|
||||
BooleanPropertyComponent::~BooleanPropertyComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void BooleanPropertyComponent::setState (const bool newState)
|
||||
{
|
||||
button.setToggleState (newState, sendNotification);
|
||||
}
|
||||
|
||||
bool BooleanPropertyComponent::getState() const
|
||||
{
|
||||
return button.getToggleState();
|
||||
}
|
||||
|
||||
void BooleanPropertyComponent::paint (Graphics& g)
|
||||
{
|
||||
PropertyComponent::paint (g);
|
||||
|
||||
g.setColour (findColour (backgroundColourId));
|
||||
g.fillRect (button.getBounds());
|
||||
|
||||
g.setColour (findColour (outlineColourId));
|
||||
g.drawRect (button.getBounds());
|
||||
}
|
||||
|
||||
void BooleanPropertyComponent::refresh()
|
||||
{
|
||||
button.setToggleState (getState(), dontSendNotification);
|
||||
button.setButtonText (button.getToggleState() ? onText : offText);
|
||||
}
|
||||
|
||||
} // namespace juce
|
109
deps/juce/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h
vendored
Normal file
109
deps/juce/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A PropertyComponent that contains an on/off toggle button.
|
||||
|
||||
This type of property component can be used if you have a boolean value to
|
||||
toggle on/off.
|
||||
|
||||
@see PropertyComponent
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API BooleanPropertyComponent : public PropertyComponent
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates a button component.
|
||||
|
||||
If you use this constructor, you must override the getState() and setState()
|
||||
methods.
|
||||
|
||||
@param propertyName the property name to be passed to the PropertyComponent
|
||||
@param buttonTextWhenTrue the text shown in the button when the value is true
|
||||
@param buttonTextWhenFalse the text shown in the button when the value is false
|
||||
*/
|
||||
BooleanPropertyComponent (const String& propertyName,
|
||||
const String& buttonTextWhenTrue,
|
||||
const String& buttonTextWhenFalse);
|
||||
|
||||
public:
|
||||
/** Creates a button component.
|
||||
|
||||
Note that if you call this constructor then you must use the Value to interact with the
|
||||
button state, and you can't override the class with your own setState or getState methods.
|
||||
If you want to use getState and setState, call the other constructor instead.
|
||||
|
||||
@param valueToControl a Value object that this property should refer to.
|
||||
@param propertyName the property name to be passed to the PropertyComponent
|
||||
@param buttonText the text shown in the ToggleButton component
|
||||
*/
|
||||
BooleanPropertyComponent (const Value& valueToControl,
|
||||
const String& propertyName,
|
||||
const String& buttonText);
|
||||
|
||||
/** Destructor. */
|
||||
~BooleanPropertyComponent() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Called to change the state of the boolean value. */
|
||||
virtual void setState (bool newState);
|
||||
|
||||
/** Must return the current value of the property. */
|
||||
virtual bool getState() const;
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the component.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
backgroundColourId = 0x100e801, /**< The colour to fill the background of the button area. */
|
||||
outlineColourId = 0x100e803, /**< The colour to use to draw an outline around the text area. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paint (Graphics&) override;
|
||||
/** @internal */
|
||||
void refresh() override;
|
||||
|
||||
private:
|
||||
ToggleButton button;
|
||||
String onText, offText;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BooleanPropertyComponent)
|
||||
};
|
||||
|
||||
} // namespace juce
|
46
deps/juce/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp
vendored
Normal file
46
deps/juce/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
ButtonPropertyComponent::ButtonPropertyComponent (const String& name, bool triggerOnMouseDown)
|
||||
: PropertyComponent (name)
|
||||
{
|
||||
addAndMakeVisible (button);
|
||||
button.setTriggeredOnMouseDown (triggerOnMouseDown);
|
||||
button.onClick = [this] { buttonClicked(); };
|
||||
}
|
||||
|
||||
ButtonPropertyComponent::~ButtonPropertyComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void ButtonPropertyComponent::refresh()
|
||||
{
|
||||
button.setButtonText (getButtonText());
|
||||
}
|
||||
|
||||
} // namespace juce
|
76
deps/juce/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h
vendored
Normal file
76
deps/juce/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A PropertyComponent that contains a button.
|
||||
|
||||
This type of property component can be used if you need a button to trigger some
|
||||
kind of action.
|
||||
|
||||
@see PropertyComponent
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API ButtonPropertyComponent : public PropertyComponent
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a button component.
|
||||
|
||||
@param propertyName the property name to be passed to the PropertyComponent
|
||||
@param triggerOnMouseDown this is passed to the Button::setTriggeredOnMouseDown() method
|
||||
*/
|
||||
ButtonPropertyComponent (const String& propertyName,
|
||||
bool triggerOnMouseDown);
|
||||
|
||||
/** Destructor. */
|
||||
~ButtonPropertyComponent() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Called when the user clicks the button.
|
||||
*/
|
||||
virtual void buttonClicked() = 0;
|
||||
|
||||
/** Returns the string that should be displayed in the button.
|
||||
|
||||
If you need to change this string, call refresh() to update the component.
|
||||
*/
|
||||
virtual String getButtonText() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void refresh() override;
|
||||
|
||||
private:
|
||||
TextButton button;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonPropertyComponent)
|
||||
};
|
||||
|
||||
} // namespace juce
|
284
deps/juce/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp
vendored
Normal file
284
deps/juce/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
class ChoicePropertyComponent::RemapperValueSource : public Value::ValueSource,
|
||||
private Value::Listener
|
||||
{
|
||||
public:
|
||||
RemapperValueSource (const Value& source, const Array<var>& map)
|
||||
: sourceValue (source),
|
||||
mappings (map)
|
||||
{
|
||||
sourceValue.addListener (this);
|
||||
}
|
||||
|
||||
var getValue() const override
|
||||
{
|
||||
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 remappedVal = mappings [static_cast<int> (newValue) - 1];
|
||||
|
||||
if (! remappedVal.equalsWithSameType (sourceValue))
|
||||
sourceValue = remappedVal;
|
||||
}
|
||||
|
||||
protected:
|
||||
Value sourceValue;
|
||||
Array<var> mappings;
|
||||
|
||||
void valueChanged (Value&) override { sendChangeMessage (true); }
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSource)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ChoicePropertyComponent::RemapperValueSourceWithDefault : public Value::ValueSource,
|
||||
private Value::Listener
|
||||
{
|
||||
public:
|
||||
RemapperValueSourceWithDefault (ValueWithDefault* vwd, const Array<var>& map)
|
||||
: valueWithDefault (vwd),
|
||||
sourceValue (valueWithDefault->getPropertyAsValue()),
|
||||
mappings (map)
|
||||
{
|
||||
sourceValue.addListener (this);
|
||||
}
|
||||
|
||||
var getValue() const override
|
||||
{
|
||||
if (valueWithDefault != nullptr && ! valueWithDefault->isUsingDefault())
|
||||
{
|
||||
const auto target = sourceValue.getValue();
|
||||
const auto equalsWithSameType = [&target] (const var& map) { return map.equalsWithSameType (target); };
|
||||
|
||||
auto iter = std::find_if (mappings.begin(), mappings.end(), equalsWithSameType);
|
||||
|
||||
if (iter == mappings.end())
|
||||
iter = std::find (mappings.begin(), mappings.end(), target);
|
||||
|
||||
if (iter != mappings.end())
|
||||
return 1 + (int) std::distance (mappings.begin(), iter);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void setValue (const var& newValue) override
|
||||
{
|
||||
if (valueWithDefault == nullptr)
|
||||
return;
|
||||
|
||||
auto newValueInt = static_cast<int> (newValue);
|
||||
|
||||
if (newValueInt == -1)
|
||||
{
|
||||
valueWithDefault->resetToDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto remappedVal = mappings [newValueInt - 1];
|
||||
|
||||
if (! remappedVal.equalsWithSameType (sourceValue))
|
||||
*valueWithDefault = remappedVal;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void valueChanged (Value&) override { sendChangeMessage (true); }
|
||||
|
||||
WeakReference<ValueWithDefault> valueWithDefault;
|
||||
Value sourceValue;
|
||||
Array<var> mappings;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSourceWithDefault)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
ChoicePropertyComponent::ChoicePropertyComponent (const String& name)
|
||||
: PropertyComponent (name),
|
||||
isCustomClass (true)
|
||||
{
|
||||
}
|
||||
|
||||
ChoicePropertyComponent::ChoicePropertyComponent (const String& name,
|
||||
const StringArray& choiceList,
|
||||
const Array<var>& correspondingValues)
|
||||
: PropertyComponent (name),
|
||||
choices (choiceList)
|
||||
{
|
||||
// The array of corresponding values must contain one value for each of the items in
|
||||
// the choices array!
|
||||
jassertquiet (correspondingValues.size() == choices.size());
|
||||
}
|
||||
|
||||
ChoicePropertyComponent::ChoicePropertyComponent (const Value& valueToControl,
|
||||
const String& name,
|
||||
const StringArray& choiceList,
|
||||
const Array<var>& correspondingValues)
|
||||
: ChoicePropertyComponent (name, choiceList, correspondingValues)
|
||||
{
|
||||
refreshChoices();
|
||||
initialiseComboBox (Value (new RemapperValueSource (valueToControl, correspondingValues)));
|
||||
}
|
||||
|
||||
ChoicePropertyComponent::ChoicePropertyComponent (ValueWithDefault& valueToControl,
|
||||
const String& name,
|
||||
const StringArray& choiceList,
|
||||
const Array<var>& correspondingValues)
|
||||
: ChoicePropertyComponent (name, choiceList, correspondingValues)
|
||||
{
|
||||
valueWithDefault = &valueToControl;
|
||||
|
||||
auto getDefaultString = [this, correspondingValues] { return choices [correspondingValues.indexOf (valueWithDefault->getDefault())]; };
|
||||
|
||||
refreshChoices (getDefaultString());
|
||||
initialiseComboBox (Value (new RemapperValueSourceWithDefault (valueWithDefault, correspondingValues)));
|
||||
|
||||
valueWithDefault->onDefaultChange = [this, getDefaultString]
|
||||
{
|
||||
auto selectedId = comboBox.getSelectedId();
|
||||
refreshChoices (getDefaultString());
|
||||
comboBox.setSelectedId (selectedId);
|
||||
};
|
||||
}
|
||||
|
||||
ChoicePropertyComponent::ChoicePropertyComponent (ValueWithDefault& valueToControl,
|
||||
const String& name)
|
||||
: PropertyComponent (name),
|
||||
choices ({ "Enabled", "Disabled" })
|
||||
{
|
||||
valueWithDefault = &valueToControl;
|
||||
|
||||
auto getDefaultString = [this] { return valueWithDefault->getDefault() ? "Enabled" : "Disabled"; };
|
||||
|
||||
refreshChoices (getDefaultString());
|
||||
initialiseComboBox (Value (new RemapperValueSourceWithDefault (valueWithDefault, { true, false })));
|
||||
|
||||
valueWithDefault->onDefaultChange = [this, getDefaultString]
|
||||
{
|
||||
auto selectedId = comboBox.getSelectedId();
|
||||
refreshChoices (getDefaultString());
|
||||
comboBox.setSelectedId (selectedId);
|
||||
};
|
||||
}
|
||||
|
||||
ChoicePropertyComponent::~ChoicePropertyComponent()
|
||||
{
|
||||
if (valueWithDefault != nullptr)
|
||||
valueWithDefault->onDefaultChange = nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ChoicePropertyComponent::initialiseComboBox (const Value& v)
|
||||
{
|
||||
if (v != Value())
|
||||
{
|
||||
comboBox.setSelectedId (v.getValue(), dontSendNotification);
|
||||
comboBox.getSelectedIdAsValue().referTo (v);
|
||||
}
|
||||
|
||||
comboBox.setEditableText (false);
|
||||
addAndMakeVisible (comboBox);
|
||||
}
|
||||
|
||||
void ChoicePropertyComponent::refreshChoices()
|
||||
{
|
||||
comboBox.clear();
|
||||
|
||||
for (auto choice : choices)
|
||||
{
|
||||
if (choice.isNotEmpty())
|
||||
comboBox.addItem (choice, choices.indexOf (choice) + 1);
|
||||
else
|
||||
comboBox.addSeparator();
|
||||
}
|
||||
}
|
||||
|
||||
void ChoicePropertyComponent::refreshChoices (const String& defaultString)
|
||||
{
|
||||
refreshChoices();
|
||||
comboBox.addItem ("Default" + (defaultString.isNotEmpty() ? " (" + defaultString + ")" : ""), -1);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ChoicePropertyComponent::setIndex (const int /*newIndex*/)
|
||||
{
|
||||
jassertfalse; // you need to override this method in your subclass!
|
||||
}
|
||||
|
||||
int ChoicePropertyComponent::getIndex() const
|
||||
{
|
||||
jassertfalse; // you need to override this method in your subclass!
|
||||
return -1;
|
||||
}
|
||||
|
||||
const StringArray& ChoicePropertyComponent::getChoices() const
|
||||
{
|
||||
return choices;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ChoicePropertyComponent::refresh()
|
||||
{
|
||||
if (isCustomClass)
|
||||
{
|
||||
if (! comboBox.isVisible())
|
||||
{
|
||||
refreshChoices();
|
||||
initialiseComboBox ({});
|
||||
comboBox.onChange = [this] { changeIndex(); };
|
||||
}
|
||||
|
||||
comboBox.setSelectedId (getIndex() + 1, dontSendNotification);
|
||||
}
|
||||
}
|
||||
|
||||
void ChoicePropertyComponent::changeIndex()
|
||||
{
|
||||
if (isCustomClass)
|
||||
{
|
||||
auto newIndex = comboBox.getSelectedId() - 1;
|
||||
|
||||
if (newIndex != getIndex())
|
||||
setIndex (newIndex);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace juce
|
162
deps/juce/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h
vendored
Normal file
162
deps/juce/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A PropertyComponent that shows its value as a combo box.
|
||||
|
||||
This type of property component contains a list of options and has a
|
||||
combo box to choose one.
|
||||
|
||||
Your subclass's constructor must add some strings to the choices StringArray
|
||||
and these are shown in the list.
|
||||
|
||||
The getIndex() method will be called to find out which option is the currently
|
||||
selected one. If you call refresh() it will call getIndex() to check whether
|
||||
the value has changed, and will update the combo box if needed.
|
||||
|
||||
If the user selects a different item from the list, setIndex() will be
|
||||
called to let your class process this.
|
||||
|
||||
@see PropertyComponent, PropertyPanel
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API ChoicePropertyComponent : public PropertyComponent
|
||||
{
|
||||
private:
|
||||
/** Delegating constructor. */
|
||||
ChoicePropertyComponent (const String&, const StringArray&, const Array<var>&);
|
||||
|
||||
protected:
|
||||
/** Creates the component.
|
||||
Your subclass's constructor must add a list of options to the choices member variable.
|
||||
*/
|
||||
ChoicePropertyComponent (const String& propertyName);
|
||||
|
||||
public:
|
||||
/** Creates the component.
|
||||
|
||||
Note that if you call this constructor then you must use the Value to interact with the
|
||||
index, and you can't override the class with your own setIndex or getIndex methods.
|
||||
If you want to use those methods, call the other constructor instead.
|
||||
|
||||
@param valueToControl the value 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 (const Value& valueToControl,
|
||||
const String& propertyName,
|
||||
const StringArray& choices,
|
||||
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. */
|
||||
~ChoicePropertyComponent() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Called when the user selects an item from the combo box.
|
||||
|
||||
Your subclass must use this callback to update the value that this component
|
||||
represents. The index is the index of the chosen item in the choices
|
||||
StringArray.
|
||||
*/
|
||||
virtual void setIndex (int newIndex);
|
||||
|
||||
/** Returns the index of the item that should currently be shown.
|
||||
This is the index of the item in the choices StringArray that will be shown.
|
||||
*/
|
||||
virtual int getIndex() const;
|
||||
|
||||
/** Returns the list of options. */
|
||||
const StringArray& getChoices() const;
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void refresh() override;
|
||||
|
||||
protected:
|
||||
/** The list of options that will be shown in the combo box.
|
||||
|
||||
Your subclass must populate this array in its constructor. If any empty
|
||||
strings are added, these will be replaced with horizontal separators (see
|
||||
ComboBox::addSeparator() for more info).
|
||||
*/
|
||||
StringArray choices;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class RemapperValueSource;
|
||||
class RemapperValueSourceWithDefault;
|
||||
|
||||
//==============================================================================
|
||||
void initialiseComboBox (const Value&);
|
||||
void refreshChoices();
|
||||
void refreshChoices (const String&);
|
||||
|
||||
void changeIndex();
|
||||
|
||||
//==============================================================================
|
||||
ComboBox comboBox;
|
||||
bool isCustomClass = false;
|
||||
|
||||
WeakReference<ValueWithDefault> valueWithDefault;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChoicePropertyComponent)
|
||||
};
|
||||
|
||||
} // namespace juce
|
373
deps/juce/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.cpp
vendored
Normal file
373
deps/juce/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.cpp
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
class StringComparator
|
||||
{
|
||||
public:
|
||||
static int compareElements (var first, var second)
|
||||
{
|
||||
if (first.toString() > second.toString())
|
||||
return 1;
|
||||
else if (first.toString() < second.toString())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
static void updateButtonTickColour (ToggleButton* button, bool usingDefault)
|
||||
{
|
||||
button->setColour (ToggleButton::tickColourId, button->getLookAndFeel().findColour (ToggleButton::tickColourId)
|
||||
.withAlpha (usingDefault ? 0.4f : 1.0f));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class MultiChoicePropertyComponent::MultiChoiceRemapperSource : public Value::ValueSource,
|
||||
private Value::Listener
|
||||
{
|
||||
public:
|
||||
MultiChoiceRemapperSource (const Value& source, var v, int c)
|
||||
: sourceValue (source),
|
||||
varToControl (v),
|
||||
maxChoices (c)
|
||||
{
|
||||
sourceValue.addListener (this);
|
||||
}
|
||||
|
||||
var getValue() const override
|
||||
{
|
||||
if (auto* arr = sourceValue.getValue().getArray())
|
||||
if (arr->contains (varToControl))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void setValue (const var& newValue) override
|
||||
{
|
||||
if (auto* arr = sourceValue.getValue().getArray())
|
||||
{
|
||||
auto temp = *arr;
|
||||
|
||||
if (static_cast<bool> (newValue))
|
||||
{
|
||||
if (temp.addIfNotAlreadyThere (varToControl) && (maxChoices != -1) && (temp.size() > maxChoices))
|
||||
temp.remove (temp.size() - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.remove (arr->indexOf (varToControl));
|
||||
}
|
||||
|
||||
StringComparator c;
|
||||
temp.sort (c);
|
||||
|
||||
sourceValue = temp;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Value sourceValue;
|
||||
var varToControl;
|
||||
|
||||
int maxChoices;
|
||||
|
||||
//==============================================================================
|
||||
void valueChanged (Value&) override { sendChangeMessage (true); }
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultiChoiceRemapperSource)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class MultiChoicePropertyComponent::MultiChoiceRemapperSourceWithDefault : public Value::ValueSource,
|
||||
private Value::Listener
|
||||
{
|
||||
public:
|
||||
MultiChoiceRemapperSourceWithDefault (ValueWithDefault* vwd, var v, int c, ToggleButton* b)
|
||||
: valueWithDefault (vwd),
|
||||
varToControl (v),
|
||||
sourceValue (valueWithDefault->getPropertyAsValue()),
|
||||
maxChoices (c),
|
||||
buttonToControl (b)
|
||||
{
|
||||
sourceValue.addListener (this);
|
||||
}
|
||||
|
||||
var getValue() const override
|
||||
{
|
||||
if (valueWithDefault == nullptr)
|
||||
return {};
|
||||
|
||||
auto v = valueWithDefault->get();
|
||||
|
||||
if (auto* arr = v.getArray())
|
||||
{
|
||||
if (arr->contains (varToControl))
|
||||
{
|
||||
updateButtonTickColour (buttonToControl, valueWithDefault->isUsingDefault());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void setValue (const var& newValue) override
|
||||
{
|
||||
if (valueWithDefault == nullptr)
|
||||
return;
|
||||
|
||||
auto v = valueWithDefault->get();
|
||||
|
||||
OptionalScopedPointer<Array<var>> arrayToControl;
|
||||
|
||||
if (valueWithDefault->isUsingDefault())
|
||||
arrayToControl.set (new Array<var>(), true); // use an empty array so the default values are overwritten
|
||||
else
|
||||
arrayToControl.set (v.getArray(), false);
|
||||
|
||||
if (arrayToControl != nullptr)
|
||||
{
|
||||
auto temp = *arrayToControl;
|
||||
|
||||
bool newState = newValue;
|
||||
|
||||
if (valueWithDefault->isUsingDefault())
|
||||
{
|
||||
if (auto* defaultArray = v.getArray())
|
||||
{
|
||||
if (defaultArray->contains (varToControl))
|
||||
newState = true; // force the state as the user is setting it explicitly
|
||||
}
|
||||
}
|
||||
|
||||
if (newState)
|
||||
{
|
||||
if (temp.addIfNotAlreadyThere (varToControl) && (maxChoices != -1) && (temp.size() > maxChoices))
|
||||
temp.remove (temp.size() - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.remove (temp.indexOf (varToControl));
|
||||
}
|
||||
|
||||
StringComparator c;
|
||||
temp.sort (c);
|
||||
|
||||
*valueWithDefault = temp;
|
||||
|
||||
if (temp.size() == 0)
|
||||
valueWithDefault->resetToDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void valueChanged (Value&) override { sendChangeMessage (true); }
|
||||
|
||||
//==============================================================================
|
||||
WeakReference<ValueWithDefault> valueWithDefault;
|
||||
var varToControl;
|
||||
Value sourceValue;
|
||||
|
||||
int maxChoices;
|
||||
|
||||
ToggleButton* buttonToControl;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultiChoiceRemapperSourceWithDefault)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
int MultiChoicePropertyComponent::getTotalButtonsHeight (int numButtons)
|
||||
{
|
||||
return numButtons * buttonHeight + 1;
|
||||
}
|
||||
|
||||
MultiChoicePropertyComponent::MultiChoicePropertyComponent (const String& propertyName,
|
||||
const StringArray& choices,
|
||||
const Array<var>& correspondingValues)
|
||||
: 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!
|
||||
jassertquiet (choices.size() == correspondingValues.size());
|
||||
|
||||
for (auto choice : choices)
|
||||
addAndMakeVisible (choiceButtons.add (new ToggleButton (choice)));
|
||||
|
||||
if (preferredHeight >= collapsedHeight)
|
||||
{
|
||||
expandable = true;
|
||||
maxHeight = getTotalButtonsHeight (choiceButtons.size()) + expandAreaHeight;
|
||||
}
|
||||
|
||||
if (isExpandable())
|
||||
{
|
||||
{
|
||||
Path expandShape;
|
||||
expandShape.addTriangle ({ 0, 0 }, { 5, 10 }, { 10, 0});
|
||||
expandButton.setShape (expandShape, true, true, false);
|
||||
}
|
||||
|
||||
expandButton.onClick = [this] { setExpanded (! expanded); };
|
||||
addAndMakeVisible (expandButton);
|
||||
|
||||
lookAndFeelChanged();
|
||||
}
|
||||
}
|
||||
|
||||
MultiChoicePropertyComponent::MultiChoicePropertyComponent (const Value& valueToControl,
|
||||
const String& propertyName,
|
||||
const StringArray& choices,
|
||||
const Array<var>& correspondingValues,
|
||||
int maxChoices)
|
||||
: MultiChoicePropertyComponent (propertyName, choices, correspondingValues)
|
||||
{
|
||||
// The value to control must be an array!
|
||||
jassert (valueToControl.getValue().isArray());
|
||||
|
||||
for (int i = 0; i < choiceButtons.size(); ++i)
|
||||
choiceButtons[i]->getToggleStateValue().referTo (Value (new MultiChoiceRemapperSource (valueToControl,
|
||||
correspondingValues[i],
|
||||
maxChoices)));
|
||||
}
|
||||
|
||||
MultiChoicePropertyComponent::MultiChoicePropertyComponent (ValueWithDefault& valueToControl,
|
||||
const String& propertyName,
|
||||
const StringArray& choices,
|
||||
const Array<var>& correspondingValues,
|
||||
int maxChoices)
|
||||
: MultiChoicePropertyComponent (propertyName, choices, correspondingValues)
|
||||
{
|
||||
valueWithDefault = &valueToControl;
|
||||
|
||||
// The value to control must be an array!
|
||||
jassert (valueWithDefault->get().isArray());
|
||||
|
||||
for (int i = 0; i < choiceButtons.size(); ++i)
|
||||
choiceButtons[i]->getToggleStateValue().referTo (Value (new MultiChoiceRemapperSourceWithDefault (valueWithDefault,
|
||||
correspondingValues[i],
|
||||
maxChoices,
|
||||
choiceButtons[i])));
|
||||
|
||||
valueWithDefault->onDefaultChange = [this] { repaint(); };
|
||||
}
|
||||
|
||||
MultiChoicePropertyComponent::~MultiChoicePropertyComponent()
|
||||
{
|
||||
if (valueWithDefault != nullptr)
|
||||
valueWithDefault->onDefaultChange = nullptr;
|
||||
}
|
||||
|
||||
void MultiChoicePropertyComponent::paint (Graphics& g)
|
||||
{
|
||||
g.setColour (findColour (TextEditor::backgroundColourId));
|
||||
g.fillRect (getLookAndFeel().getPropertyComponentContentPosition (*this));
|
||||
|
||||
if (isExpandable() && ! isExpanded())
|
||||
{
|
||||
g.setColour (findColour (TextEditor::backgroundColourId).contrasting().withAlpha (0.4f));
|
||||
g.drawFittedText ("+ " + String (numHidden) + " more", getLookAndFeel().getPropertyComponentContentPosition (*this)
|
||||
.removeFromBottom (expandAreaHeight).withTrimmedLeft (10),
|
||||
Justification::centredLeft, 1);
|
||||
}
|
||||
|
||||
PropertyComponent::paint (g);
|
||||
}
|
||||
|
||||
void MultiChoicePropertyComponent::resized()
|
||||
{
|
||||
auto bounds = getLookAndFeel().getPropertyComponentContentPosition (*this);
|
||||
|
||||
if (isExpandable())
|
||||
{
|
||||
bounds.removeFromBottom (5);
|
||||
|
||||
auto buttonSlice = bounds.removeFromBottom (10);
|
||||
expandButton.setSize (10, 10);
|
||||
expandButton.setCentrePosition (buttonSlice.getCentre());
|
||||
}
|
||||
|
||||
numHidden = 0;
|
||||
|
||||
for (auto* b : choiceButtons)
|
||||
{
|
||||
if (bounds.getHeight() >= buttonHeight)
|
||||
{
|
||||
b->setVisible (true);
|
||||
b->setBounds (bounds.removeFromTop (buttonHeight).reduced (5, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
b->setVisible (false);
|
||||
++numHidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MultiChoicePropertyComponent::setExpanded (bool shouldBeExpanded) noexcept
|
||||
{
|
||||
if (! isExpandable() || (isExpanded() == shouldBeExpanded))
|
||||
return;
|
||||
|
||||
expanded = shouldBeExpanded;
|
||||
preferredHeight = expanded ? maxHeight : collapsedHeight;
|
||||
|
||||
if (auto* propertyPanel = findParentComponentOfClass<PropertyPanel>())
|
||||
propertyPanel->resized();
|
||||
|
||||
if (onHeightChange != nullptr)
|
||||
onHeightChange();
|
||||
|
||||
expandButton.setTransform (AffineTransform::rotation (expanded ? MathConstants<float>::pi : MathConstants<float>::twoPi,
|
||||
(float) expandButton.getBounds().getCentreX(),
|
||||
(float) expandButton.getBounds().getCentreY()));
|
||||
|
||||
resized();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void MultiChoicePropertyComponent::lookAndFeelChanged()
|
||||
{
|
||||
auto iconColour = findColour (TextEditor::backgroundColourId).contrasting();
|
||||
expandButton.setColours (iconColour, iconColour.darker(), iconColour.darker());
|
||||
|
||||
if (valueWithDefault != nullptr)
|
||||
{
|
||||
auto usingDefault = valueWithDefault->isUsingDefault();
|
||||
|
||||
for (auto* button : choiceButtons)
|
||||
updateButtonTickColour (button, usingDefault);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace juce
|
140
deps/juce/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h
vendored
Normal file
140
deps/juce/modules/juce_gui_basics/properties/juce_MultiChoicePropertyComponent.h
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A PropertyComponent that shows its value as an expandable list of ToggleButtons.
|
||||
|
||||
This type of property component contains a list of options where multiple options
|
||||
can be selected at once.
|
||||
|
||||
@see PropertyComponent, PropertyPanel
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class MultiChoicePropertyComponent : public PropertyComponent
|
||||
{
|
||||
private:
|
||||
/** Delegating constructor. */
|
||||
MultiChoicePropertyComponent (const String&, const StringArray&, const Array<var>&);
|
||||
|
||||
public:
|
||||
/** Creates the component. Note that the underlying var object that the Value refers to must be an array.
|
||||
|
||||
@param valueToControl the value 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.
|
||||
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
|
||||
@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 (const Value& valueToControl,
|
||||
const String& propertyName,
|
||||
const StringArray& choices,
|
||||
const Array<var>& correspondingValues,
|
||||
int maxChoices = -1);
|
||||
|
||||
/** Creates the component using a ValueWithDefault 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 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.
|
||||
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
|
||||
@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,
|
||||
const String& propertyName,
|
||||
const StringArray& choices,
|
||||
const Array<var>& correspondingValues,
|
||||
int maxChoices = -1);
|
||||
|
||||
~MultiChoicePropertyComponent() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the list of options is expanded. */
|
||||
bool isExpanded() const noexcept { return expanded; }
|
||||
|
||||
/** Returns true if the list of options has been truncated and can be expanded. */
|
||||
bool isExpandable() const noexcept { return expandable; }
|
||||
|
||||
/** Expands or shrinks the list of options if they are not all visible.
|
||||
|
||||
N.B. This will just set the preferredHeight value of the PropertyComponent and attempt to
|
||||
call PropertyPanel::resized(), so if you are not displaying this object in a PropertyPanel
|
||||
then you should use the onHeightChange callback to resize it when the height changes.
|
||||
|
||||
@see onHeightChange
|
||||
*/
|
||||
void setExpanded (bool expanded) noexcept;
|
||||
|
||||
/** You can assign a lambda to this callback object to have it called when the MultiChoicePropertyComponent height changes. */
|
||||
std::function<void()> onHeightChange;
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paint (Graphics& g) override;
|
||||
/** @internal */
|
||||
void resized() override;
|
||||
/** @internal */
|
||||
void refresh() override {}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class MultiChoiceRemapperSource;
|
||||
class MultiChoiceRemapperSourceWithDefault;
|
||||
|
||||
//==============================================================================
|
||||
static int getTotalButtonsHeight (int);
|
||||
void lookAndFeelChanged() override;
|
||||
|
||||
//==============================================================================
|
||||
WeakReference<ValueWithDefault> valueWithDefault;
|
||||
|
||||
static constexpr int collapsedHeight = 125;
|
||||
static constexpr int buttonHeight = 25;
|
||||
static constexpr int expandAreaHeight = 20;
|
||||
|
||||
int maxHeight = 0, numHidden = 0;
|
||||
bool expandable = false, expanded = false;
|
||||
|
||||
OwnedArray<ToggleButton> choiceButtons;
|
||||
ShapeButton expandButton { "Expand", Colours::transparentBlack, Colours::transparentBlack, Colours::transparentBlack };
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultiChoicePropertyComponent)
|
||||
};
|
||||
|
||||
} // namespace juce
|
56
deps/juce/modules/juce_gui_basics/properties/juce_PropertyComponent.cpp
vendored
Normal file
56
deps/juce/modules/juce_gui_basics/properties/juce_PropertyComponent.cpp
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
PropertyComponent::PropertyComponent (const String& name, int height)
|
||||
: Component (name), preferredHeight (height)
|
||||
{
|
||||
jassert (name.isNotEmpty());
|
||||
}
|
||||
|
||||
PropertyComponent::~PropertyComponent() {}
|
||||
|
||||
void PropertyComponent::paint (Graphics& g)
|
||||
{
|
||||
auto& lf = getLookAndFeel();
|
||||
|
||||
lf.drawPropertyComponentBackground (g, getWidth(), getHeight(), *this);
|
||||
lf.drawPropertyComponentLabel (g, getWidth(), getHeight(), *this);
|
||||
}
|
||||
|
||||
void PropertyComponent::resized()
|
||||
{
|
||||
if (auto c = getChildComponent(0))
|
||||
c->setBounds (getLookAndFeel().getPropertyComponentContentPosition (*this));
|
||||
}
|
||||
|
||||
void PropertyComponent::enablementChanged()
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
|
||||
} // namespace juce
|
145
deps/juce/modules/juce_gui_basics/properties/juce_PropertyComponent.h
vendored
Normal file
145
deps/juce/modules/juce_gui_basics/properties/juce_PropertyComponent.h
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A base class for a component that goes in a PropertyPanel and displays one of
|
||||
an item's properties.
|
||||
|
||||
Subclasses of this are used to display a property in various forms, e.g. a
|
||||
ChoicePropertyComponent shows its value as a combo box; a SliderPropertyComponent
|
||||
shows its value as a slider; a TextPropertyComponent as a text box, etc.
|
||||
|
||||
A subclass must implement the refresh() method which will be called to tell the
|
||||
component to update itself, and is also responsible for calling this it when the
|
||||
item that it refers to is changed.
|
||||
|
||||
@see PropertyPanel, TextPropertyComponent, SliderPropertyComponent,
|
||||
ChoicePropertyComponent, ButtonPropertyComponent, BooleanPropertyComponent
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API PropertyComponent : public Component,
|
||||
public SettableTooltipClient
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a PropertyComponent.
|
||||
|
||||
@param propertyName the name is stored as this component's name, and is
|
||||
used as the name displayed next to this component in
|
||||
a property panel
|
||||
@param preferredHeight the height that the component should be given - some
|
||||
items may need to be larger than a normal row height.
|
||||
This value can also be set if a subclass changes the
|
||||
preferredHeight member variable.
|
||||
*/
|
||||
PropertyComponent (const String& propertyName,
|
||||
int preferredHeight = 25);
|
||||
|
||||
/** Destructor. */
|
||||
~PropertyComponent() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns this item's preferred height.
|
||||
|
||||
This value is specified either in the constructor or by a subclass changing the
|
||||
preferredHeight member variable.
|
||||
*/
|
||||
int getPreferredHeight() const noexcept { return preferredHeight; }
|
||||
|
||||
void setPreferredHeight (int newHeight) noexcept { preferredHeight = newHeight; }
|
||||
|
||||
//==============================================================================
|
||||
/** Updates the property component if the item it refers to has changed.
|
||||
|
||||
A subclass must implement this method, and other objects may call it to
|
||||
force it to refresh itself.
|
||||
|
||||
The subclass should be economical in the amount of work is done, so for
|
||||
example it should check whether it really needs to do a repaint rather than
|
||||
just doing one every time this method is called, as it may be called when
|
||||
the value being displayed hasn't actually changed.
|
||||
*/
|
||||
virtual void refresh() = 0;
|
||||
|
||||
|
||||
/** The default paint method fills the background and draws a label for the
|
||||
item's name.
|
||||
|
||||
@see LookAndFeel::drawPropertyComponentBackground(), LookAndFeel::drawPropertyComponentLabel()
|
||||
*/
|
||||
void paint (Graphics&) override;
|
||||
|
||||
/** The default resize method positions any child component to the right of this
|
||||
one, based on the look and feel's default label size.
|
||||
*/
|
||||
void resized() override;
|
||||
|
||||
/** By default, this just repaints the component. */
|
||||
void enablementChanged() override;
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the combo box.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
backgroundColourId = 0x1008300, /**< The background colour to fill the component with. */
|
||||
labelTextColourId = 0x1008301, /**< The colour for the property's label text. */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** This abstract base class is implemented by LookAndFeel classes. */
|
||||
struct JUCE_API LookAndFeelMethods
|
||||
{
|
||||
virtual ~LookAndFeelMethods() = default;
|
||||
|
||||
virtual void drawPropertyPanelSectionHeader (Graphics&, const String& name, bool isOpen, int width, int height) = 0;
|
||||
virtual void drawPropertyComponentBackground (Graphics&, int width, int height, PropertyComponent&) = 0;
|
||||
virtual void drawPropertyComponentLabel (Graphics&, int width, int height, PropertyComponent&) = 0;
|
||||
virtual Rectangle<int> getPropertyComponentContentPosition (PropertyComponent&) = 0;
|
||||
virtual int getPropertyPanelSectionHeaderHeight (const String& sectionTitle) = 0;
|
||||
};
|
||||
|
||||
protected:
|
||||
/** Used by the PropertyPanel to determine how high this component needs to be.
|
||||
A subclass can update this value in its constructor but shouldn't alter it later
|
||||
as changes won't necessarily be picked up.
|
||||
*/
|
||||
int preferredHeight;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyComponent)
|
||||
};
|
||||
|
||||
} // namespace juce
|
396
deps/juce/modules/juce_gui_basics/properties/juce_PropertyPanel.cpp
vendored
Normal file
396
deps/juce/modules/juce_gui_basics/properties/juce_PropertyPanel.cpp
vendored
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
struct PropertyPanel::SectionComponent : public Component
|
||||
{
|
||||
SectionComponent (const String& sectionTitle,
|
||||
const Array<PropertyComponent*>& newProperties,
|
||||
bool sectionIsOpen,
|
||||
int extraPadding)
|
||||
: Component (sectionTitle),
|
||||
isOpen (sectionIsOpen),
|
||||
padding (extraPadding)
|
||||
{
|
||||
lookAndFeelChanged();
|
||||
|
||||
propertyComps.addArray (newProperties);
|
||||
|
||||
for (auto* propertyComponent : propertyComps)
|
||||
{
|
||||
addAndMakeVisible (propertyComponent);
|
||||
propertyComponent->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
~SectionComponent() override
|
||||
{
|
||||
propertyComps.clear();
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
if (titleHeight > 0)
|
||||
getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen, getWidth(), titleHeight);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
auto y = titleHeight;
|
||||
|
||||
for (auto* propertyComponent : propertyComps)
|
||||
{
|
||||
propertyComponent->setBounds (1, y, getWidth() - 2, propertyComponent->getPreferredHeight());
|
||||
y = propertyComponent->getBottom() + padding;
|
||||
}
|
||||
}
|
||||
|
||||
void lookAndFeelChanged() override
|
||||
{
|
||||
titleHeight = getLookAndFeel().getPropertyPanelSectionHeaderHeight (getName());
|
||||
resized();
|
||||
repaint();
|
||||
}
|
||||
|
||||
int getPreferredHeight() const
|
||||
{
|
||||
auto y = titleHeight;
|
||||
|
||||
auto numComponents = propertyComps.size();
|
||||
|
||||
if (numComponents > 0 && isOpen)
|
||||
{
|
||||
for (auto* propertyComponent : propertyComps)
|
||||
y += propertyComponent->getPreferredHeight();
|
||||
|
||||
y += (numComponents - 1) * padding;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
void setOpen (bool open)
|
||||
{
|
||||
if (isOpen != open)
|
||||
{
|
||||
isOpen = open;
|
||||
|
||||
for (auto* propertyComponent : propertyComps)
|
||||
propertyComponent->setVisible (open);
|
||||
|
||||
if (auto* propertyPanel = findParentComponentOfClass<PropertyPanel>())
|
||||
propertyPanel->resized();
|
||||
}
|
||||
}
|
||||
|
||||
void refreshAll() const
|
||||
{
|
||||
for (auto* propertyComponent : propertyComps)
|
||||
propertyComponent->refresh();
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e) override
|
||||
{
|
||||
if (e.getMouseDownX() < titleHeight
|
||||
&& e.x < titleHeight
|
||||
&& e.getNumberOfClicks() != 2)
|
||||
mouseDoubleClick (e);
|
||||
}
|
||||
|
||||
void mouseDoubleClick (const MouseEvent& e) override
|
||||
{
|
||||
if (e.y < titleHeight)
|
||||
setOpen (! isOpen);
|
||||
}
|
||||
|
||||
OwnedArray<PropertyComponent> propertyComps;
|
||||
int titleHeight;
|
||||
bool isOpen;
|
||||
int padding;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (SectionComponent)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct PropertyPanel::PropertyHolderComponent : public Component
|
||||
{
|
||||
PropertyHolderComponent() {}
|
||||
|
||||
void paint (Graphics&) override {}
|
||||
|
||||
void updateLayout (int width)
|
||||
{
|
||||
auto y = 0;
|
||||
|
||||
for (auto* section : sections)
|
||||
{
|
||||
section->setBounds (0, y, width, section->getPreferredHeight());
|
||||
y = section->getBottom();
|
||||
}
|
||||
|
||||
setSize (width, y);
|
||||
repaint();
|
||||
}
|
||||
|
||||
void refreshAll() const
|
||||
{
|
||||
for (auto* section : sections)
|
||||
section->refreshAll();
|
||||
}
|
||||
|
||||
void insertSection (int indexToInsertAt, SectionComponent* newSection)
|
||||
{
|
||||
sections.insert (indexToInsertAt, newSection);
|
||||
addAndMakeVisible (newSection, 0);
|
||||
}
|
||||
|
||||
SectionComponent* getSectionWithNonEmptyName (int targetIndex) const noexcept
|
||||
{
|
||||
auto index = 0;
|
||||
for (auto* section : sections)
|
||||
{
|
||||
if (section->getName().isNotEmpty())
|
||||
if (index++ == targetIndex)
|
||||
return section;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OwnedArray<SectionComponent> sections;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (PropertyHolderComponent)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PropertyPanel::PropertyPanel()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
PropertyPanel::PropertyPanel (const String& name) : Component (name)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void PropertyPanel::init()
|
||||
{
|
||||
messageWhenEmpty = TRANS("(nothing selected)");
|
||||
|
||||
addAndMakeVisible (viewport);
|
||||
viewport.setViewedComponent (propertyHolderComponent = new PropertyHolderComponent());
|
||||
viewport.setFocusContainerType (FocusContainerType::keyboardFocusContainer);
|
||||
}
|
||||
|
||||
PropertyPanel::~PropertyPanel()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PropertyPanel::paint (Graphics& g)
|
||||
{
|
||||
if (isEmpty())
|
||||
{
|
||||
g.setColour (Colours::black.withAlpha (0.5f));
|
||||
g.setFont (14.0f);
|
||||
g.drawText (messageWhenEmpty, getLocalBounds().withHeight (30),
|
||||
Justification::centred, true);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyPanel::resized()
|
||||
{
|
||||
viewport.setBounds (getLocalBounds());
|
||||
updatePropHolderLayout();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PropertyPanel::clear()
|
||||
{
|
||||
if (! isEmpty())
|
||||
{
|
||||
propertyHolderComponent->sections.clear();
|
||||
updatePropHolderLayout();
|
||||
}
|
||||
}
|
||||
|
||||
bool PropertyPanel::isEmpty() const
|
||||
{
|
||||
return propertyHolderComponent->sections.size() == 0;
|
||||
}
|
||||
|
||||
int PropertyPanel::getTotalContentHeight() const
|
||||
{
|
||||
return propertyHolderComponent->getHeight();
|
||||
}
|
||||
|
||||
void PropertyPanel::addProperties (const Array<PropertyComponent*>& newProperties,
|
||||
int extraPaddingBetweenComponents)
|
||||
{
|
||||
if (isEmpty())
|
||||
repaint();
|
||||
|
||||
propertyHolderComponent->insertSection (-1, new SectionComponent ({}, newProperties, true, extraPaddingBetweenComponents));
|
||||
updatePropHolderLayout();
|
||||
}
|
||||
|
||||
void PropertyPanel::addSection (const String& sectionTitle,
|
||||
const Array<PropertyComponent*>& newProperties,
|
||||
bool shouldBeOpen,
|
||||
int indexToInsertAt,
|
||||
int extraPaddingBetweenComponents)
|
||||
{
|
||||
jassert (sectionTitle.isNotEmpty());
|
||||
|
||||
if (isEmpty())
|
||||
repaint();
|
||||
|
||||
propertyHolderComponent->insertSection (indexToInsertAt, new SectionComponent (sectionTitle,
|
||||
newProperties,
|
||||
shouldBeOpen,
|
||||
extraPaddingBetweenComponents));
|
||||
|
||||
updatePropHolderLayout();
|
||||
}
|
||||
|
||||
void PropertyPanel::updatePropHolderLayout() const
|
||||
{
|
||||
auto maxWidth = viewport.getMaximumVisibleWidth();
|
||||
propertyHolderComponent->updateLayout (maxWidth);
|
||||
|
||||
auto newMaxWidth = viewport.getMaximumVisibleWidth();
|
||||
if (maxWidth != newMaxWidth)
|
||||
{
|
||||
// need to do this twice because of scrollbars changing the size, etc.
|
||||
propertyHolderComponent->updateLayout (newMaxWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyPanel::refreshAll() const
|
||||
{
|
||||
propertyHolderComponent->refreshAll();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
StringArray PropertyPanel::getSectionNames() const
|
||||
{
|
||||
StringArray s;
|
||||
|
||||
for (auto* section : propertyHolderComponent->sections)
|
||||
{
|
||||
if (section->getName().isNotEmpty())
|
||||
s.add (section->getName());
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool PropertyPanel::isSectionOpen (int sectionIndex) const
|
||||
{
|
||||
if (auto* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex))
|
||||
return s->isOpen;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PropertyPanel::setSectionOpen (int sectionIndex, bool shouldBeOpen)
|
||||
{
|
||||
if (auto* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex))
|
||||
s->setOpen (shouldBeOpen);
|
||||
}
|
||||
|
||||
void PropertyPanel::setSectionEnabled (int sectionIndex, bool shouldBeEnabled)
|
||||
{
|
||||
if (auto* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex))
|
||||
s->setEnabled (shouldBeEnabled);
|
||||
}
|
||||
|
||||
void PropertyPanel::removeSection (int sectionIndex)
|
||||
{
|
||||
if (auto* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex))
|
||||
{
|
||||
propertyHolderComponent->sections.removeObject (s);
|
||||
updatePropHolderLayout();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<XmlElement> PropertyPanel::getOpennessState() const
|
||||
{
|
||||
auto xml = std::make_unique<XmlElement> ("PROPERTYPANELSTATE");
|
||||
|
||||
xml->setAttribute ("scrollPos", viewport.getViewPositionY());
|
||||
|
||||
auto sections = getSectionNames();
|
||||
for (auto s : sections)
|
||||
{
|
||||
if (s.isNotEmpty())
|
||||
{
|
||||
auto* e = xml->createNewChildElement ("SECTION");
|
||||
e->setAttribute ("name", s);
|
||||
e->setAttribute ("open", isSectionOpen (sections.indexOf (s)) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
void PropertyPanel::restoreOpennessState (const XmlElement& xml)
|
||||
{
|
||||
if (xml.hasTagName ("PROPERTYPANELSTATE"))
|
||||
{
|
||||
auto sections = getSectionNames();
|
||||
|
||||
for (auto* e : xml.getChildWithTagNameIterator ("SECTION"))
|
||||
{
|
||||
setSectionOpen (sections.indexOf (e->getStringAttribute ("name")),
|
||||
e->getBoolAttribute ("open"));
|
||||
}
|
||||
|
||||
viewport.setViewPosition (viewport.getViewPositionX(),
|
||||
xml.getIntAttribute ("scrollPos", viewport.getViewPositionY()));
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PropertyPanel::setMessageWhenEmpty (const String& newMessage)
|
||||
{
|
||||
if (messageWhenEmpty != newMessage)
|
||||
{
|
||||
messageWhenEmpty = newMessage;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
const String& PropertyPanel::getMessageWhenEmpty() const noexcept
|
||||
{
|
||||
return messageWhenEmpty;
|
||||
}
|
||||
|
||||
} // namespace juce
|
177
deps/juce/modules/juce_gui_basics/properties/juce_PropertyPanel.h
vendored
Normal file
177
deps/juce/modules/juce_gui_basics/properties/juce_PropertyPanel.h
vendored
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A panel that holds a list of PropertyComponent objects.
|
||||
|
||||
This panel displays a list of PropertyComponents, and allows them to be organised
|
||||
into collapsible sections.
|
||||
|
||||
To use, simply create one of these and add your properties to it with addProperties()
|
||||
or addSection().
|
||||
|
||||
@see PropertyComponent
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API PropertyPanel : public Component
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty property panel. */
|
||||
PropertyPanel();
|
||||
|
||||
/** Creates an empty property panel. */
|
||||
PropertyPanel (const String& name);
|
||||
|
||||
/** Destructor. */
|
||||
~PropertyPanel() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Deletes all property components from the panel. */
|
||||
void clear();
|
||||
|
||||
/** Adds a set of properties to the panel.
|
||||
|
||||
The components in the list will be owned by this object and will be automatically
|
||||
deleted later on when no longer needed.
|
||||
|
||||
These properties are added without them being inside a named section. If you
|
||||
want them to be kept together in a collapsible section, use addSection() instead.
|
||||
*/
|
||||
void addProperties (const Array<PropertyComponent*>& newPropertyComponents,
|
||||
int extraPaddingBetweenComponents = 0);
|
||||
|
||||
/** Adds a set of properties to the panel.
|
||||
|
||||
These properties are added under a section heading with a plus/minus button that
|
||||
allows it to be opened and closed. If indexToInsertAt is < 0 then it will be added
|
||||
at the end of the list, or before the given index if the index is non-zero.
|
||||
|
||||
The components in the list will be owned by this object and will be automatically
|
||||
deleted later on when no longer needed.
|
||||
|
||||
To add properties without them being in a section, use addProperties().
|
||||
*/
|
||||
void addSection (const String& sectionTitle,
|
||||
const Array<PropertyComponent*>& newPropertyComponents,
|
||||
bool shouldSectionInitiallyBeOpen = true,
|
||||
int indexToInsertAt = -1,
|
||||
int extraPaddingBetweenComponents = 0);
|
||||
|
||||
/** Calls the refresh() method of all PropertyComponents in the panel */
|
||||
void refreshAll() const;
|
||||
|
||||
/** Returns true if the panel contains no properties. */
|
||||
bool isEmpty() const;
|
||||
|
||||
/** Returns the height that the panel needs in order to display all of its content
|
||||
without scrolling.
|
||||
*/
|
||||
int getTotalContentHeight() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a list of all the names of sections in the panel.
|
||||
These are the sections that have been added with addSection().
|
||||
*/
|
||||
StringArray getSectionNames() const;
|
||||
|
||||
/** Returns true if the section at this index is currently open.
|
||||
The index is from 0 up to the number of items returned by getSectionNames().
|
||||
*/
|
||||
bool isSectionOpen (int sectionIndex) const;
|
||||
|
||||
/** Opens or closes one of the sections.
|
||||
The index is from 0 up to the number of items returned by getSectionNames().
|
||||
*/
|
||||
void setSectionOpen (int sectionIndex, bool shouldBeOpen);
|
||||
|
||||
/** Enables or disables one of the sections.
|
||||
The index is from 0 up to the number of items returned by getSectionNames().
|
||||
*/
|
||||
void setSectionEnabled (int sectionIndex, bool shouldBeEnabled);
|
||||
|
||||
/** Remove one of the sections using the section index.
|
||||
The index is from 0 up to the number of items returned by getSectionNames().
|
||||
*/
|
||||
void removeSection (int sectionIndex);
|
||||
|
||||
//==============================================================================
|
||||
/** Saves the current state of open/closed sections so it can be restored later.
|
||||
To restore this state, use restoreOpennessState().
|
||||
@see restoreOpennessState
|
||||
*/
|
||||
std::unique_ptr<XmlElement> getOpennessState() const;
|
||||
|
||||
/** Restores a previously saved arrangement of open/closed sections.
|
||||
|
||||
This will try to restore a snapshot of the panel's state that was created by
|
||||
the getOpennessState() method. If any of the sections named in the original
|
||||
XML aren't present, they will be ignored.
|
||||
|
||||
@see getOpennessState
|
||||
*/
|
||||
void restoreOpennessState (const XmlElement& newState);
|
||||
|
||||
//==============================================================================
|
||||
/** Sets a message to be displayed when there are no properties in the panel.
|
||||
The default message is "nothing selected".
|
||||
*/
|
||||
void setMessageWhenEmpty (const String& newMessage);
|
||||
|
||||
/** Returns the message that is displayed when there are no properties.
|
||||
@see setMessageWhenEmpty
|
||||
*/
|
||||
const String& getMessageWhenEmpty() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the PropertyPanel's internal Viewport. */
|
||||
Viewport& getViewport() noexcept { return viewport; }
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void paint (Graphics&) override;
|
||||
/** @internal */
|
||||
void resized() override;
|
||||
|
||||
private:
|
||||
Viewport viewport;
|
||||
struct SectionComponent;
|
||||
struct PropertyHolderComponent;
|
||||
PropertyHolderComponent* propertyHolderComponent;
|
||||
String messageWhenEmpty;
|
||||
|
||||
void init();
|
||||
void updatePropHolderLayout() const;
|
||||
void updatePropHolderLayout (int width) const;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyPanel)
|
||||
};
|
||||
|
||||
} // namespace juce
|
86
deps/juce/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp
vendored
Normal file
86
deps/juce/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
SliderPropertyComponent::SliderPropertyComponent (const String& name,
|
||||
const double rangeMin,
|
||||
const double rangeMax,
|
||||
const double interval,
|
||||
const double skewFactor,
|
||||
bool symmetricSkew)
|
||||
: PropertyComponent (name)
|
||||
{
|
||||
addAndMakeVisible (slider);
|
||||
|
||||
slider.setRange (rangeMin, rangeMax, interval);
|
||||
slider.setSkewFactor (skewFactor, symmetricSkew);
|
||||
slider.setSliderStyle (Slider::LinearBar);
|
||||
|
||||
slider.onValueChange = [this]
|
||||
{
|
||||
if (getValue() != slider.getValue())
|
||||
setValue (slider.getValue());
|
||||
};
|
||||
}
|
||||
|
||||
SliderPropertyComponent::SliderPropertyComponent (const Value& valueToControl,
|
||||
const String& name,
|
||||
const double rangeMin,
|
||||
const double rangeMax,
|
||||
const double interval,
|
||||
const double skewFactor,
|
||||
bool symmetricSkew)
|
||||
: PropertyComponent (name)
|
||||
{
|
||||
addAndMakeVisible (slider);
|
||||
|
||||
slider.setRange (rangeMin, rangeMax, interval);
|
||||
slider.setSkewFactor (skewFactor, symmetricSkew);
|
||||
slider.setSliderStyle (Slider::LinearBar);
|
||||
|
||||
slider.getValueObject().referTo (valueToControl);
|
||||
}
|
||||
|
||||
SliderPropertyComponent::~SliderPropertyComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void SliderPropertyComponent::setValue (const double /*newValue*/)
|
||||
{
|
||||
}
|
||||
|
||||
double SliderPropertyComponent::getValue() const
|
||||
{
|
||||
return slider.getValue();
|
||||
}
|
||||
|
||||
void SliderPropertyComponent::refresh()
|
||||
{
|
||||
slider.setValue (getValue(), dontSendNotification);
|
||||
}
|
||||
|
||||
} // namespace juce
|
107
deps/juce/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h
vendored
Normal file
107
deps/juce/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A PropertyComponent that shows its value as a slider.
|
||||
|
||||
@see PropertyComponent, Slider
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API SliderPropertyComponent : public PropertyComponent
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates the property component.
|
||||
|
||||
The ranges, interval and skew factor are passed to the Slider component.
|
||||
|
||||
If you need to customise the slider in other ways, your constructor can
|
||||
access the slider member variable and change it directly.
|
||||
*/
|
||||
SliderPropertyComponent (const String& propertyName,
|
||||
double rangeMin,
|
||||
double rangeMax,
|
||||
double interval,
|
||||
double skewFactor = 1.0,
|
||||
bool symmetricSkew = false);
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates the property component.
|
||||
|
||||
The ranges, interval and skew factor are passed to the Slider component.
|
||||
|
||||
If you need to customise the slider in other ways, your constructor can
|
||||
access the slider member variable and change it directly.
|
||||
|
||||
Note that if you call this constructor then you must use the Value to interact with
|
||||
the value, and you can't override the class with your own setValue or getValue methods.
|
||||
If you want to use those methods, call the other constructor instead.
|
||||
*/
|
||||
SliderPropertyComponent (const Value& valueToControl,
|
||||
const String& propertyName,
|
||||
double rangeMin,
|
||||
double rangeMax,
|
||||
double interval,
|
||||
double skewFactor = 1.0,
|
||||
bool symmetricSkew = false);
|
||||
|
||||
/** Destructor. */
|
||||
~SliderPropertyComponent() override;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Called when the user moves the slider to change its value.
|
||||
|
||||
Your subclass must use this method to update whatever item this property
|
||||
represents.
|
||||
*/
|
||||
virtual void setValue (double newValue);
|
||||
|
||||
/** Returns the value that the slider should show. */
|
||||
virtual double getValue() const;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void refresh() override;
|
||||
|
||||
protected:
|
||||
/** The slider component being used in this component.
|
||||
Your subclass has access to this in case it needs to customise it in some way.
|
||||
*/
|
||||
Slider slider;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderPropertyComponent)
|
||||
};
|
||||
|
||||
} // namespace juce
|
266
deps/juce/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp
vendored
Normal file
266
deps/juce/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
class TextPropertyComponent::LabelComp : public Label,
|
||||
public FileDragAndDropTarget
|
||||
{
|
||||
public:
|
||||
LabelComp (TextPropertyComponent& tpc, int charLimit, bool multiline, bool editable)
|
||||
: Label ({}, {}),
|
||||
owner (tpc),
|
||||
maxChars (charLimit),
|
||||
isMultiline (multiline)
|
||||
{
|
||||
setEditable (editable, editable);
|
||||
|
||||
updateColours();
|
||||
}
|
||||
|
||||
bool isInterestedInFileDrag (const StringArray&) override
|
||||
{
|
||||
return interestedInFileDrag;
|
||||
}
|
||||
|
||||
void filesDropped (const StringArray& files, int, int) override
|
||||
{
|
||||
setText (getText() + files.joinIntoString (isMultiline ? "\n" : ", "), sendNotificationSync);
|
||||
showEditor();
|
||||
}
|
||||
|
||||
TextEditor* createEditorComponent() override
|
||||
{
|
||||
auto* ed = Label::createEditorComponent();
|
||||
ed->setInputRestrictions (maxChars);
|
||||
|
||||
if (isMultiline)
|
||||
{
|
||||
ed->setMultiLine (true, true);
|
||||
ed->setReturnKeyStartsNewLine (true);
|
||||
}
|
||||
|
||||
return ed;
|
||||
}
|
||||
|
||||
void textWasEdited() override
|
||||
{
|
||||
owner.textWasEdited();
|
||||
}
|
||||
|
||||
void updateColours()
|
||||
{
|
||||
setColour (backgroundColourId, owner.findColour (TextPropertyComponent::backgroundColourId));
|
||||
setColour (outlineColourId, owner.findColour (TextPropertyComponent::outlineColourId));
|
||||
setColour (textColourId, owner.findColour (TextPropertyComponent::textColourId));
|
||||
repaint();
|
||||
}
|
||||
|
||||
void setInterestedInFileDrag (bool isInterested)
|
||||
{
|
||||
interestedInFileDrag = isInterested;
|
||||
}
|
||||
|
||||
void setTextToDisplayWhenEmpty (const String& text, float alpha)
|
||||
{
|
||||
textToDisplayWhenEmpty = text;
|
||||
alphaToUseForEmptyText = alpha;
|
||||
}
|
||||
|
||||
void paintOverChildren (Graphics& g) override
|
||||
{
|
||||
if (getText().isEmpty() && ! isBeingEdited())
|
||||
{
|
||||
auto& lf = owner.getLookAndFeel();
|
||||
auto textArea = lf.getLabelBorderSize (*this).subtractedFrom (getLocalBounds());
|
||||
auto labelFont = lf.getLabelFont (*this);
|
||||
|
||||
g.setColour (owner.findColour (TextPropertyComponent::textColourId).withAlpha (alphaToUseForEmptyText));
|
||||
g.setFont (labelFont);
|
||||
|
||||
g.drawFittedText (textToDisplayWhenEmpty, textArea, getJustificationType(),
|
||||
jmax (1, (int) ((float) textArea.getHeight() / labelFont.getHeight())),
|
||||
getMinimumHorizontalScale());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TextPropertyComponent& owner;
|
||||
|
||||
int maxChars;
|
||||
bool isMultiline;
|
||||
bool interestedInFileDrag = true;
|
||||
|
||||
String textToDisplayWhenEmpty;
|
||||
float alphaToUseForEmptyText = 0.0f;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class TextPropertyComponent::RemapperValueSourceWithDefault : public Value::ValueSource
|
||||
{
|
||||
public:
|
||||
RemapperValueSourceWithDefault (ValueWithDefault* vwd)
|
||||
: valueWithDefault (vwd)
|
||||
{
|
||||
}
|
||||
|
||||
var getValue() const override
|
||||
{
|
||||
if (valueWithDefault == nullptr || valueWithDefault->isUsingDefault())
|
||||
return {};
|
||||
|
||||
return valueWithDefault->get();
|
||||
}
|
||||
|
||||
void setValue (const var& newValue) override
|
||||
{
|
||||
if (valueWithDefault == nullptr)
|
||||
return;
|
||||
|
||||
if (newValue.toString().isEmpty())
|
||||
valueWithDefault->resetToDefault();
|
||||
else
|
||||
*valueWithDefault = newValue;
|
||||
}
|
||||
|
||||
private:
|
||||
WeakReference<ValueWithDefault> valueWithDefault;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RemapperValueSourceWithDefault)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
TextPropertyComponent::TextPropertyComponent (const String& name,
|
||||
int maxNumChars,
|
||||
bool multiLine,
|
||||
bool isEditable)
|
||||
: PropertyComponent (name),
|
||||
isMultiLine (multiLine)
|
||||
{
|
||||
createEditor (maxNumChars, isEditable);
|
||||
}
|
||||
|
||||
TextPropertyComponent::TextPropertyComponent (const Value& valueToControl, const String& name,
|
||||
int maxNumChars, bool multiLine, bool isEditable)
|
||||
: TextPropertyComponent (name, maxNumChars, multiLine, isEditable)
|
||||
{
|
||||
textEditor->getTextValue().referTo (valueToControl);
|
||||
}
|
||||
|
||||
TextPropertyComponent::TextPropertyComponent (ValueWithDefault& valueToControl, const String& name,
|
||||
int maxNumChars, bool multiLine, bool isEditable)
|
||||
: TextPropertyComponent (name, maxNumChars, multiLine, isEditable)
|
||||
{
|
||||
valueWithDefault = &valueToControl;
|
||||
|
||||
textEditor->getTextValue().referTo (Value (new RemapperValueSourceWithDefault (valueWithDefault)));
|
||||
textEditor->setTextToDisplayWhenEmpty (valueWithDefault->getDefault(), 0.5f);
|
||||
|
||||
valueWithDefault->onDefaultChange = [this]
|
||||
{
|
||||
textEditor->setTextToDisplayWhenEmpty (valueWithDefault->getDefault(), 0.5f);
|
||||
repaint();
|
||||
};
|
||||
}
|
||||
|
||||
TextPropertyComponent::~TextPropertyComponent()
|
||||
{
|
||||
if (valueWithDefault != nullptr)
|
||||
valueWithDefault->onDefaultChange = nullptr;
|
||||
}
|
||||
|
||||
void TextPropertyComponent::setText (const String& newText)
|
||||
{
|
||||
textEditor->setText (newText, sendNotificationSync);
|
||||
}
|
||||
|
||||
String TextPropertyComponent::getText() const
|
||||
{
|
||||
return textEditor->getText();
|
||||
}
|
||||
|
||||
Value& TextPropertyComponent::getValue() const
|
||||
{
|
||||
return textEditor->getTextValue();
|
||||
}
|
||||
|
||||
void TextPropertyComponent::createEditor (int maxNumChars, bool isEditable)
|
||||
{
|
||||
textEditor.reset (new LabelComp (*this, maxNumChars, isMultiLine, isEditable));
|
||||
addAndMakeVisible (textEditor.get());
|
||||
|
||||
if (isMultiLine)
|
||||
{
|
||||
textEditor->setJustificationType (Justification::topLeft);
|
||||
preferredHeight = 100;
|
||||
}
|
||||
}
|
||||
|
||||
void TextPropertyComponent::refresh()
|
||||
{
|
||||
textEditor->setText (getText(), dontSendNotification);
|
||||
}
|
||||
|
||||
void TextPropertyComponent::textWasEdited()
|
||||
{
|
||||
auto newText = textEditor->getText();
|
||||
|
||||
if (getText() != newText)
|
||||
setText (newText);
|
||||
|
||||
callListeners();
|
||||
}
|
||||
|
||||
void TextPropertyComponent::addListener (TextPropertyComponent::Listener* l) { listenerList.add (l); }
|
||||
void TextPropertyComponent::removeListener (TextPropertyComponent::Listener* l) { listenerList.remove (l); }
|
||||
|
||||
void TextPropertyComponent::callListeners()
|
||||
{
|
||||
Component::BailOutChecker checker (this);
|
||||
listenerList.callChecked (checker, [this] (Listener& l) { l.textPropertyComponentChanged (this); });
|
||||
}
|
||||
|
||||
void TextPropertyComponent::colourChanged()
|
||||
{
|
||||
PropertyComponent::colourChanged();
|
||||
textEditor->updateColours();
|
||||
}
|
||||
|
||||
void TextPropertyComponent::setInterestedInFileDrag (bool isInterested)
|
||||
{
|
||||
if (textEditor != nullptr)
|
||||
textEditor->setInterestedInFileDrag (isInterested);
|
||||
}
|
||||
|
||||
void TextPropertyComponent::setEditable (bool isEditable)
|
||||
{
|
||||
if (textEditor != nullptr)
|
||||
textEditor->setEditable (isEditable, isEditable);
|
||||
}
|
||||
|
||||
} // namespace juce
|
191
deps/juce/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h
vendored
Normal file
191
deps/juce/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
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 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A PropertyComponent that shows its value as editable text.
|
||||
|
||||
@see PropertyComponent
|
||||
|
||||
@tags{GUI}
|
||||
*/
|
||||
class JUCE_API TextPropertyComponent : public PropertyComponent
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates a text property component.
|
||||
|
||||
@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 String& propertyName,
|
||||
int maxNumChars,
|
||||
bool isMultiLine,
|
||||
bool isEditable = true);
|
||||
|
||||
public:
|
||||
/** Creates a text property component.
|
||||
|
||||
@param valueToControl The Value 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 Value& valueToControl,
|
||||
const String& propertyName,
|
||||
int maxNumChars,
|
||||
bool isMultiLine,
|
||||
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 (ValueWithDefault& valueToControl,
|
||||
const String& propertyName,
|
||||
int maxNumChars,
|
||||
bool isMultiLine,
|
||||
bool isEditable = true);
|
||||
|
||||
/** Destructor. */
|
||||
~TextPropertyComponent() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Called when the user edits the text.
|
||||
|
||||
Your subclass must use this callback to change the value of whatever item
|
||||
this property component represents.
|
||||
*/
|
||||
virtual void setText (const String& newText);
|
||||
|
||||
/** Returns the text that should be shown in the text editor. */
|
||||
virtual String getText() const;
|
||||
|
||||
/** Returns the text that should be shown in the text editor as a Value object. */
|
||||
Value& getValue() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if the text editor allows carriage returns. */
|
||||
bool isTextEditorMultiLine() const noexcept { return isMultiLine; }
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the component.
|
||||
|
||||
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
|
||||
methods.
|
||||
|
||||
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
|
||||
*/
|
||||
enum ColourIds
|
||||
{
|
||||
backgroundColourId = 0x100e401, /**< The colour to fill the background of the text area. */
|
||||
textColourId = 0x100e402, /**< The colour to use for the editable text. */
|
||||
outlineColourId = 0x100e403, /**< The colour to use to draw an outline around the text area. */
|
||||
};
|
||||
|
||||
void colourChanged() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Used to receive callbacks for text changes */
|
||||
class JUCE_API Listener
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~Listener() = default;
|
||||
|
||||
/** Called when text has finished being entered (i.e. not per keypress) has changed. */
|
||||
virtual void textPropertyComponentChanged (TextPropertyComponent*) = 0;
|
||||
};
|
||||
|
||||
/** Registers a listener to receive events when this button's state changes.
|
||||
If the listener is already registered, this will not register it again.
|
||||
@see removeListener
|
||||
*/
|
||||
void addListener (Listener* newListener);
|
||||
|
||||
/** Removes a previously-registered button listener
|
||||
@see addListener
|
||||
*/
|
||||
void removeListener (Listener* listener);
|
||||
|
||||
//==============================================================================
|
||||
/** Sets whether the text property component can have files dropped onto it by an external application.
|
||||
|
||||
The default setting for this is true but you may want to disable this behaviour if you derive
|
||||
from this class and want your subclass to respond to the file drag.
|
||||
*/
|
||||
void setInterestedInFileDrag (bool isInterested);
|
||||
|
||||
/** Sets whether the text editor is editable. The default setting for this is true. */
|
||||
void setEditable (bool isEditable);
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
void refresh() override;
|
||||
/** @internal */
|
||||
virtual void textWasEdited();
|
||||
|
||||
private:
|
||||
class RemapperValueSourceWithDefault;
|
||||
class LabelComp;
|
||||
friend class LabelComp;
|
||||
|
||||
//==============================================================================
|
||||
void callListeners();
|
||||
void createEditor (int maxNumChars, bool isEditable);
|
||||
|
||||
//==============================================================================
|
||||
bool isMultiLine;
|
||||
|
||||
std::unique_ptr<LabelComp> textEditor;
|
||||
ListenerList<Listener> listenerList;
|
||||
|
||||
WeakReference<ValueWithDefault> valueWithDefault;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextPropertyComponent)
|
||||
};
|
||||
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user