VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_data_structures / values / juce_ValueTree.h
blobd262e09c4805d053f45003f2af06ea94e7aa756d
1 /*
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
8 licensing.
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
21 DISCLAIMED.
23 ==============================================================================
26 namespace juce
29 //==============================================================================
30 /**
31 A powerful tree structure that can be used to hold free-form data, and which can
32 handle its own undo and redo behaviour.
34 A ValueTree contains a list of named properties as var objects, and also holds
35 any number of sub-trees.
37 Create ValueTree objects on the stack, and don't be afraid to copy them around, as
38 they're simply a lightweight reference to a shared data container. Creating a copy
39 of another ValueTree simply creates a new reference to the same underlying object - to
40 make a separate, deep copy of a tree you should explicitly call createCopy().
42 Each ValueTree has a type name, in much the same way as an XmlElement has a tag name,
43 and much of the structure of a ValueTree is similar to an XmlElement tree.
44 You can convert a ValueTree to and from an XmlElement, and as long as the XML doesn't
45 contain text elements, the conversion works well and makes a good serialisation
46 format. They can also be serialised to a binary format, which is very fast and compact.
48 All the methods that change data take an optional UndoManager, which will be used
49 to track any changes to the object. For this to work, you have to be careful to
50 consistently always use the same UndoManager for all operations to any sub-tree inside
51 the tree.
53 A ValueTree can only be a child of one parent at a time, so if you're moving one from
54 one tree to another, be careful to always remove it first, before adding it. This
55 could also mess up your undo/redo chain, so be wary! In a debug build you should hit
56 assertions if you try to do anything dangerous, but there are still plenty of ways it
57 could go wrong.
59 Note that although the children in a tree have a fixed order, the properties are not
60 guaranteed to be stored in any particular order, so don't expect that a property's index
61 will correspond to the order in which the property was added, or that it will remain
62 constant when other properties are added or removed.
64 Listeners can be added to a ValueTree to be told when properties change and when
65 sub-trees are added or removed.
67 @see var, XmlElement
69 @tags{DataStructures}
71 class JUCE_API ValueTree final
73 public:
74 //==============================================================================
75 /** Creates an empty, invalid ValueTree.
77 A ValueTree that is created with this constructor can't actually be used for anything,
78 it's just a default 'null' ValueTree that can be returned to indicate some sort of failure.
79 To create a real one, use the constructor that takes a string.
81 ValueTree() noexcept;
83 /** Creates an empty ValueTree with the given type name.
85 Like an XmlElement, each ValueTree has a type, which you can access with
86 getType() and hasType().
88 explicit ValueTree (const Identifier& type);
90 /** Creates a value tree from nested lists of properties and ValueTrees.
92 This code,
94 @code
95 ValueTree groups
96 { "ParameterGroups", {},
98 { "Group", {{ "name", "Tone Controls" }},
100 { "Parameter", {{ "id", "distortion" }, { "value", 0.5 }}},
101 { "Parameter", {{ "id", "reverb" }, { "value", 0.5 }}}
104 { "Group", {{ "name", "Other Controls" }},
106 { "Parameter", {{ "id", "drywet" }, { "value", 0.5 }}},
107 { "Parameter", {{ "id", "gain" }, { "value", 0.5 }}}
112 @endcode
114 produces this tree:
116 @verbatim
117 <ParameterGroups>
118 <Group name="Tone Controls">
119 <Parameter id="distortion" value="0.5"/>
120 <Parameter id="reverb" value="0.5"/>
121 </Group>
122 <Group name="Other Controls">
123 <Parameter id="drywet" value="0.5"/>
124 <Parameter id="gain" value="0.5"/>
125 </Group>
126 </ParameterGroups>
127 @endverbatim
129 ValueTree (const Identifier& type,
130 std::initializer_list<NamedValueSet::NamedValue> properties,
131 std::initializer_list<ValueTree> subTrees = {});
133 /** Creates a reference to another ValueTree. */
134 ValueTree (const ValueTree&) noexcept;
136 /** Move constructor */
137 ValueTree (ValueTree&&) noexcept;
139 /** Changes this object to be a reference to the given tree.
140 Note that calling this just points this at the new object and invokes the
141 Listener::valueTreeRedirected callback, but it's not an undoable operation. If
142 you're trying to replace an entire tree in an undoable way, you probably want
143 to use copyPropertiesAndChildrenFrom() instead.
145 ValueTree& operator= (const ValueTree&);
147 /** Destructor. */
148 ~ValueTree();
150 /** Returns true if both this and the other tree refer to the same underlying structure.
151 Note that this isn't a value comparison - two independently-created trees which
152 contain identical data are NOT considered equal.
154 bool operator== (const ValueTree&) const noexcept;
156 /** Returns true if this and the other tree refer to different underlying structures.
157 Note that this isn't a value comparison - two independently-created trees which
158 contain identical data are not considered equal.
160 bool operator!= (const ValueTree&) const noexcept;
162 /** Performs a deep comparison between the properties and children of two trees.
163 If all the properties and children of the two trees are the same (recursively), this
164 returns true.
165 The normal operator==() only checks whether two trees refer to the same shared data
166 structure, so use this method if you need to do a proper value comparison.
168 bool isEquivalentTo (const ValueTree&) const;
170 //==============================================================================
171 /** Returns true if this tree refers to some valid data.
172 An invalid tree is one that was created with the default constructor.
174 bool isValid() const noexcept { return object != nullptr; }
176 /** Returns a deep copy of this tree and all its sub-trees. */
177 ValueTree createCopy() const;
179 /** Overwrites all the properties in this tree with the properties of the source tree.
180 Any properties that already exist will be updated; and new ones will be added, and
181 any that are not present in the source tree will be removed.
182 @see copyPropertiesAndChildrenFrom
184 void copyPropertiesFrom (const ValueTree& source, UndoManager* undoManager);
186 /** Replaces all children and properties of this object with copies of those from
187 the source object.
188 @see copyPropertiesFrom
190 void copyPropertiesAndChildrenFrom (const ValueTree& source, UndoManager* undoManager);
192 //==============================================================================
193 /** Returns the type of this tree.
194 The type is specified when the ValueTree is created.
195 @see hasType
197 Identifier getType() const noexcept;
199 /** Returns true if the tree has this type.
200 The comparison is case-sensitive.
201 @see getType
203 bool hasType (const Identifier& typeName) const noexcept;
205 //==============================================================================
206 /** Returns the value of a named property.
207 If no such property has been set, this will return a void variant.
208 You can also use operator[] to get a property.
209 @see var, setProperty, getPropertyPointer, hasProperty
211 const var& getProperty (const Identifier& name) const noexcept;
213 /** Returns the value of a named property, or the value of defaultReturnValue
214 if the property doesn't exist.
215 You can also use operator[] and getProperty to get a property.
216 @see var, getProperty, getPropertyPointer, setProperty, hasProperty
218 var getProperty (const Identifier& name, const var& defaultReturnValue) const;
220 /** Returns a pointer to the value of a named property, or nullptr if the property
221 doesn't exist.
222 @see var, getProperty, setProperty, hasProperty
224 const var* getPropertyPointer (const Identifier& name) const noexcept;
226 /** Returns the value of a named property.
227 If no such property has been set, this will return a void variant. This is the same as
228 calling getProperty().
229 @see getProperty
231 const var& operator[] (const Identifier& name) const noexcept;
233 /** Changes a named property of the tree.
234 The name identifier must not be an empty string.
235 If the undoManager parameter is not nullptr, its UndoManager::perform() method will be used,
236 so that this change can be undone. Be very careful not to mix undoable and non-undoable changes!
237 @see var, getProperty, removeProperty
238 @returns a reference to the value tree, so that you can daisy-chain calls to this method.
240 ValueTree& setProperty (const Identifier& name, const var& newValue, UndoManager* undoManager);
242 /** Returns true if the tree contains a named property. */
243 bool hasProperty (const Identifier& name) const noexcept;
245 /** Removes a property from the tree.
246 If the undoManager parameter is not nullptr, its UndoManager::perform() method will be used,
247 so that this change can be undone. Be very careful not to mix undoable and non-undoable changes!
249 void removeProperty (const Identifier& name, UndoManager* undoManager);
251 /** Removes all properties from the tree.
252 If the undoManager parameter is not nullptr, its UndoManager::perform() method will be used,
253 so that this change can be undone. Be very careful not to mix undoable and non-undoable changes!
255 void removeAllProperties (UndoManager* undoManager);
257 /** Returns the total number of properties that the tree contains.
258 @see getProperty.
260 int getNumProperties() const noexcept;
262 /** Returns the identifier of the property with a given index.
263 Note that properties are not guaranteed to be stored in any particular order, so don't
264 expect that the index will correspond to the order in which the property was added, or
265 that it will remain constant when other properties are added or removed.
266 @see getNumProperties
268 Identifier getPropertyName (int index) const noexcept;
270 /** Returns a Value object that can be used to control and respond to one of the tree's properties.
272 The Value object will maintain a reference to this tree, and will use the undo manager when
273 it needs to change the value. Attaching a Value::Listener to the value object will provide
274 callbacks whenever the property changes.
275 If shouldUpdateSynchronously is true the Value::Listener will be updated synchronously.
276 @see ValueSource::sendChangeMessage (bool)
278 Value getPropertyAsValue (const Identifier& name, UndoManager* undoManager,
279 bool shouldUpdateSynchronously = false);
281 //==============================================================================
282 /** Returns the number of child trees inside this one.
283 @see getChild
285 int getNumChildren() const noexcept;
287 /** Returns one of this tree's sub-trees.
288 If the index is out of range, it'll return an invalid tree. (You can use isValid() to
289 check whether a tree is valid)
291 ValueTree getChild (int index) const;
293 /** Returns the first sub-tree with the specified type name.
294 If no such child tree exists, it'll return an invalid tree. (You can use isValid() to
295 check whether a tree is valid)
296 @see getOrCreateChildWithName
298 ValueTree getChildWithName (const Identifier& type) const;
300 /** Returns the first sub-tree with the specified type name, creating and adding
301 a child with this name if there wasn't already one there.
302 The only time this will return an invalid object is when the object that you're calling
303 the method on is itself invalid.
304 @see getChildWithName
306 ValueTree getOrCreateChildWithName (const Identifier& type, UndoManager* undoManager);
308 /** Looks for the first sub-tree that has the specified property value.
309 This will scan the child trees in order, until it finds one that has property that matches
310 the specified value.
311 If no such tree is found, it'll return an invalid object. (You can use isValid() to
312 check whether a tree is valid)
314 ValueTree getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const;
316 /** Adds a child to this tree.
317 Make sure that the child being added has first been removed from any former parent before
318 calling this, or else you'll hit an assertion.
319 If the index is < 0 or greater than the current number of sub-trees, the new one will be
320 added at the end of the list.
321 If the undoManager parameter is not nullptr, its UndoManager::perform() method will be used,
322 so that this change can be undone. Be very careful not to mix undoable and non-undoable changes!
323 @see appendChild, removeChild
325 void addChild (const ValueTree& child, int index, UndoManager* undoManager);
327 /** Appends a new child sub-tree to this tree.
328 This is equivalent to calling addChild() with an index of -1. See addChild() for more details.
329 @see addChild, removeChild
331 void appendChild (const ValueTree& child, UndoManager* undoManager);
333 /** Removes the specified child from this tree's child-list.
334 If the undoManager parameter is not nullptr, its UndoManager::perform() method will be used,
335 so that this change can be undone. Be very careful not to mix undoable and non-undoable changes!
337 void removeChild (const ValueTree& child, UndoManager* undoManager);
339 /** Removes a sub-tree from this tree.
340 If the index is out-of-range, nothing will be changed.
341 If the undoManager parameter is not nullptr, its UndoManager::perform() method will be used,
342 so that this change can be undone. Be very careful not to mix undoable and non-undoable changes!
344 void removeChild (int childIndex, UndoManager* undoManager);
346 /** Removes all child-trees.
347 If the undoManager parameter is not nullptr, its UndoManager::perform() method will be used,
348 so that this change can be undone. Be very careful not to mix undoable and non-undoable changes!
350 void removeAllChildren (UndoManager* undoManager);
352 /** Moves one of the sub-trees to a different index.
353 This will move the child to a specified index, shuffling along any intervening
354 items as required. So for example, if you have a list of { 0, 1, 2, 3, 4, 5 }, then
355 calling move (2, 4) would result in { 0, 1, 3, 4, 2, 5 }.
357 @param currentIndex the index of the item to be moved. If this isn't a
358 valid index, then nothing will be done
359 @param newIndex the index at which you'd like this item to end up. If this
360 is less than zero, the value will be moved to the end
361 of the list
362 @param undoManager the optional UndoManager to use to store this transaction
364 void moveChild (int currentIndex, int newIndex, UndoManager* undoManager);
366 /** Returns true if this tree is a sub-tree (at any depth) of the given parent.
367 This searches recursively, so returns true if it's a sub-tree at any level below the parent.
369 bool isAChildOf (const ValueTree& possibleParent) const noexcept;
371 /** Returns the index of a child item in this parent.
372 If the child isn't found, this returns -1.
374 int indexOf (const ValueTree& child) const noexcept;
376 /** Returns the parent tree that contains this one.
377 If the tree has no parent, this will return an invalid object. (You can use isValid() to
378 check whether a tree is valid)
380 ValueTree getParent() const noexcept;
382 /** Recursively finds the highest-level parent tree that contains this one.
383 If the tree has no parent, this will return itself.
385 ValueTree getRoot() const noexcept;
387 /** Returns one of this tree's siblings in its parent's child list.
388 The delta specifies how far to move through the list, so a value of 1 would return the tree
389 that follows this one, -1 would return the tree before it, 0 will return this one, etc.
390 If the requested position is beyond the start or end of the child list, this will return an
391 invalid object.
393 ValueTree getSibling (int delta) const noexcept;
395 //==============================================================================
396 /** Iterator for a ValueTree.
397 You shouldn't ever need to use this class directly - it's used internally by ValueTree::begin()
398 and ValueTree::end() to allow range-based-for loops on a ValueTree.
400 struct Iterator
402 Iterator (const ValueTree&, bool isEnd);
403 Iterator& operator++();
405 bool operator== (const Iterator&) const;
406 bool operator!= (const Iterator&) const;
407 ValueTree operator*() const;
409 using difference_type = std::ptrdiff_t;
410 using value_type = ValueTree;
411 using reference = ValueTree&;
412 using pointer = ValueTree*;
413 using iterator_category = std::forward_iterator_tag;
415 private:
416 void* internal;
419 /** Returns a start iterator for the children in this tree. */
420 Iterator begin() const noexcept;
422 /** Returns an end iterator for the children in this tree. */
423 Iterator end() const noexcept;
425 //==============================================================================
426 /** Creates an XmlElement that holds a complete image of this tree and all its children.
427 If this tree is invalid, this may return nullptr. Otherwise, the XML that is produced can
428 be used to recreate a similar tree by calling ValueTree::fromXml().
429 @see fromXml, toXmlString
431 std::unique_ptr<XmlElement> createXml() const;
433 /** Tries to recreate a tree from its XML representation.
434 This isn't designed to cope with random XML data - it should only be fed XML that was created
435 by the createXml() method.
437 static ValueTree fromXml (const XmlElement& xml);
439 /** Tries to recreate a tree from its XML representation.
440 This isn't designed to cope with random XML data - it should only be fed XML that was created
441 by the createXml() method.
443 static ValueTree fromXml (const String& xmlText);
445 /** This returns a string containing an XML representation of the tree.
446 This is quite handy for debugging purposes, as it provides a quick way to view a tree.
447 @see createXml()
449 String toXmlString (const XmlElement::TextFormat& format = {}) const;
451 //==============================================================================
452 /** Stores this tree (and all its children) in a binary format.
454 Once written, the data can be read back with readFromStream().
456 It's much faster to load/save your tree in binary form than as XML, but
457 obviously isn't human-readable.
459 void writeToStream (OutputStream& output) const;
461 /** Reloads a tree from a stream that was written with writeToStream(). */
462 static ValueTree readFromStream (InputStream& input);
464 /** Reloads a tree from a data block that was written with writeToStream(). */
465 static ValueTree readFromData (const void* data, size_t numBytes);
467 /** Reloads a tree from a data block that was written with writeToStream() and
468 then zipped using GZIPCompressorOutputStream.
470 static ValueTree readFromGZIPData (const void* data, size_t numBytes);
472 //==============================================================================
473 /** Listener class for events that happen to a ValueTree.
475 To get events from a ValueTree, make your class implement this interface, and use
476 ValueTree::addListener() and ValueTree::removeListener() to register it.
478 class JUCE_API Listener
480 public:
481 /** Destructor. */
482 virtual ~Listener() = default;
484 /** This method is called when a property of this tree (or of one of its sub-trees) is changed.
485 Note that when you register a listener to a tree, it will receive this callback for
486 property changes in that tree, and also for any of its children, (recursively, at any depth).
487 If your tree has sub-trees but you only want to know about changes to the top level tree,
488 simply check the tree parameter in this callback to make sure it's the tree you're interested in.
490 virtual void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged,
491 const Identifier& property);
493 /** This method is called when a child sub-tree is added.
494 Note that when you register a listener to a tree, it will receive this callback for
495 child changes in both that tree and any of its children, (recursively, at any depth).
496 If your tree has sub-trees but you only want to know about changes to the top level tree,
497 just check the parentTree parameter to make sure it's the one that you're interested in.
499 virtual void valueTreeChildAdded (ValueTree& parentTree,
500 ValueTree& childWhichHasBeenAdded);
502 /** This method is called when a child sub-tree is removed.
504 Note that when you register a listener to a tree, it will receive this callback for
505 child changes in both that tree and any of its children, (recursively, at any depth).
506 If your tree has sub-trees but you only want to know about changes to the top level tree,
507 just check the parentTree parameter to make sure it's the one that you're interested in.
509 virtual void valueTreeChildRemoved (ValueTree& parentTree,
510 ValueTree& childWhichHasBeenRemoved,
511 int indexFromWhichChildWasRemoved);
513 /** This method is called when a tree's children have been re-shuffled.
515 Note that when you register a listener to a tree, it will receive this callback for
516 child changes in both that tree and any of its children, (recursively, at any depth).
517 If your tree has sub-trees but you only want to know about changes to the top level tree,
518 just check the parameter to make sure it's the tree that you're interested in.
520 virtual void valueTreeChildOrderChanged (ValueTree& parentTreeWhoseChildrenHaveMoved,
521 int oldIndex, int newIndex);
523 /** This method is called when a tree has been added or removed from a parent.
525 This callback happens when the tree to which the listener was registered is added or
526 removed from a parent. Unlike the other callbacks, it applies only to the tree to which
527 the listener is registered, and not to any of its children.
529 virtual void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged);
531 /** This method is called when a tree is made to point to a different internal shared object.
532 When operator= is used to make a ValueTree refer to a different object, this callback
533 will be made.
535 virtual void valueTreeRedirected (ValueTree& treeWhichHasBeenChanged);
538 /** Adds a listener to receive callbacks when this tree is changed in some way.
540 The listener is added to this specific ValueTree object, and not to the shared
541 object that it refers to. When this object is deleted, all the listeners will
542 be lost, even if other references to the same ValueTree still exist. And if you
543 use the operator= to make this refer to a different ValueTree, any listeners will
544 begin listening to changes to the new tree instead of the old one.
546 When you're adding a listener, make sure that you add it to a ValueTree instance that
547 will last for as long as you need the listener. In general, you'd never want to add a
548 listener to a local stack-based ValueTree, and would usually add one to a member variable.
550 @see removeListener
552 void addListener (Listener* listener);
554 /** Removes a listener that was previously added with addListener(). */
555 void removeListener (Listener* listener);
557 /** Changes a named property of the tree, but will not notify a specified listener of the change.
558 @see setProperty
560 ValueTree& setPropertyExcludingListener (Listener* listenerToExclude,
561 const Identifier& name, const var& newValue,
562 UndoManager* undoManager);
564 /** Causes a property-change callback to be triggered for the specified property,
565 calling any listeners that are registered.
567 void sendPropertyChangeMessage (const Identifier& property);
569 //==============================================================================
570 /** This method uses a comparator object to sort the tree's children into order.
572 The object provided must have a method of the form:
573 @code
574 int compareElements (const ValueTree& first, const ValueTree& second);
575 @endcode
577 ..and this method must return:
578 - a value of < 0 if the first comes before the second
579 - a value of 0 if the two objects are equivalent
580 - a value of > 0 if the second comes before the first
582 To improve performance, the compareElements() method can be declared as static or const.
584 @param comparator the comparator to use for comparing elements.
585 @param undoManager optional UndoManager for storing the changes
586 @param retainOrderOfEquivalentItems if this is true, then items which the comparator says are
587 equivalent will be kept in the order in which they currently appear in the array.
588 This is slower to perform, but may be important in some cases. If it's false, a
589 faster algorithm is used, but equivalent elements may be rearranged.
591 template <typename ElementComparator>
592 void sort (ElementComparator& comparator, UndoManager* undoManager, bool retainOrderOfEquivalentItems)
594 if (object != nullptr)
596 OwnedArray<ValueTree> sortedList;
597 createListOfChildren (sortedList);
598 ComparatorAdapter<ElementComparator> adapter (comparator);
599 sortedList.sort (adapter, retainOrderOfEquivalentItems);
600 reorderChildren (sortedList, undoManager);
604 /** Returns the total number of references to the shared underlying data structure that this
605 ValueTree is using.
607 int getReferenceCount() const noexcept;
609 #if JUCE_ALLOW_STATIC_NULL_VARIABLES && ! defined (DOXYGEN)
610 /* An invalid ValueTree that can be used if you need to return one as an error condition, etc. */
611 [[deprecated ("If you need an empty ValueTree object, just use ValueTree() or {}.")]]
612 static const ValueTree invalid;
613 #endif
615 private:
616 //==============================================================================
617 JUCE_PUBLIC_IN_DLL_BUILD (class SharedObject)
618 friend class SharedObject;
620 ReferenceCountedObjectPtr<SharedObject> object;
621 ListenerList<Listener> listeners;
623 template <typename ElementComparator>
624 struct ComparatorAdapter
626 ComparatorAdapter (ElementComparator& comp) noexcept : comparator (comp) {}
628 int compareElements (const ValueTree* const first, const ValueTree* const second)
630 return comparator.compareElements (*first, *second);
633 private:
634 ElementComparator& comparator;
635 JUCE_DECLARE_NON_COPYABLE (ComparatorAdapter)
638 void createListOfChildren (OwnedArray<ValueTree>&) const;
639 void reorderChildren (const OwnedArray<ValueTree>&, UndoManager*);
641 explicit ValueTree (ReferenceCountedObjectPtr<SharedObject>) noexcept;
642 explicit ValueTree (SharedObject&) noexcept;
645 } // namespace juce