2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
23 ==============================================================================
29 //==============================================================================
31 This class acts as a typed wrapper around a property inside a ValueTree.
33 A CachedValue provides an easy way to read and write a ValueTree property with
34 a chosen type. So for example a CachedValue<int> allows you to read or write the
35 property as an int, and a CachedValue<String> lets you work with it as a String.
37 It also allows efficient access to the value, by caching a copy of it in the
38 type that is being used.
40 You can give the CachedValue an optional UndoManager which it will use when writing
41 to the underlying ValueTree.
43 If the property inside the ValueTree is missing, the CachedValue will automatically
44 return an optional default value, which can be specified when initialising the CachedValue.
46 To create one, you can either use the constructor to attach the CachedValue to a
47 ValueTree, or can create an uninitialised CachedValue with its default constructor and
48 then attach it later with the referTo() methods.
50 Common types like String, int, double which can be easily converted to a var should work
51 out-of-the-box, but if you want to use more complex custom types, you may need to implement
52 some template specialisations of VariantConverter which this class uses to convert between
53 the type and the ValueTree's internal var.
57 template <typename Type
>
58 class CachedValue
: private ValueTree::Listener
61 //==============================================================================
62 /** Default constructor.
63 Creates a default CachedValue not referring to any property. To initialise the
64 object, call one of the referTo() methods.
70 Creates a CachedValue referring to a Value property inside a ValueTree.
71 If you use this constructor, the fallback value will be a default-constructed
74 @param tree The ValueTree containing the property
75 @param propertyID The identifier of the property
76 @param undoManager The UndoManager to use when writing to the property
78 CachedValue (ValueTree
& tree
, const Identifier
& propertyID
,
79 UndoManager
* undoManager
);
83 Creates a default Cached Value referring to a Value property inside a ValueTree,
84 and specifies a fallback value to use if the property does not exist.
86 @param tree The ValueTree containing the property
87 @param propertyID The identifier of the property
88 @param undoManager The UndoManager to use when writing to the property
89 @param defaultToUse The fallback default value to use.
91 CachedValue (ValueTree
& tree
, const Identifier
& propertyID
,
92 UndoManager
* undoManager
, const Type
& defaultToUse
);
94 //==============================================================================
95 /** Returns the current value of the property. If the property does not exist,
96 returns the fallback default value.
98 This is the same as calling get().
100 operator Type() const noexcept
{ return cachedValue
; }
102 /** Returns the current value of the property. If the property does not exist,
103 returns the fallback default value.
105 Type
get() const noexcept
{ return cachedValue
; }
107 /** Dereference operator. Provides direct access to the property. */
108 Type
& operator*() noexcept
{ return cachedValue
; }
110 /** Dereference operator. Provides direct access to members of the property
111 if it is of object type.
113 Type
* operator->() noexcept
{ return &cachedValue
; }
115 /** Returns true if the current value of the property (or the fallback value)
118 template <typename OtherType
>
119 bool operator== (const OtherType
& other
) const { return cachedValue
== other
; }
121 /** Returns true if the current value of the property (or the fallback value)
122 is not equal to other.
124 template <typename OtherType
>
125 bool operator!= (const OtherType
& other
) const { return cachedValue
!= other
; }
127 //==============================================================================
128 /** Returns the current property as a Value object. */
129 Value
getPropertyAsValue();
131 /** Returns true if the current property does not exist and the CachedValue is using
132 the fallback default value instead.
134 bool isUsingDefault() const;
136 /** Returns the current fallback default value. */
137 Type
getDefault() const { return defaultValue
; }
139 //==============================================================================
140 /** Sets the property. This will actually modify the property in the referenced ValueTree. */
141 CachedValue
& operator= (const Type
& newValue
);
143 /** Sets the property. This will actually modify the property in the referenced ValueTree. */
144 void setValue (const Type
& newValue
, UndoManager
* undoManagerToUse
);
146 /** Removes the property from the referenced ValueTree and makes the CachedValue
147 return the fallback default value instead.
149 void resetToDefault();
151 /** Removes the property from the referenced ValueTree and makes the CachedValue
152 return the fallback default value instead.
154 void resetToDefault (UndoManager
* undoManagerToUse
);
156 /** Resets the fallback default value. */
157 void setDefault (const Type
& value
) { defaultValue
= value
; }
159 //==============================================================================
160 /** Makes the CachedValue refer to the specified property inside the given ValueTree. */
161 void referTo (ValueTree
& tree
, const Identifier
& property
, UndoManager
* um
);
163 /** Makes the CachedValue refer to the specified property inside the given ValueTree,
164 and specifies a fallback value to use if the property does not exist.
166 void referTo (ValueTree
& tree
, const Identifier
& property
, UndoManager
* um
, const Type
& defaultVal
);
168 /** Force an update in case the referenced property has been changed from elsewhere.
170 Note: The CachedValue is a ValueTree::Listener and therefore will be informed of
171 changes of the referenced property anyway (and update itself). But this may happen
172 asynchronously. forceUpdateOfCachedValue() forces an update immediately.
174 void forceUpdateOfCachedValue();
176 //==============================================================================
177 /** Returns a reference to the ValueTree containing the referenced property. */
178 ValueTree
& getValueTree() noexcept
{ return targetTree
; }
180 /** Returns the property ID of the referenced property. */
181 const Identifier
& getPropertyID() const noexcept
{ return targetProperty
; }
183 /** Returns the UndoManager that is being used. */
184 UndoManager
* getUndoManager() noexcept
{ return undoManager
; }
187 //==============================================================================
188 ValueTree targetTree
;
189 Identifier targetProperty
;
190 UndoManager
* undoManager
= nullptr;
194 //==============================================================================
195 void referToWithDefault (ValueTree
&, const Identifier
&, UndoManager
*, const Type
&);
196 Type
getTypedValue() const;
198 void valueTreePropertyChanged (ValueTree
& changedTree
, const Identifier
& changedProperty
) override
;
200 //==============================================================================
201 JUCE_DECLARE_WEAK_REFERENCEABLE (CachedValue
)
202 JUCE_DECLARE_NON_COPYABLE (CachedValue
)
206 //==============================================================================
207 template <typename Type
>
208 inline CachedValue
<Type
>::CachedValue() = default;
210 template <typename Type
>
211 inline CachedValue
<Type
>::CachedValue (ValueTree
& v
, const Identifier
& i
, UndoManager
* um
)
212 : targetTree (v
), targetProperty (i
), undoManager (um
),
213 defaultValue(), cachedValue (getTypedValue())
215 targetTree
.addListener (this);
218 template <typename Type
>
219 inline CachedValue
<Type
>::CachedValue (ValueTree
& v
, const Identifier
& i
, UndoManager
* um
, const Type
& defaultToUse
)
220 : targetTree (v
), targetProperty (i
), undoManager (um
),
221 defaultValue (defaultToUse
), cachedValue (getTypedValue())
223 targetTree
.addListener (this);
226 template <typename Type
>
227 inline Value CachedValue
<Type
>::getPropertyAsValue()
229 return targetTree
.getPropertyAsValue (targetProperty
, undoManager
);
232 template <typename Type
>
233 inline bool CachedValue
<Type
>::isUsingDefault() const
235 return ! targetTree
.hasProperty (targetProperty
);
238 template <typename Type
>
239 inline CachedValue
<Type
>& CachedValue
<Type
>::operator= (const Type
& newValue
)
241 setValue (newValue
, undoManager
);
245 template <typename Type
>
246 inline void CachedValue
<Type
>::setValue (const Type
& newValue
, UndoManager
* undoManagerToUse
)
248 if (cachedValue
!= newValue
|| isUsingDefault())
250 cachedValue
= newValue
;
251 targetTree
.setProperty (targetProperty
, VariantConverter
<Type
>::toVar (newValue
), undoManagerToUse
);
255 template <typename Type
>
256 inline void CachedValue
<Type
>::resetToDefault()
258 resetToDefault (undoManager
);
261 template <typename Type
>
262 inline void CachedValue
<Type
>::resetToDefault (UndoManager
* undoManagerToUse
)
264 targetTree
.removeProperty (targetProperty
, undoManagerToUse
);
265 forceUpdateOfCachedValue();
268 template <typename Type
>
269 inline void CachedValue
<Type
>::referTo (ValueTree
& v
, const Identifier
& i
, UndoManager
* um
)
271 referToWithDefault (v
, i
, um
, Type());
274 template <typename Type
>
275 inline void CachedValue
<Type
>::referTo (ValueTree
& v
, const Identifier
& i
, UndoManager
* um
, const Type
& defaultVal
)
277 referToWithDefault (v
, i
, um
, defaultVal
);
280 template <typename Type
>
281 inline void CachedValue
<Type
>::forceUpdateOfCachedValue()
283 cachedValue
= getTypedValue();
286 template <typename Type
>
287 inline void CachedValue
<Type
>::referToWithDefault (ValueTree
& v
, const Identifier
& i
, UndoManager
* um
, const Type
& defaultVal
)
289 targetTree
.removeListener (this);
293 defaultValue
= defaultVal
;
294 cachedValue
= getTypedValue();
295 targetTree
.addListener (this);
298 template <typename Type
>
299 inline Type CachedValue
<Type
>::getTypedValue() const
301 if (const var
* property
= targetTree
.getPropertyPointer (targetProperty
))
302 return VariantConverter
<Type
>::fromVar (*property
);
307 template <typename Type
>
308 inline void CachedValue
<Type
>::valueTreePropertyChanged (ValueTree
& changedTree
, const Identifier
& changedProperty
)
310 if (changedProperty
== targetProperty
&& targetTree
== changedTree
)
311 forceUpdateOfCachedValue();