335 lines
11 KiB
C++
335 lines
11 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library.
|
|
Copyright (c) 2022 - 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 7 End-User License
|
|
Agreement and JUCE Privacy Policy.
|
|
|
|
End User License Agreement: www.juce.com/juce-7-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
|
|
{
|
|
|
|
//==============================================================================
|
|
/**
|
|
This class acts as a wrapper around a property inside a ValueTree.
|
|
|
|
If the property inside the ValueTree is missing it will return a default value,
|
|
which can be specified in the constructor or by calling setDefault().
|
|
|
|
@tags{DataStructures}
|
|
*/
|
|
class JUCE_API ValueTreePropertyWithDefault : private Value::Listener
|
|
{
|
|
public:
|
|
//==============================================================================
|
|
/** Creates an uninitialised ValueTreePropertyWithDefault object.
|
|
|
|
Initialise it using one of the referTo() methods.
|
|
*/
|
|
ValueTreePropertyWithDefault() = default;
|
|
|
|
/** Creates a ValueTreePropertyWithDefault object for the specified property.
|
|
|
|
The default value will be an empty var.
|
|
*/
|
|
ValueTreePropertyWithDefault (ValueTree& tree,
|
|
const Identifier& propertyID,
|
|
UndoManager* um)
|
|
{
|
|
referTo (tree, propertyID, um);
|
|
}
|
|
|
|
/** Creates an ValueTreePropertyWithDefault object for the specified property.
|
|
|
|
The default value will be defaultToUse.
|
|
*/
|
|
ValueTreePropertyWithDefault (ValueTree& tree,
|
|
const Identifier& propertyID,
|
|
UndoManager* um,
|
|
var defaultToUse)
|
|
{
|
|
referTo (tree, propertyID, um, defaultToUse);
|
|
}
|
|
|
|
/** Creates a ValueTreePropertyWithDefault object for the specified property.
|
|
|
|
The default value will be defaultToUse.
|
|
|
|
Use this constructor if the underlying var object being controlled is an array and
|
|
it will handle the conversion to/from a delimited String that can be written to
|
|
XML format.
|
|
*/
|
|
ValueTreePropertyWithDefault (ValueTree& tree,
|
|
const Identifier& propertyID,
|
|
UndoManager* um,
|
|
var defaultToUse,
|
|
StringRef arrayDelimiter)
|
|
{
|
|
referTo (tree, propertyID, um, defaultToUse, arrayDelimiter);
|
|
}
|
|
|
|
/** Creates a ValueTreePropertyWithDefault object from another ValueTreePropertyWithDefault object. */
|
|
ValueTreePropertyWithDefault (const ValueTreePropertyWithDefault& other)
|
|
{
|
|
referToWithDefault (other.targetTree,
|
|
other.targetProperty,
|
|
other.undoManager,
|
|
other.defaultValue,
|
|
other.delimiter);
|
|
}
|
|
|
|
/** Destructor. */
|
|
~ValueTreePropertyWithDefault() override
|
|
{
|
|
defaultValue.removeListener (this);
|
|
}
|
|
|
|
//==============================================================================
|
|
/** Returns the current value of the property.
|
|
|
|
If the property does not exist this returns the default value.
|
|
*/
|
|
var get() const noexcept
|
|
{
|
|
if (isUsingDefault())
|
|
return defaultValue;
|
|
|
|
if (delimiter.isNotEmpty())
|
|
return delimitedStringToVarArray (targetTree[targetProperty].toString(), delimiter);
|
|
|
|
return targetTree[targetProperty];
|
|
}
|
|
|
|
/** Returns the current property as a Value object. */
|
|
Value getPropertyAsValue() { return targetTree.getPropertyAsValue (targetProperty, undoManager); }
|
|
|
|
/** Returns the current default value. */
|
|
var getDefault() const { return defaultValue; }
|
|
|
|
/** Sets the default value to a new var. */
|
|
void setDefault (const var& newDefault) { defaultValue = newDefault; }
|
|
|
|
/** Returns true if the property does not exist in the referenced ValueTree. */
|
|
bool isUsingDefault() const { return ! targetTree.hasProperty (targetProperty); }
|
|
|
|
/** Removes the property from the referenced ValueTree. */
|
|
void resetToDefault() noexcept { targetTree.removeProperty (targetProperty, nullptr); }
|
|
|
|
/** You can assign a lambda to this callback and it will called when the default
|
|
value is changed.
|
|
|
|
@see setDefault
|
|
*/
|
|
std::function<void()> onDefaultChange;
|
|
|
|
//==============================================================================
|
|
/** Sets the property and returns the new ValueTreePropertyWithDefault.
|
|
|
|
This will modify the property in the referenced ValueTree.
|
|
*/
|
|
ValueTreePropertyWithDefault& operator= (const var& newValue)
|
|
{
|
|
setValue (newValue, undoManager);
|
|
return *this;
|
|
}
|
|
|
|
/** Sets the property.
|
|
|
|
This will modify the property in the referenced ValueTree.
|
|
*/
|
|
void setValue (const var& newValue, UndoManager* undoManagerToUse)
|
|
{
|
|
if (auto* array = newValue.getArray())
|
|
targetTree.setProperty (targetProperty, varArrayToDelimitedString (*array, delimiter), undoManagerToUse);
|
|
else
|
|
targetTree.setProperty (targetProperty, newValue, undoManagerToUse);
|
|
}
|
|
|
|
//==============================================================================
|
|
/** Makes the ValueTreePropertyWithDefault refer to the specified property inside
|
|
the given ValueTree.
|
|
|
|
The default value will be an empty var.
|
|
*/
|
|
void referTo (ValueTree tree,
|
|
const Identifier& property,
|
|
UndoManager* um)
|
|
{
|
|
referToWithDefault (tree,
|
|
property,
|
|
um,
|
|
Value (new SynchronousValueSource (var())),
|
|
{});
|
|
}
|
|
|
|
/** Makes the ValueTreePropertyWithDefault refer to the specified property inside
|
|
the given ValueTree.
|
|
|
|
The default value will be defaultVal.
|
|
*/
|
|
void referTo (ValueTree tree,
|
|
const Identifier& property,
|
|
UndoManager* um,
|
|
var defaultVal)
|
|
{
|
|
referToWithDefault (tree,
|
|
property,
|
|
um,
|
|
Value (new SynchronousValueSource (defaultVal)),
|
|
{});
|
|
}
|
|
|
|
/** Makes the ValueTreePropertyWithDefault refer to the specified property inside
|
|
the given ValueTree.
|
|
|
|
The default value will be defaultVal.
|
|
*/
|
|
void referTo (ValueTree tree,
|
|
const Identifier& property,
|
|
UndoManager* um,
|
|
var defaultVal,
|
|
StringRef arrayDelimiter)
|
|
{
|
|
referToWithDefault (tree,
|
|
property,
|
|
um,
|
|
Value (new SynchronousValueSource (defaultVal)),
|
|
arrayDelimiter);
|
|
}
|
|
|
|
//==============================================================================
|
|
/** Returns a reference to the ValueTree containing the referenced property. */
|
|
ValueTree& getValueTree() noexcept { return targetTree; }
|
|
|
|
/** Returns the property ID of the referenced property. */
|
|
Identifier& getPropertyID() noexcept { return targetProperty; }
|
|
|
|
/** Returns the UndoManager that is being used. */
|
|
UndoManager* getUndoManager() noexcept { return undoManager; }
|
|
|
|
//==============================================================================
|
|
ValueTreePropertyWithDefault& operator= (const ValueTreePropertyWithDefault& other)
|
|
{
|
|
referToWithDefault (other.targetTree,
|
|
other.targetProperty,
|
|
other.undoManager,
|
|
other.defaultValue,
|
|
other.delimiter);
|
|
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
//==============================================================================
|
|
class SynchronousValueSource : public Value::ValueSource
|
|
{
|
|
public:
|
|
explicit SynchronousValueSource (const var& initialValue)
|
|
: value (initialValue)
|
|
{
|
|
}
|
|
|
|
var getValue() const override
|
|
{
|
|
return value;
|
|
}
|
|
|
|
void setValue (const var& newValue) override
|
|
{
|
|
if (! newValue.equalsWithSameType (value))
|
|
{
|
|
value = newValue;
|
|
sendChangeMessage (true);
|
|
}
|
|
}
|
|
|
|
private:
|
|
var value;
|
|
|
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SynchronousValueSource)
|
|
};
|
|
|
|
//==============================================================================
|
|
static String varArrayToDelimitedString (const Array<var>& input, StringRef delim)
|
|
{
|
|
// if you are trying to control a var that is an array then you need to
|
|
// set a delimiter string that will be used when writing to XML!
|
|
jassert (delim.isNotEmpty());
|
|
|
|
StringArray elements;
|
|
|
|
for (auto& v : input)
|
|
elements.add (v.toString());
|
|
|
|
return elements.joinIntoString (delim);
|
|
}
|
|
|
|
static Array<var> delimitedStringToVarArray (StringRef input, StringRef delim)
|
|
{
|
|
Array<var> arr;
|
|
|
|
for (auto t : StringArray::fromTokens (input, delim, {}))
|
|
arr.add (t);
|
|
|
|
return arr;
|
|
}
|
|
|
|
void valueChanged (Value&) override
|
|
{
|
|
if (onDefaultChange != nullptr)
|
|
onDefaultChange();
|
|
}
|
|
|
|
void referToWithDefault (ValueTree v,
|
|
const Identifier& i,
|
|
UndoManager* um,
|
|
const Value& defaultVal,
|
|
StringRef del)
|
|
{
|
|
targetTree = v;
|
|
targetProperty = i;
|
|
undoManager = um;
|
|
defaultValue.referTo (defaultVal);
|
|
delimiter = del;
|
|
|
|
defaultValue.addListener (this);
|
|
}
|
|
|
|
//==============================================================================
|
|
ValueTree targetTree;
|
|
Identifier targetProperty;
|
|
UndoManager* undoManager = nullptr;
|
|
Value defaultValue;
|
|
String delimiter;
|
|
|
|
//==============================================================================
|
|
JUCE_LEAK_DETECTOR (ValueTreePropertyWithDefault)
|
|
};
|
|
|
|
//==============================================================================
|
|
#ifndef DOXYGEN
|
|
using ValueWithDefault [[deprecated ("This class has been renamed to better describe what is does. "
|
|
"This declaration is here for backwards compatibility and new "
|
|
"code should use the new class name.")]]
|
|
= ValueTreePropertyWithDefault;
|
|
#endif
|
|
|
|
} // namespace juce
|