Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

312 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2016 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #ifndef JUCE_CACHEDVALUE_H_INCLUDED
  18. #define JUCE_CACHEDVALUE_H_INCLUDED
  19. //==============================================================================
  20. /**
  21. This class acts as a typed wrapper around a property inside a ValueTree.
  22. A CachedValue provides an easy way to read and write a ValueTree property with
  23. a chosen type. So for example a CachedValue<int> allows you to read or write the
  24. property as an int, and a CachedValue<String> lets you work with it as a String.
  25. It also allows efficient access to the value, by caching a copy of it in the
  26. type that is being used.
  27. You can give the CachedValue an optional UndoManager which it will use when writing
  28. to the underlying ValueTree.
  29. If the property inside the ValueTree is missing, the CachedValue will automatically
  30. return an optional default value, which can be specified when initialising the CachedValue.
  31. To create one, you can either use the constructor to attach the CachedValue to a
  32. ValueTree, or can create an uninitialised CachedValue with its default constructor and
  33. then attach it later with the referTo() methods.
  34. Common types like String, int, double which can be easily converted to a var should work
  35. out-of-the-box, but if you want to use more complex custom types, you may need to implement
  36. some template specialisations of VariantConverter which this class uses to convert between
  37. the type and the ValueTree's internal var.
  38. */
  39. template <typename Type>
  40. class CachedValue : private ValueTree::Listener
  41. {
  42. public:
  43. //==============================================================================
  44. /** Default constructor.
  45. Creates a default CachedValue not referring to any property. To initialise the
  46. object, call one of the referTo() methods.
  47. */
  48. CachedValue();
  49. /** Constructor.
  50. Creates a CachedValue referring to a Value property inside a ValueTree.
  51. If you use this constructor, the fallback value will be a default-constructed
  52. instance of Type.
  53. @param tree The ValueTree containing the property
  54. @param propertyID The identifier of the property
  55. @param undoManager The UndoManager to use when writing to the property
  56. */
  57. CachedValue (ValueTree& tree, const Identifier& propertyID,
  58. UndoManager* undoManager);
  59. /** Constructor.
  60. Creates a default Cached Value referring to a Value property inside a ValueTree,
  61. and specifies a fallback value to use if the property does not exist.
  62. @param tree The ValueTree containing the property
  63. @param propertyID The identifier of the property
  64. @param undoManager The UndoManager to use when writing to the property
  65. @param defaultToUse The fallback default value to use.
  66. */
  67. CachedValue (ValueTree& tree, const Identifier& propertyID,
  68. UndoManager* undoManager, const Type& defaultToUse);
  69. //==============================================================================
  70. /** Returns the current value of the property. If the property does not exist,
  71. returns the fallback default value.
  72. This is the same as calling get().
  73. */
  74. operator Type() const noexcept { return cachedValue; }
  75. /** Returns the current value of the property. If the property does not exist,
  76. returns the fallback default value.
  77. */
  78. Type get() const noexcept { return cachedValue; }
  79. /** Dereference operator. Provides direct access to the property. */
  80. Type& operator*() noexcept { return cachedValue; }
  81. /** Dereference operator. Provides direct access to members of the property
  82. if it is of object type.
  83. */
  84. Type* operator->() noexcept { return &cachedValue; }
  85. /** Returns true if the current value of the property (or the fallback value)
  86. is equal to other.
  87. */
  88. template <typename OtherType>
  89. bool operator== (const OtherType& other) const { return cachedValue == other; }
  90. /** Returns true if the current value of the property (or the fallback value)
  91. is not equal to other.
  92. */
  93. template <typename OtherType>
  94. bool operator!= (const OtherType& other) const { return cachedValue != other; }
  95. //==============================================================================
  96. /** Returns the current property as a Value object. */
  97. Value getPropertyAsValue();
  98. /** Returns true if the current property does not exist and the CachedValue is using
  99. the fallback default value instead.
  100. */
  101. bool isUsingDefault() const;
  102. /** Returns the current fallback default value. */
  103. Type getDefault() const { return defaultValue; }
  104. //==============================================================================
  105. /** Sets the property. This will actually modify the property in the referenced ValueTree. */
  106. CachedValue& operator= (const Type& newValue);
  107. /** Sets the property. This will actually modify the property in the referenced ValueTree. */
  108. void setValue (const Type& newValue, UndoManager* undoManagerToUse);
  109. /** Removes the property from the referenced ValueTree and makes the CachedValue
  110. return the fallback default value instead.
  111. */
  112. void resetToDefault();
  113. /** Removes the property from the referenced ValueTree and makes the CachedValue
  114. return the fallback default value instead.
  115. */
  116. void resetToDefault (UndoManager* undoManagerToUse);
  117. /** Resets the fallback default value. */
  118. void setDefault (const Type& value) { defaultValue = value; }
  119. //==============================================================================
  120. /** Makes the CachedValue refer to the specified property inside the given ValueTree. */
  121. void referTo (ValueTree& tree, const Identifier& property, UndoManager* um);
  122. /** Makes the CachedValue refer to the specified property inside the given ValueTree,
  123. and specifies a fallback value to use if the property does not exist.
  124. */
  125. void referTo (ValueTree& tree, const Identifier& property, UndoManager* um, const Type& defaultVal);
  126. /** Force an update in case the referenced property has been changed from elsewhere.
  127. Note: The CachedValue is a ValueTree::Listener and therefore will be informed of
  128. changes of the referenced property anyway (and update itself). But this may happen
  129. asynchronously. forceUpdateOfCachedValue() forces an update immediately.
  130. */
  131. void forceUpdateOfCachedValue();
  132. //==============================================================================
  133. /** Returns a reference to the ValueTree containing the referenced property. */
  134. ValueTree& getValueTree() noexcept { return targetTree; }
  135. /** Returns the property ID of the referenced property. */
  136. const Identifier& getPropertyID() const noexcept { return targetProperty; }
  137. private:
  138. //==============================================================================
  139. ValueTree targetTree;
  140. Identifier targetProperty;
  141. UndoManager* undoManager;
  142. Type defaultValue;
  143. Type cachedValue;
  144. //==============================================================================
  145. void referToWithDefault (ValueTree&, const Identifier&, UndoManager*, const Type&);
  146. Type getTypedValue() const;
  147. void valueTreePropertyChanged (ValueTree& changedTree, const Identifier& changedProperty) override;
  148. void valueTreeChildAdded (ValueTree&, ValueTree&) override {}
  149. void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override {}
  150. void valueTreeChildOrderChanged (ValueTree&, int, int) override {}
  151. void valueTreeParentChanged (ValueTree&) override {}
  152. JUCE_DECLARE_NON_COPYABLE (CachedValue)
  153. };
  154. //==============================================================================
  155. template <typename Type>
  156. inline CachedValue<Type>::CachedValue() : undoManager (nullptr) {}
  157. template <typename Type>
  158. inline CachedValue<Type>::CachedValue (ValueTree& v, const Identifier& i, UndoManager* um)
  159. : targetTree (v), targetProperty (i), undoManager (um),
  160. defaultValue(), cachedValue (getTypedValue())
  161. {
  162. targetTree.addListener (this);
  163. }
  164. template <typename Type>
  165. inline CachedValue<Type>::CachedValue (ValueTree& v, const Identifier& i, UndoManager* um, const Type& defaultToUse)
  166. : targetTree (v), targetProperty (i), undoManager (um),
  167. defaultValue (defaultToUse), cachedValue (getTypedValue())
  168. {
  169. targetTree.addListener (this);
  170. }
  171. template <typename Type>
  172. inline Value CachedValue<Type>::getPropertyAsValue()
  173. {
  174. return targetTree.getPropertyAsValue (targetProperty, undoManager);
  175. }
  176. template <typename Type>
  177. inline bool CachedValue<Type>::isUsingDefault() const
  178. {
  179. return ! targetTree.hasProperty (targetProperty);
  180. }
  181. template <typename Type>
  182. inline CachedValue<Type>& CachedValue<Type>::operator= (const Type& newValue)
  183. {
  184. setValue (newValue, undoManager);
  185. return *this;
  186. }
  187. template <typename Type>
  188. inline void CachedValue<Type>::setValue (const Type& newValue, UndoManager* undoManagerToUse)
  189. {
  190. if (cachedValue != newValue || isUsingDefault())
  191. {
  192. cachedValue = newValue;
  193. targetTree.setProperty (targetProperty, VariantConverter<Type>::toVar (newValue), undoManagerToUse);
  194. }
  195. }
  196. template <typename Type>
  197. inline void CachedValue<Type>::resetToDefault()
  198. {
  199. resetToDefault (undoManager);
  200. }
  201. template <typename Type>
  202. inline void CachedValue<Type>::resetToDefault (UndoManager* undoManagerToUse)
  203. {
  204. targetTree.removeProperty (targetProperty, undoManagerToUse);
  205. forceUpdateOfCachedValue();
  206. }
  207. template <typename Type>
  208. inline void CachedValue<Type>::referTo (ValueTree& v, const Identifier& i, UndoManager* um)
  209. {
  210. referToWithDefault (v, i, um, Type());
  211. }
  212. template <typename Type>
  213. inline void CachedValue<Type>::referTo (ValueTree& v, const Identifier& i, UndoManager* um, const Type& defaultVal)
  214. {
  215. referToWithDefault (v, i, um, defaultVal);
  216. }
  217. template <typename Type>
  218. inline void CachedValue<Type>::forceUpdateOfCachedValue()
  219. {
  220. cachedValue = getTypedValue();
  221. }
  222. template <typename Type>
  223. inline void CachedValue<Type>::referToWithDefault (ValueTree& v, const Identifier& i, UndoManager* um, const Type& defaultVal)
  224. {
  225. targetTree.removeListener (this);
  226. targetTree = v;
  227. targetProperty = i;
  228. undoManager = um;
  229. defaultValue = defaultVal;
  230. cachedValue = getTypedValue();
  231. targetTree.addListener (this);
  232. }
  233. template <typename Type>
  234. inline Type CachedValue<Type>::getTypedValue() const
  235. {
  236. if (const var* property = targetTree.getPropertyPointer (targetProperty))
  237. return VariantConverter<Type>::fromVar (*property);
  238. return defaultValue;
  239. }
  240. template <typename Type>
  241. inline void CachedValue<Type>::valueTreePropertyChanged (ValueTree& changedTree, const Identifier& changedProperty)
  242. {
  243. if (changedProperty == targetProperty && targetTree == changedTree)
  244. forceUpdateOfCachedValue();
  245. }
  246. #endif // JUCE_CACHEDVALUE_H_INCLUDED