32 using Ptr = ReferenceCountedObjectPtr<SharedObject>;
34 explicit SharedObject (
const Identifier& t) noexcept : type (t) {}
36 SharedObject (
const SharedObject& other)
39 for (
auto* c : other.children)
41 auto* child = new SharedObject (*c);
47 SharedObject& operator= (
const SharedObject&) =
delete;
49 ~SharedObject()
override
51 jassert (parent ==
nullptr);
53 for (
auto i = children.size(); --i >= 0;)
55 const Ptr c (children.getObjectPointerUnchecked (i));
58 c->sendParentChangeMessage();
62 SharedObject& getRoot() noexcept
64 return parent ==
nullptr ? *this : parent->getRoot();
67 template <
typename Function>
68 void callListeners (ValueTree::Listener* listenerToExclude, Function fn)
const
70 auto numListeners = valueTreesWithListeners.size();
72 if (numListeners == 1)
74 valueTreesWithListeners.getUnchecked (0)->listeners.callExcluding (listenerToExclude, fn);
76 else if (numListeners > 0)
78 auto listenersCopy = valueTreesWithListeners;
80 for (
int i = 0; i < numListeners; ++i)
82 auto* v = listenersCopy.getUnchecked (i);
84 if (i == 0 || valueTreesWithListeners.contains (v))
85 v->listeners.callExcluding (listenerToExclude, fn);
90 template <
typename Function>
91 void callListenersForAllParents (ValueTree::Listener* listenerToExclude, Function fn)
const
93 for (
auto* t =
this; t !=
nullptr; t = t->parent)
94 t->callListeners (listenerToExclude, fn);
97 void sendPropertyChangeMessage (
const Identifier& property, ValueTree::Listener* listenerToExclude =
nullptr)
100 callListenersForAllParents (listenerToExclude, [&] (Listener& l) { l.valueTreePropertyChanged (tree, property); });
103 void sendChildAddedMessage (
ValueTree child)
106 callListenersForAllParents (
nullptr, [&] (Listener& l) { l.valueTreeChildAdded (tree, child); });
109 void sendChildRemovedMessage (
ValueTree child,
int index)
112 callListenersForAllParents (
nullptr, [=, &tree, &child] (Listener& l) { l.valueTreeChildRemoved (tree, child, index); });
115 void sendChildOrderChangedMessage (
int oldIndex,
int newIndex)
118 callListenersForAllParents (
nullptr, [=, &tree] (Listener& l) { l.valueTreeChildOrderChanged (tree, oldIndex, newIndex); });
121 void sendParentChangeMessage()
125 for (
auto j = children.size(); --j >= 0;)
126 if (
auto* child = children.getObjectPointer (j))
127 child->sendParentChangeMessage();
129 callListeners (
nullptr, [&] (Listener& l) { l.valueTreeParentChanged (tree); });
132 void setProperty (
const Identifier& name,
const var& newValue, UndoManager* undoManager,
133 ValueTree::Listener* listenerToExclude =
nullptr)
135 if (undoManager ==
nullptr)
137 if (properties.set (name, newValue))
138 sendPropertyChangeMessage (name, listenerToExclude);
142 if (
auto* existingValue = properties.getVarPointer (name))
144 if (*existingValue != newValue)
145 undoManager->perform (
new SetPropertyAction (*
this, name, newValue, *existingValue,
146 false,
false, listenerToExclude));
150 undoManager->perform (
new SetPropertyAction (*
this, name, newValue, {},
151 true,
false, listenerToExclude));
156 bool hasProperty (
const Identifier& name)
const noexcept
158 return properties.contains (name);
161 void removeProperty (
const Identifier& name, UndoManager* undoManager)
163 if (undoManager ==
nullptr)
165 if (properties.remove (name))
166 sendPropertyChangeMessage (name);
170 if (properties.contains (name))
171 undoManager->perform (
new SetPropertyAction (*
this, name, {}, properties[name],
false,
true));
175 void removeAllProperties (UndoManager* undoManager)
177 if (undoManager ==
nullptr)
179 while (properties.size() > 0)
181 auto name = properties.getName (properties.size() - 1);
182 properties.remove (name);
183 sendPropertyChangeMessage (name);
188 for (
auto i = properties.size(); --i >= 0;)
189 undoManager->perform (
new SetPropertyAction (*
this, properties.getName (i), {},
190 properties.getValueAt (i),
false,
true));
194 void copyPropertiesFrom (
const SharedObject& source, UndoManager* undoManager)
196 for (
auto i = properties.size(); --i >= 0;)
197 if (! source.properties.contains (properties.getName (i)))
198 removeProperty (properties.getName (i), undoManager);
200 for (
int i = 0; i < source.properties.size(); ++i)
201 setProperty (source.properties.getName (i), source.properties.getValueAt (i), undoManager);
204 ValueTree getChildWithName (
const Identifier& typeToMatch)
const
206 for (
auto* s : children)
207 if (s->type == typeToMatch)
213 ValueTree getOrCreateChildWithName (
const Identifier& typeToMatch, UndoManager* undoManager)
215 for (
auto* s : children)
216 if (s->type == typeToMatch)
219 auto newObject =
new SharedObject (typeToMatch);
220 addChild (newObject, -1, undoManager);
224 ValueTree getChildWithProperty (
const Identifier& propertyName,
const var& propertyValue)
const
226 for (
auto* s : children)
227 if (s->properties[propertyName] == propertyValue)
233 bool isAChildOf (
const SharedObject* possibleParent)
const noexcept
235 for (
auto* p = parent; p !=
nullptr; p = p->parent)
236 if (p == possibleParent)
242 int indexOf (
const ValueTree& child)
const noexcept
244 return children.indexOf (child.object);
247 void addChild (SharedObject* child,
int index, UndoManager* undoManager)
249 if (child !=
nullptr && child->parent !=
this)
251 if (child !=
this && ! isAChildOf (child))
256 jassert (child->parent ==
nullptr);
258 if (child->parent !=
nullptr)
260 jassert (child->parent->children.indexOf (child) >= 0);
261 child->parent->removeChild (child->parent->children.indexOf (child), undoManager);
264 if (undoManager ==
nullptr)
266 children.insert (index, child);
267 child->parent =
this;
268 sendChildAddedMessage (
ValueTree (*child));
269 child->sendParentChangeMessage();
273 if (! isPositiveAndBelow (index, children.size()))
274 index = children.size();
276 undoManager->perform (
new AddOrRemoveChildAction (*
this, index, child));
288 void removeChild (
int childIndex, UndoManager* undoManager)
290 if (
auto child = Ptr (children.getObjectPointer (childIndex)))
292 if (undoManager ==
nullptr)
294 children.remove (childIndex);
295 child->parent =
nullptr;
296 sendChildRemovedMessage (
ValueTree (child), childIndex);
297 child->sendParentChangeMessage();
301 undoManager->perform (
new AddOrRemoveChildAction (*
this, childIndex, {}));
306 void removeAllChildren (UndoManager* undoManager)
308 while (children.size() > 0)
309 removeChild (children.size() - 1, undoManager);
312 void moveChild (
int currentIndex,
int newIndex, UndoManager* undoManager)
315 jassert (isPositiveAndBelow (currentIndex, children.size()));
317 if (currentIndex != newIndex
318 && isPositiveAndBelow (currentIndex, children.size()))
320 if (undoManager ==
nullptr)
322 children.move (currentIndex, newIndex);
323 sendChildOrderChangedMessage (currentIndex, newIndex);
327 if (! isPositiveAndBelow (newIndex, children.size()))
328 newIndex = children.size() - 1;
330 undoManager->perform (
new MoveChildAction (*
this, currentIndex, newIndex));
335 void reorderChildren (
const OwnedArray<ValueTree>& newOrder, UndoManager* undoManager)
337 jassert (newOrder.size() == children.size());
339 for (
int i = 0; i < children.size(); ++i)
341 auto* child = newOrder.getUnchecked (i)->object.get();
343 if (children.getObjectPointerUnchecked (i) != child)
345 auto oldIndex = children.indexOf (child);
346 jassert (oldIndex >= 0);
347 moveChild (oldIndex, i, undoManager);
352 bool isEquivalentTo (
const SharedObject& other)
const noexcept
354 if (type != other.type
355 || properties.size() != other.properties.size()
356 || children.size() != other.children.size()
357 || properties != other.properties)
360 for (
int i = 0; i < children.size(); ++i)
361 if (! children.getObjectPointerUnchecked (i)->isEquivalentTo (*other.children.getObjectPointerUnchecked (i)))
367 XmlElement* createXml()
const
369 auto* xml =
new XmlElement (type);
370 properties.copyToXmlAttributes (*xml);
373 for (
auto i = children.size(); --i >= 0;)
374 xml->prependChildElement (children.getObjectPointerUnchecked (i)->createXml());
379 void writeToStream (OutputStream& output)
const
381 output.writeString (type.toString());
382 output.writeCompressedInt (properties.size());
384 for (
int j = 0; j < properties.size(); ++j)
386 output.writeString (properties.getName (j).toString());
387 properties.getValueAt (j).writeToStream (output);
390 output.writeCompressedInt (children.size());
392 for (
auto* c : children)
393 writeObjectToStream (output, c);
396 static void writeObjectToStream (OutputStream& output,
const SharedObject*
object)
398 if (
object !=
nullptr)
400 object->writeToStream (output);
404 output.writeString ({});
405 output.writeCompressedInt (0);
406 output.writeCompressedInt (0);
411 struct SetPropertyAction final :
public UndoableAction
413 SetPropertyAction (Ptr targetObject,
const Identifier& propertyName,
414 const var& newVal,
const var& oldVal,
bool isAdding,
bool isDeleting,
415 ValueTree::Listener* listenerToExclude =
nullptr)
416 : target (std::move (targetObject)),
417 name (propertyName), newValue (newVal), oldValue (oldVal),
418 isAddingNewProperty (isAdding), isDeletingProperty (isDeleting),
419 excludeListener (listenerToExclude)
423 bool perform()
override
425 jassert (! (isAddingNewProperty && target->hasProperty (name)));
427 if (isDeletingProperty)
428 target->removeProperty (name,
nullptr);
430 target->setProperty (name, newValue,
nullptr, excludeListener);
437 if (isAddingNewProperty)
438 target->removeProperty (name,
nullptr);
440 target->setProperty (name, oldValue,
nullptr);
445 int getSizeInUnits()
override
447 return (
int)
sizeof (*this);
452 if (! (isAddingNewProperty || isDeletingProperty))
454 if (
auto* next =
dynamic_cast<SetPropertyAction*
> (nextAction))
455 if (next->target == target && next->name == name
456 && ! (next->isAddingNewProperty || next->isDeletingProperty))
457 return new SetPropertyAction (*target, name, next->newValue, oldValue,
false,
false);
465 const Identifier name;
468 const bool isAddingNewProperty : 1, isDeletingProperty : 1;
469 ValueTree::Listener* excludeListener;
471 JUCE_DECLARE_NON_COPYABLE (SetPropertyAction)
475 struct AddOrRemoveChildAction final :
public UndoableAction
477 AddOrRemoveChildAction (Ptr parentObject,
int index, SharedObject* newChild)
478 : target (std::move (parentObject)),
479 child (newChild != nullptr ? newChild : target->children.getObjectPointer (index)),
481 isDeleting (newChild == nullptr)
483 jassert (child !=
nullptr);
486 bool perform()
override
489 target->removeChild (childIndex,
nullptr);
491 target->addChild (child.get(), childIndex,
nullptr);
500 target->addChild (child.get(), childIndex,
nullptr);
506 jassert (childIndex < target->children.size());
507 target->removeChild (childIndex,
nullptr);
513 int getSizeInUnits()
override
515 return (
int)
sizeof (*this);
519 const Ptr target, child;
520 const int childIndex;
521 const bool isDeleting;
523 JUCE_DECLARE_NON_COPYABLE (AddOrRemoveChildAction)
527 struct MoveChildAction final :
public UndoableAction
529 MoveChildAction (Ptr parentObject,
int fromIndex,
int toIndex) noexcept
530 : parent (std::move (parentObject)), startIndex (fromIndex), endIndex (toIndex)
534 bool perform()
override
536 parent->moveChild (startIndex, endIndex,
nullptr);
542 parent->moveChild (endIndex, startIndex,
nullptr);
546 int getSizeInUnits()
override
548 return (
int)
sizeof (*this);
553 if (
auto* next =
dynamic_cast<MoveChildAction*
> (nextAction))
554 if (next->parent == parent && next->startIndex == endIndex)
555 return new MoveChildAction (parent, startIndex, next->endIndex);
562 const int startIndex, endIndex;
564 JUCE_DECLARE_NON_COPYABLE (MoveChildAction)
568 const Identifier type;
569 NamedValueSet properties;
570 ReferenceCountedArray<SharedObject> children;
571 SortedSet<ValueTree*> valueTreesWithListeners;
572 SharedObject* parent =
nullptr;
574 JUCE_LEAK_DETECTOR (SharedObject)
588 std::initializer_list<NamedValueSet::NamedValue> properties,
589 std::initializer_list<ValueTree> subTrees)
594 for (
auto& tree : subTrees)
607 if (
object != other.object)
609 if (listeners.isEmpty())
611 object = other.object;
615 if (
object !=
nullptr)
616 object->valueTreesWithListeners.removeValue (
this);
618 if (other.object !=
nullptr)
619 other.object->valueTreesWithListeners.add (
this);
621 object = other.object;
631 : object (std::move (other.object))
633 if (
object !=
nullptr)
634 object->valueTreesWithListeners.removeValue (&other);
639 if (! listeners.isEmpty() &&
object !=
nullptr)
640 object->valueTreesWithListeners.removeValue (
this);
645 return object == other.object;
650 return object != other.object;
655 return object == other.object
656 || (
object !=
nullptr && other.object !=
nullptr
657 &&
object->isEquivalentTo (*other.object));
662 if (
object !=
nullptr)
663 return ValueTree (*
new SharedObject (*
object));
670 jassert (
object !=
nullptr || source.object ==
nullptr);
675 if (source.object ==
nullptr)
677 else if (
object !=
nullptr)
678 object->copyPropertiesFrom (*(source.object), undoManager);
683 jassert (
object !=
nullptr || source.object ==
nullptr);
691 if (
object !=
nullptr && source.object !=
nullptr)
692 for (
auto& child : source.object->children)
693 object->addChild (createCopyIfNotNull (child), -1, undoManager);
698 return object !=
nullptr &&
object->type == typeName;
703 return object !=
nullptr ?
object->type :
Identifier();
708 if (
object !=
nullptr)
709 if (
auto p = object->parent)
717 if (
object !=
nullptr)
725 if (
object !=
nullptr)
726 if (
auto* p = object->parent)
727 if (
auto* c = p->children.getObjectPointer (p->indexOf (*
this) + delta))
733static const var& getNullVarRef() noexcept
741 return object ==
nullptr ? getNullVarRef() :
object->properties[name];
746 return object ==
nullptr ? getNullVarRef() :
object->properties[name];
751 return object ==
nullptr ? defaultReturnValue
752 :
object->properties.getWithDefault (name, defaultReturnValue);
757 return object ==
nullptr ? nullptr
758 :
object->properties.getVarPointer (name);
770 jassert (
object !=
nullptr);
772 if (
object !=
nullptr)
773 object->setProperty (name, newValue, undoManager, listenerToExclude);
780 return object !=
nullptr &&
object->hasProperty (name);
785 if (
object !=
nullptr)
786 object->removeProperty (name, undoManager);
791 if (
object !=
nullptr)
792 object->removeAllProperties (undoManager);
797 return object ==
nullptr ? 0 :
object->properties.size();
803 :
object->properties.getName (index);
808 return object !=
nullptr ?
object->getReferenceCount() : 0;
816 : tree (vt), property (prop), undoManager (um), updateSynchronously (sync)
821 ~ValueTreePropertyValueSource()
override
826 var getValue()
const override {
return tree[property]; }
827 void setValue (
const var& newValue)
override { tree.setProperty (property, newValue, undoManager); }
831 const Identifier property;
832 UndoManager*
const undoManager;
833 const bool updateSynchronously;
835 void valueTreePropertyChanged (ValueTree& changedTree,
const Identifier& changedProperty)
override
837 if (tree == changedTree && property == changedProperty)
841 void valueTreeChildAdded (ValueTree&, ValueTree&)
override {}
842 void valueTreeChildRemoved (ValueTree&, ValueTree&,
int)
override {}
843 void valueTreeChildOrderChanged (ValueTree&,
int,
int)
override {}
844 void valueTreeParentChanged (ValueTree&)
override {}
846 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueTreePropertyValueSource)
851 return Value (
new ValueTreePropertyValueSource (*
this, name, undoManager, updateSynchronously));
857 return object ==
nullptr ? 0 :
object->children.size();
862 if (
object !=
nullptr)
863 if (
auto* c = object->children.getObjectPointer (index))
869ValueTree::Iterator::Iterator (
const ValueTree& v,
bool isEnd)
870 : internal (v.object != nullptr ? (isEnd ? v.object->children.end() : v.object->children.begin()) : nullptr)
874ValueTree::Iterator& ValueTree::Iterator::operator++()
880bool ValueTree::Iterator::operator== (
const Iterator& other)
const {
return internal == other.internal; }
881bool ValueTree::Iterator::operator!= (
const Iterator& other)
const {
return internal != other.internal; }
883ValueTree ValueTree::Iterator::operator*()
const
885 return ValueTree (SharedObject::Ptr (*internal));
908 return object !=
nullptr &&
object->isAChildOf (possibleParent.object.get());
913 return object !=
nullptr ?
object->indexOf (child) : -1;
918 jassert (
object !=
nullptr);
920 if (
object !=
nullptr)
921 object->addChild (child.object.
get(), index, undoManager);
931 if (
object !=
nullptr)
932 object->removeChild (childIndex, undoManager);
937 if (
object !=
nullptr)
938 object->removeChild (object->children.indexOf (child.object), undoManager);
943 if (
object !=
nullptr)
944 object->removeAllChildren (undoManager);
949 if (
object !=
nullptr)
950 object->moveChild (currentIndex, newIndex, undoManager);
956 if (
object !=
nullptr)
957 for (
auto* o : object->children)
962void ValueTree::reorderChildren (
const OwnedArray<ValueTree>& newOrder, UndoManager* undoManager)
964 if (
object !=
nullptr)
965 object->reorderChildren (newOrder, undoManager);
971 if (listener !=
nullptr)
973 if (listeners.isEmpty() &&
object !=
nullptr)
974 object->valueTreesWithListeners.add (
this);
976 listeners.add (listener);
982 listeners.remove (listener);
984 if (listeners.isEmpty() &&
object !=
nullptr)
985 object->valueTreesWithListeners.removeValue (
this);
990 if (
object !=
nullptr)
991 object->sendPropertyChangeMessage (property);
997 return std::unique_ptr<XmlElement> (
object !=
nullptr ? object->createXml() :
nullptr);
1005 v.object->properties.setFromXmlAttributes (xml);
1020 if (
auto xml = parseXML (xmlText))
1029 return xml->toString (format);
1037 SharedObject::writeObjectToStream (output,
object.get());
1057 for (
int i = 0; i < numProps; ++i)
1061 if (name.isNotEmpty())
1068 v.object->children.ensureStorageAllocated (numChildren);
1070 for (
int i = 0; i < numChildren; ++i)
1074 if (! child.isValid())
1077 v.object->children.add (child.object);
1078 child.object->parent = v.object.
get();
1105#if JUCE_ALLOW_STATIC_NULL_VARIABLES
1107JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wdeprecated-declarations")
1108JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
1112JUCE_END_IGNORE_WARNINGS_GCC_LIKE
1113JUCE_END_IGNORE_WARNINGS_MSVC
1121class ValueTreeTests final :
public UnitTest
1125 :
UnitTest (
"ValueTrees", UnitTestCategories::values)
1130 char buffer[50] = { 0 };
1131 const char chars[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:";
1133 for (
int i = 1 + r.
nextInt (numElementsInArray (buffer) - 2); --i >= 0;)
1134 buffer[i] = chars[r.
nextInt (sizeof (chars) - 1)];
1136 String result (buffer);
1138 if (! XmlElement::isValidXmlName (result))
1139 result = createRandomIdentifier (r);
1144 static String createRandomWideCharString (Random& r)
1146 juce_wchar buffer[50] = { 0 };
1148 for (
int i = r.nextInt (numElementsInArray (buffer) - 1); --i >= 0;)
1154 buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
1156 while (! CharPointer_UTF16::canRepresent (buffer[i]));
1159 buffer[i] = (juce_wchar) (1 + r.nextInt (0x7e));
1162 return CharPointer_UTF32 (buffer);
1165 static ValueTree createRandomTree (UndoManager* undoManager,
int depth, Random& r)
1167 ValueTree v (createRandomIdentifier (r));
1169 for (
int i = r.nextInt (10); --i >= 0;)
1171 switch (r.nextInt (5))
1173 case 0: v.setProperty (createRandomIdentifier (r), createRandomWideCharString (r), undoManager);
break;
1174 case 1: v.setProperty (createRandomIdentifier (r), r.nextInt(), undoManager);
break;
1175 case 2:
if (depth < 5) v.addChild (createRandomTree (undoManager, depth + 1, r), r.nextInt (v.getNumChildren() + 1), undoManager);
break;
1176 case 3: v.setProperty (createRandomIdentifier (r), r.nextBool(), undoManager);
break;
1177 case 4: v.setProperty (createRandomIdentifier (r), r.nextDouble(), undoManager);
break;
1185 void runTest()
override
1188 beginTest (
"ValueTree");
1190 auto r = getRandom();
1192 for (
int i = 10; --i >= 0;)
1194 MemoryOutputStream mo;
1195 auto v1 = createRandomTree (
nullptr, 0, r);
1196 v1.writeToStream (mo);
1198 MemoryInputStream mi (mo.getData(), mo.getDataSize(),
false);
1199 auto v2 = ValueTree::readFromStream (mi);
1200 expect (v1.isEquivalentTo (v2));
1202 MemoryOutputStream zipped;
1204 GZIPCompressorOutputStream zippedOut (zipped);
1205 v1.writeToStream (zippedOut);
1207 expect (v1.isEquivalentTo (ValueTree::readFromGZIPData (zipped.getData(), zipped.getDataSize())));
1209 auto xml1 = v1.createXml();
1210 auto xml2 = v2.createCopy().createXml();
1211 expect (xml1->isEquivalentTo (xml2.get(),
false));
1213 auto v4 = v2.createCopy();
1214 expect (v1.isEquivalentTo (v4));
1219 beginTest (
"Float formatting");
1221 ValueTree testVT (
"Test");
1222 Identifier number (
"number");
1224 std::map<double, String> tests;
1227 tests[1.01] =
"1.01";
1228 tests[0.76378] =
"0.76378";
1229 tests[-10] =
"-10.0";
1230 tests[10.01] =
"10.01";
1231 tests[0.0123] =
"0.0123";
1232 tests[-3.7e-27] =
"-3.7e-27";
1233 tests[1e+40] =
"1.0e40";
1234 tests[-12345678901234567.0] =
"-1.234567890123457e16";
1235 tests[192000] =
"192000.0";
1236 tests[1234567] =
"1.234567e6";
1237 tests[0.00006] =
"0.00006";
1238 tests[0.000006] =
"6.0e-6";
1240 for (
auto& test : tests)
1242 testVT.setProperty (number, test.first,
nullptr);
1243 auto lines = StringArray::fromLines (testVT.toXmlString());
1244 lines.removeEmptyStrings();
1245 auto numLines = lines.size();
1246 expect (numLines > 1);
1247 expectEquals (lines[numLines - 1],
"<Test number=\"" + test.second +
"\"/>");
1253static ValueTreeTests valueTreeTests;
const String & toString() const noexcept
ObjectClass * add(ObjectClass *newObject)
ReferencedType * get() const noexcept
ReferenceCountedObject()=default
bool isNotEmpty() const noexcept
virtual void valueTreeRedirected(ValueTree &treeWhichHasBeenChanged)
virtual void valueTreeChildRemoved(ValueTree &parentTree, ValueTree &childWhichHasBeenRemoved, int indexFromWhichChildWasRemoved)
virtual void valueTreeChildOrderChanged(ValueTree &parentTreeWhoseChildrenHaveMoved, int oldIndex, int newIndex)
virtual void valueTreeParentChanged(ValueTree &treeWhoseParentHasChanged)
virtual void valueTreePropertyChanged(ValueTree &treeWhosePropertyHasChanged, const Identifier &property)
virtual void valueTreeChildAdded(ValueTree &parentTree, ValueTree &childWhichHasBeenAdded)
Value getPropertyAsValue(const Identifier &name, UndoManager *undoManager, bool shouldUpdateSynchronously=false)
Identifier getPropertyName(int index) const noexcept
Iterator begin() const noexcept
bool operator!=(const ValueTree &) const noexcept
std::unique_ptr< XmlElement > createXml() const
bool hasType(const Identifier &typeName) const noexcept
static ValueTree readFromStream(InputStream &input)
void removeChild(const ValueTree &child, UndoManager *undoManager)
String toXmlString(const XmlElement::TextFormat &format={}) const
static ValueTree readFromGZIPData(const void *data, size_t numBytes)
ValueTree getChild(int index) const
int getNumProperties() const noexcept
int getNumChildren() const noexcept
void copyPropertiesFrom(const ValueTree &source, UndoManager *undoManager)
int getReferenceCount() const noexcept
const var * getPropertyPointer(const Identifier &name) const noexcept
ValueTree & setProperty(const Identifier &name, const var &newValue, UndoManager *undoManager)
void removeAllChildren(UndoManager *undoManager)
bool isAChildOf(const ValueTree &possibleParent) const noexcept
void removeAllProperties(UndoManager *undoManager)
void addListener(Listener *listener)
void appendChild(const ValueTree &child, UndoManager *undoManager)
int indexOf(const ValueTree &child) const noexcept
bool operator==(const ValueTree &) const noexcept
ValueTree & setPropertyExcludingListener(Listener *listenerToExclude, const Identifier &name, const var &newValue, UndoManager *undoManager)
void addChild(const ValueTree &child, int index, UndoManager *undoManager)
ValueTree getParent() const noexcept
const var & getProperty(const Identifier &name) const noexcept
static ValueTree fromXml(const XmlElement &xml)
ValueTree createCopy() const
Identifier getType() const noexcept
ValueTree getChildWithName(const Identifier &type) const
Iterator end() const noexcept
ValueTree & operator=(const ValueTree &)
void removeListener(Listener *listener)
void writeToStream(OutputStream &output) const
bool isEquivalentTo(const ValueTree &) const
ValueTree getOrCreateChildWithName(const Identifier &type, UndoManager *undoManager)
void moveChild(int currentIndex, int newIndex, UndoManager *undoManager)
void sendPropertyChangeMessage(const Identifier &property)
void removeProperty(const Identifier &name, UndoManager *undoManager)
const var & operator[](const Identifier &name) const noexcept
ValueTree getSibling(int delta) const noexcept
ValueTree getChildWithProperty(const Identifier &propertyName, const var &propertyValue) const
void copyPropertiesAndChildrenFrom(const ValueTree &source, UndoManager *undoManager)
ValueTree getRoot() const noexcept
static ValueTree readFromData(const void *data, size_t numBytes)
bool hasProperty(const Identifier &name) const noexcept
void sendChangeMessage(bool dispatchSynchronously)
bool isTextElement() const noexcept
Iterator< GetNextElement > getChildIterator() const
const String & getTagName() const noexcept
static var readFromStream(InputStream &input)