OpenShot Library | libopenshot-audio  0.2.0
juce_ValueTree.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  By using JUCE, you agree to the terms of both the JUCE 5 End-User License
11  Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12  27th April 2017).
13 
14  End User License Agreement: www.juce.com/juce-5-licence
15  Privacy Policy: www.juce.com/juce-5-privacy-policy
16 
17  Or: You may also use this code under the terms of the GPL v3 (see
18  www.gnu.org/licenses).
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
31 {
32 public:
34 
35  explicit SharedObject (const Identifier& t) noexcept : type (t) {}
36 
37  SharedObject (const SharedObject& other)
38  : ReferenceCountedObject(), type (other.type), properties (other.properties)
39  {
40  for (auto* c : other.children)
41  {
42  auto* child = new SharedObject (*c);
43  child->parent = this;
44  children.add (child);
45  }
46  }
47 
48  SharedObject& operator= (const SharedObject&) = delete;
49 
50  ~SharedObject()
51  {
52  jassert (parent == nullptr); // this should never happen unless something isn't obeying the ref-counting!
53 
54  for (auto i = children.size(); --i >= 0;)
55  {
56  const Ptr c (children.getObjectPointerUnchecked (i));
57  c->parent = nullptr;
58  children.remove (i);
59  c->sendParentChangeMessage();
60  }
61  }
62 
63  SharedObject& getRoot() noexcept
64  {
65  return parent == nullptr ? *this : parent->getRoot();
66  }
67 
68  template <typename Function>
69  void callListeners (ValueTree::Listener* listenerToExclude, Function fn) const
70  {
71  auto numListeners = valueTreesWithListeners.size();
72 
73  if (numListeners == 1)
74  {
75  valueTreesWithListeners.getUnchecked (0)->listeners.callExcluding (listenerToExclude, fn);
76  }
77  else if (numListeners > 0)
78  {
79  auto listenersCopy = valueTreesWithListeners;
80 
81  for (int i = 0; i < numListeners; ++i)
82  {
83  auto* v = listenersCopy.getUnchecked (i);
84 
85  if (i == 0 || valueTreesWithListeners.contains (v))
86  v->listeners.callExcluding (listenerToExclude, fn);
87  }
88  }
89  }
90 
91  template <typename Function>
92  void callListenersForAllParents (ValueTree::Listener* listenerToExclude, Function fn) const
93  {
94  for (auto* t = this; t != nullptr; t = t->parent)
95  t->callListeners (listenerToExclude, fn);
96  }
97 
98  void sendPropertyChangeMessage (const Identifier& property, ValueTree::Listener* listenerToExclude = nullptr)
99  {
100  ValueTree tree (*this);
101  callListenersForAllParents (listenerToExclude, [&] (Listener& l) { l.valueTreePropertyChanged (tree, property); });
102  }
103 
104  void sendChildAddedMessage (ValueTree child)
105  {
106  ValueTree tree (*this);
107  callListenersForAllParents (nullptr, [&] (Listener& l) { l.valueTreeChildAdded (tree, child); });
108  }
109 
110  void sendChildRemovedMessage (ValueTree child, int index)
111  {
112  ValueTree tree (*this);
113  callListenersForAllParents (nullptr, [=, &tree, &child] (Listener& l) { l.valueTreeChildRemoved (tree, child, index); });
114  }
115 
116  void sendChildOrderChangedMessage (int oldIndex, int newIndex)
117  {
118  ValueTree tree (*this);
119  callListenersForAllParents (nullptr, [=, &tree] (Listener& l) { l.valueTreeChildOrderChanged (tree, oldIndex, newIndex); });
120  }
121 
122  void sendParentChangeMessage()
123  {
124  ValueTree tree (*this);
125 
126  for (auto j = children.size(); --j >= 0;)
127  if (auto* child = children.getObjectPointer (j))
128  child->sendParentChangeMessage();
129 
130  callListeners (nullptr, [&] (Listener& l) { l.valueTreeParentChanged (tree); });
131  }
132 
133  void setProperty (const Identifier& name, const var& newValue, UndoManager* undoManager,
134  ValueTree::Listener* listenerToExclude = nullptr)
135  {
136  if (undoManager == nullptr)
137  {
138  if (properties.set (name, newValue))
139  sendPropertyChangeMessage (name, listenerToExclude);
140  }
141  else
142  {
143  if (auto* existingValue = properties.getVarPointer (name))
144  {
145  if (*existingValue != newValue)
146  undoManager->perform (new SetPropertyAction (*this, name, newValue, *existingValue,
147  false, false, listenerToExclude));
148  }
149  else
150  {
151  undoManager->perform (new SetPropertyAction (*this, name, newValue, {},
152  true, false, listenerToExclude));
153  }
154  }
155  }
156 
157  bool hasProperty (const Identifier& name) const noexcept
158  {
159  return properties.contains (name);
160  }
161 
162  void removeProperty (const Identifier& name, UndoManager* undoManager)
163  {
164  if (undoManager == nullptr)
165  {
166  if (properties.remove (name))
167  sendPropertyChangeMessage (name);
168  }
169  else
170  {
171  if (properties.contains (name))
172  undoManager->perform (new SetPropertyAction (*this, name, {}, properties[name], false, true));
173  }
174  }
175 
176  void removeAllProperties (UndoManager* undoManager)
177  {
178  if (undoManager == nullptr)
179  {
180  while (properties.size() > 0)
181  {
182  auto name = properties.getName (properties.size() - 1);
183  properties.remove (name);
184  sendPropertyChangeMessage (name);
185  }
186  }
187  else
188  {
189  for (auto i = properties.size(); --i >= 0;)
190  undoManager->perform (new SetPropertyAction (*this, properties.getName (i), {},
191  properties.getValueAt (i), false, true));
192  }
193  }
194 
195  void copyPropertiesFrom (const SharedObject& source, UndoManager* undoManager)
196  {
197  for (auto i = properties.size(); --i >= 0;)
198  if (! source.properties.contains (properties.getName (i)))
199  removeProperty (properties.getName (i), undoManager);
200 
201  for (int i = 0; i < source.properties.size(); ++i)
202  setProperty (source.properties.getName (i), source.properties.getValueAt (i), undoManager);
203  }
204 
205  ValueTree getChildWithName (const Identifier& typeToMatch) const
206  {
207  for (auto* s : children)
208  if (s->type == typeToMatch)
209  return ValueTree (*s);
210 
211  return {};
212  }
213 
214  ValueTree getOrCreateChildWithName (const Identifier& typeToMatch, UndoManager* undoManager)
215  {
216  for (auto* s : children)
217  if (s->type == typeToMatch)
218  return ValueTree (*s);
219 
220  auto newObject = new SharedObject (typeToMatch);
221  addChild (newObject, -1, undoManager);
222  return ValueTree (*newObject);
223  }
224 
225  ValueTree getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const
226  {
227  for (auto* s : children)
228  if (s->properties[propertyName] == propertyValue)
229  return ValueTree (*s);
230 
231  return {};
232  }
233 
234  bool isAChildOf (const SharedObject* possibleParent) const noexcept
235  {
236  for (auto* p = parent; p != nullptr; p = p->parent)
237  if (p == possibleParent)
238  return true;
239 
240  return false;
241  }
242 
243  int indexOf (const ValueTree& child) const noexcept
244  {
245  return children.indexOf (child.object);
246  }
247 
248  void addChild (SharedObject* child, int index, UndoManager* undoManager)
249  {
250  if (child != nullptr && child->parent != this)
251  {
252  if (child != this && ! isAChildOf (child))
253  {
254  // You should always make sure that a child is removed from its previous parent before
255  // adding it somewhere else - otherwise, it's ambiguous as to whether a different
256  // undomanager should be used when removing it from its current parent..
257  jassert (child->parent == nullptr);
258 
259  if (child->parent != nullptr)
260  {
261  jassert (child->parent->children.indexOf (child) >= 0);
262  child->parent->removeChild (child->parent->children.indexOf (child), undoManager);
263  }
264 
265  if (undoManager == nullptr)
266  {
267  children.insert (index, child);
268  child->parent = this;
269  sendChildAddedMessage (ValueTree (*child));
270  child->sendParentChangeMessage();
271  }
272  else
273  {
274  if (! isPositiveAndBelow (index, children.size()))
275  index = children.size();
276 
277  undoManager->perform (new AddOrRemoveChildAction (*this, index, child));
278  }
279  }
280  else
281  {
282  // You're attempting to create a recursive loop! A node
283  // can't be a child of one of its own children!
284  jassertfalse;
285  }
286  }
287  }
288 
289  void removeChild (int childIndex, UndoManager* undoManager)
290  {
291  if (auto child = Ptr (children.getObjectPointer (childIndex)))
292  {
293  if (undoManager == nullptr)
294  {
295  children.remove (childIndex);
296  child->parent = nullptr;
297  sendChildRemovedMessage (ValueTree (child), childIndex);
298  child->sendParentChangeMessage();
299  }
300  else
301  {
302  undoManager->perform (new AddOrRemoveChildAction (*this, childIndex, {}));
303  }
304  }
305  }
306 
307  void removeAllChildren (UndoManager* undoManager)
308  {
309  while (children.size() > 0)
310  removeChild (children.size() - 1, undoManager);
311  }
312 
313  void moveChild (int currentIndex, int newIndex, UndoManager* undoManager)
314  {
315  // The source index must be a valid index!
316  jassert (isPositiveAndBelow (currentIndex, children.size()));
317 
318  if (currentIndex != newIndex
319  && isPositiveAndBelow (currentIndex, children.size()))
320  {
321  if (undoManager == nullptr)
322  {
323  children.move (currentIndex, newIndex);
324  sendChildOrderChangedMessage (currentIndex, newIndex);
325  }
326  else
327  {
328  if (! isPositiveAndBelow (newIndex, children.size()))
329  newIndex = children.size() - 1;
330 
331  undoManager->perform (new MoveChildAction (*this, currentIndex, newIndex));
332  }
333  }
334  }
335 
336  void reorderChildren (const OwnedArray<ValueTree>& newOrder, UndoManager* undoManager)
337  {
338  jassert (newOrder.size() == children.size());
339 
340  for (int i = 0; i < children.size(); ++i)
341  {
342  auto* child = newOrder.getUnchecked (i)->object.get();
343 
344  if (children.getObjectPointerUnchecked (i) != child)
345  {
346  auto oldIndex = children.indexOf (child);
347  jassert (oldIndex >= 0);
348  moveChild (oldIndex, i, undoManager);
349  }
350  }
351  }
352 
353  bool isEquivalentTo (const SharedObject& other) const noexcept
354  {
355  if (type != other.type
356  || properties.size() != other.properties.size()
357  || children.size() != other.children.size()
358  || properties != other.properties)
359  return false;
360 
361  for (int i = 0; i < children.size(); ++i)
362  if (! children.getObjectPointerUnchecked (i)->isEquivalentTo (*other.children.getObjectPointerUnchecked (i)))
363  return false;
364 
365  return true;
366  }
367 
368  XmlElement* createXml() const
369  {
370  auto* xml = new XmlElement (type);
371  properties.copyToXmlAttributes (*xml);
372 
373  // (NB: it's faster to add nodes to XML elements in reverse order)
374  for (auto i = children.size(); --i >= 0;)
375  xml->prependChildElement (children.getObjectPointerUnchecked (i)->createXml());
376 
377  return xml;
378  }
379 
380  void writeToStream (OutputStream& output) const
381  {
382  output.writeString (type.toString());
383  output.writeCompressedInt (properties.size());
384 
385  for (int j = 0; j < properties.size(); ++j)
386  {
387  output.writeString (properties.getName (j).toString());
388  properties.getValueAt (j).writeToStream (output);
389  }
390 
391  output.writeCompressedInt (children.size());
392 
393  for (auto* c : children)
394  writeObjectToStream (output, c);
395  }
396 
397  static void writeObjectToStream (OutputStream& output, const SharedObject* object)
398  {
399  if (object != nullptr)
400  {
401  object->writeToStream (output);
402  }
403  else
404  {
405  output.writeString ({});
406  output.writeCompressedInt (0);
407  output.writeCompressedInt (0);
408  }
409  }
410 
411  //==============================================================================
413  {
414  SetPropertyAction (Ptr targetObject, const Identifier& propertyName,
415  const var& newVal, const var& oldVal, bool isAdding, bool isDeleting,
416  ValueTree::Listener* listenerToExclude = nullptr)
417  : target (std::move (targetObject)),
418  name (propertyName), newValue (newVal), oldValue (oldVal),
419  isAddingNewProperty (isAdding), isDeletingProperty (isDeleting),
420  excludeListener (listenerToExclude)
421  {
422  }
423 
424  bool perform() override
425  {
426  jassert (! (isAddingNewProperty && target->hasProperty (name)));
427 
428  if (isDeletingProperty)
429  target->removeProperty (name, nullptr);
430  else
431  target->setProperty (name, newValue, nullptr, excludeListener);
432 
433  return true;
434  }
435 
436  bool undo() override
437  {
438  if (isAddingNewProperty)
439  target->removeProperty (name, nullptr);
440  else
441  target->setProperty (name, oldValue, nullptr);
442 
443  return true;
444  }
445 
446  int getSizeInUnits() override
447  {
448  return (int) sizeof (*this); //xxx should be more accurate
449  }
450 
452  {
453  if (! (isAddingNewProperty || isDeletingProperty))
454  {
455  if (auto* next = dynamic_cast<SetPropertyAction*> (nextAction))
456  if (next->target == target && next->name == name
457  && ! (next->isAddingNewProperty || next->isDeletingProperty))
458  return new SetPropertyAction (*target, name, next->newValue, oldValue, false, false);
459  }
460 
461  return nullptr;
462  }
463 
464  private:
465  const Ptr target;
466  const Identifier name;
467  const var newValue;
468  var oldValue;
469  const bool isAddingNewProperty : 1, isDeletingProperty : 1;
470  ValueTree::Listener* excludeListener;
471 
472  JUCE_DECLARE_NON_COPYABLE (SetPropertyAction)
473  };
474 
475  //==============================================================================
477  {
478  AddOrRemoveChildAction (Ptr parentObject, int index, SharedObject* newChild)
479  : target (std::move (parentObject)),
480  child (newChild != nullptr ? newChild : target->children.getObjectPointer (index)),
481  childIndex (index),
482  isDeleting (newChild == nullptr)
483  {
484  jassert (child != nullptr);
485  }
486 
487  bool perform() override
488  {
489  if (isDeleting)
490  target->removeChild (childIndex, nullptr);
491  else
492  target->addChild (child.get(), childIndex, nullptr);
493 
494  return true;
495  }
496 
497  bool undo() override
498  {
499  if (isDeleting)
500  {
501  target->addChild (child.get(), childIndex, nullptr);
502  }
503  else
504  {
505  // If you hit this, it seems that your object's state is getting confused - probably
506  // because you've interleaved some undoable and non-undoable operations?
507  jassert (childIndex < target->children.size());
508  target->removeChild (childIndex, nullptr);
509  }
510 
511  return true;
512  }
513 
514  int getSizeInUnits() override
515  {
516  return (int) sizeof (*this); //xxx should be more accurate
517  }
518 
519  private:
520  const Ptr target, child;
521  const int childIndex;
522  const bool isDeleting;
523 
524  JUCE_DECLARE_NON_COPYABLE (AddOrRemoveChildAction)
525  };
526 
527  //==============================================================================
529  {
530  MoveChildAction (Ptr parentObject, int fromIndex, int toIndex) noexcept
531  : parent (std::move (parentObject)), startIndex (fromIndex), endIndex (toIndex)
532  {
533  }
534 
535  bool perform() override
536  {
537  parent->moveChild (startIndex, endIndex, nullptr);
538  return true;
539  }
540 
541  bool undo() override
542  {
543  parent->moveChild (endIndex, startIndex, nullptr);
544  return true;
545  }
546 
547  int getSizeInUnits() override
548  {
549  return (int) sizeof (*this); //xxx should be more accurate
550  }
551 
553  {
554  if (auto* next = dynamic_cast<MoveChildAction*> (nextAction))
555  if (next->parent == parent && next->startIndex == endIndex)
556  return new MoveChildAction (parent, startIndex, next->endIndex);
557 
558  return nullptr;
559  }
560 
561  private:
562  const Ptr parent;
563  const int startIndex, endIndex;
564 
565  JUCE_DECLARE_NON_COPYABLE (MoveChildAction)
566  };
567 
568  //==============================================================================
569  const Identifier type;
570  NamedValueSet properties;
572  SortedSet<ValueTree*> valueTreesWithListeners;
573  SharedObject* parent = nullptr;
574 
575  JUCE_LEAK_DETECTOR (SharedObject)
576 };
577 
578 //==============================================================================
580 {
581 }
582 
583 JUCE_DECLARE_DEPRECATED_STATIC (const ValueTree ValueTree::invalid;)
584 
585 ValueTree::ValueTree (const Identifier& type) : object (new ValueTree::SharedObject (type))
586 {
587  jassert (type.toString().isNotEmpty()); // All objects must be given a sensible type name!
588 }
589 
591  std::initializer_list<NamedValueSet::NamedValue> properties,
592  std::initializer_list<ValueTree> subTrees)
593  : ValueTree (type)
594 {
595  object->properties = NamedValueSet (std::move (properties));
596 
597  for (auto& tree : subTrees)
598  addChild (tree, -1, nullptr);
599 }
600 
601 ValueTree::ValueTree (SharedObject::Ptr so) noexcept : object (std::move (so)) {}
602 ValueTree::ValueTree (SharedObject& so) noexcept : object (so) {}
603 
604 ValueTree::ValueTree (const ValueTree& other) noexcept : object (other.object)
605 {
606 }
607 
609 {
610  if (object != other.object)
611  {
612  if (listeners.isEmpty())
613  {
614  object = other.object;
615  }
616  else
617  {
618  if (object != nullptr)
619  object->valueTreesWithListeners.removeValue (this);
620 
621  if (other.object != nullptr)
622  other.object->valueTreesWithListeners.add (this);
623 
624  object = other.object;
625 
626  listeners.call ([this] (Listener& l) { l.valueTreeRedirected (*this); });
627  }
628  }
629 
630  return *this;
631 }
632 
633 ValueTree::ValueTree (ValueTree&& other) noexcept
634  : object (std::move (other.object))
635 {
636  if (object != nullptr)
637  object->valueTreesWithListeners.removeValue (&other);
638 }
639 
641 {
642  if (! listeners.isEmpty() && object != nullptr)
643  object->valueTreesWithListeners.removeValue (this);
644 }
645 
646 bool ValueTree::operator== (const ValueTree& other) const noexcept
647 {
648  return object == other.object;
649 }
650 
651 bool ValueTree::operator!= (const ValueTree& other) const noexcept
652 {
653  return object != other.object;
654 }
655 
656 bool ValueTree::isEquivalentTo (const ValueTree& other) const
657 {
658  return object == other.object
659  || (object != nullptr && other.object != nullptr
660  && object->isEquivalentTo (*other.object));
661 }
662 
664 {
665  if (object != nullptr)
666  return ValueTree (*new SharedObject (*object));
667 
668  return {};
669 }
670 
671 void ValueTree::copyPropertiesFrom (const ValueTree& source, UndoManager* undoManager)
672 {
673  jassert (object != nullptr || source.object == nullptr); // Trying to add properties to a null ValueTree will fail!
674 
675  if (source.object == nullptr)
676  removeAllProperties (undoManager);
677  else if (object != nullptr)
678  object->copyPropertiesFrom (*(source.object), undoManager);
679 }
680 
682 {
683  jassert (object != nullptr || source.object == nullptr); // Trying to copy to a null ValueTree will fail!
684 
685  copyPropertiesFrom (source, undoManager);
686  removeAllChildren (undoManager);
687 
688  if (object != nullptr && source.object != nullptr)
689  for (auto& child : source.object->children)
690  object->addChild (createCopyIfNotNull (child), -1, undoManager);
691 }
692 
693 bool ValueTree::hasType (const Identifier& typeName) const noexcept
694 {
695  return object != nullptr && object->type == typeName;
696 }
697 
699 {
700  return object != nullptr ? object->type : Identifier();
701 }
702 
704 {
705  if (object != nullptr)
706  if (auto p = object->parent)
707  return ValueTree (*p);
708 
709  return {};
710 }
711 
713 {
714  if (object != nullptr)
715  return ValueTree (object->getRoot());
716 
717  return {};
718 }
719 
720 ValueTree ValueTree::getSibling (int delta) const noexcept
721 {
722  if (object != nullptr)
723  if (auto* p = object->parent)
724  if (auto* c = p->children.getObjectPointer (p->indexOf (*this) + delta))
725  return ValueTree (*c);
726 
727  return {};
728 }
729 
730 static const var& getNullVarRef() noexcept
731 {
732  static var nullVar;
733  return nullVar;
734 }
735 
736 const var& ValueTree::operator[] (const Identifier& name) const noexcept
737 {
738  return object == nullptr ? getNullVarRef() : object->properties[name];
739 }
740 
741 const var& ValueTree::getProperty (const Identifier& name) const noexcept
742 {
743  return object == nullptr ? getNullVarRef() : object->properties[name];
744 }
745 
746 var ValueTree::getProperty (const Identifier& name, const var& defaultReturnValue) const
747 {
748  return object == nullptr ? defaultReturnValue
749  : object->properties.getWithDefault (name, defaultReturnValue);
750 }
751 
752 const var* ValueTree::getPropertyPointer (const Identifier& name) const noexcept
753 {
754  return object == nullptr ? nullptr
755  : object->properties.getVarPointer (name);
756 }
757 
758 ValueTree& ValueTree::setProperty (const Identifier& name, const var& newValue, UndoManager* undoManager)
759 {
760  return setPropertyExcludingListener (nullptr, name, newValue, undoManager);
761 }
762 
764  const var& newValue, UndoManager* undoManager)
765 {
766  jassert (name.toString().isNotEmpty()); // Must have a valid property name!
767  jassert (object != nullptr); // Trying to add a property to a null ValueTree will fail!
768 
769  if (object != nullptr)
770  object->setProperty (name, newValue, undoManager, listenerToExclude);
771 
772  return *this;
773 }
774 
775 bool ValueTree::hasProperty (const Identifier& name) const noexcept
776 {
777  return object != nullptr && object->hasProperty (name);
778 }
779 
780 void ValueTree::removeProperty (const Identifier& name, UndoManager* undoManager)
781 {
782  if (object != nullptr)
783  object->removeProperty (name, undoManager);
784 }
785 
787 {
788  if (object != nullptr)
789  object->removeAllProperties (undoManager);
790 }
791 
792 int ValueTree::getNumProperties() const noexcept
793 {
794  return object == nullptr ? 0 : object->properties.size();
795 }
796 
797 Identifier ValueTree::getPropertyName (int index) const noexcept
798 {
799  return object == nullptr ? Identifier()
800  : object->properties.getName (index);
801 }
802 
803 int ValueTree::getReferenceCount() const noexcept
804 {
805  return object != nullptr ? object->getReferenceCount() : 0;
806 }
807 
808 //==============================================================================
810  private ValueTree::Listener
811 {
812  ValueTreePropertyValueSource (const ValueTree& vt, const Identifier& prop, UndoManager* um, bool sync)
813  : tree (vt), property (prop), undoManager (um), updateSynchronously (sync)
814  {
815  tree.addListener (this);
816  }
817 
818  ~ValueTreePropertyValueSource() override
819  {
820  tree.removeListener (this);
821  }
822 
823  var getValue() const override { return tree[property]; }
824  void setValue (const var& newValue) override { tree.setProperty (property, newValue, undoManager); }
825 
826 private:
827  ValueTree tree;
828  const Identifier property;
829  UndoManager* const undoManager;
830  const bool updateSynchronously;
831 
832  void valueTreePropertyChanged (ValueTree& changedTree, const Identifier& changedProperty) override
833  {
834  if (tree == changedTree && property == changedProperty)
835  sendChangeMessage (updateSynchronously);
836  }
837 
838  void valueTreeChildAdded (ValueTree&, ValueTree&) override {}
839  void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override {}
840  void valueTreeChildOrderChanged (ValueTree&, int, int) override {}
841  void valueTreeParentChanged (ValueTree&) override {}
842 
843  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueTreePropertyValueSource)
844 };
845 
846 Value ValueTree::getPropertyAsValue (const Identifier& name, UndoManager* undoManager, bool updateSynchronously)
847 {
848  return Value (new ValueTreePropertyValueSource (*this, name, undoManager, updateSynchronously));
849 }
850 
851 //==============================================================================
852 int ValueTree::getNumChildren() const noexcept
853 {
854  return object == nullptr ? 0 : object->children.size();
855 }
856 
858 {
859  if (object != nullptr)
860  if (auto* c = object->children.getObjectPointer (index))
861  return ValueTree (*c);
862 
863  return {};
864 }
865 
866 ValueTree::Iterator::Iterator (const ValueTree& v, bool isEnd)
867  : internal (v.object != nullptr ? (isEnd ? v.object->children.end() : v.object->children.begin()) : nullptr)
868 {
869 }
870 
871 ValueTree::Iterator& ValueTree::Iterator::operator++()
872 {
873  internal = static_cast<SharedObject**> (internal) + 1;
874  return *this;
875 }
876 
877 bool ValueTree::Iterator::operator== (const Iterator& other) const { return internal == other.internal; }
878 bool ValueTree::Iterator::operator!= (const Iterator& other) const { return internal != other.internal; }
879 
880 ValueTree ValueTree::Iterator::operator*() const
881 {
882  return ValueTree (SharedObject::Ptr (*static_cast<SharedObject**> (internal)));
883 }
884 
885 ValueTree::Iterator ValueTree::begin() const noexcept { return Iterator (*this, false); }
886 ValueTree::Iterator ValueTree::end() const noexcept { return Iterator (*this, true); }
887 
889 {
890  return object != nullptr ? object->getChildWithName (type) : ValueTree();
891 }
892 
894 {
895  return object != nullptr ? object->getOrCreateChildWithName (type, undoManager) : ValueTree();
896 }
897 
898 ValueTree ValueTree::getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const
899 {
900  return object != nullptr ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree();
901 }
902 
903 bool ValueTree::isAChildOf (const ValueTree& possibleParent) const noexcept
904 {
905  return object != nullptr && object->isAChildOf (possibleParent.object.get());
906 }
907 
908 int ValueTree::indexOf (const ValueTree& child) const noexcept
909 {
910  return object != nullptr ? object->indexOf (child) : -1;
911 }
912 
913 void ValueTree::addChild (const ValueTree& child, int index, UndoManager* undoManager)
914 {
915  jassert (object != nullptr); // Trying to add a child to a null ValueTree!
916 
917  if (object != nullptr)
918  object->addChild (child.object.get(), index, undoManager);
919 }
920 
921 void ValueTree::appendChild (const ValueTree& child, UndoManager* undoManager)
922 {
923  addChild (child, -1, undoManager);
924 }
925 
926 void ValueTree::removeChild (int childIndex, UndoManager* undoManager)
927 {
928  if (object != nullptr)
929  object->removeChild (childIndex, undoManager);
930 }
931 
932 void ValueTree::removeChild (const ValueTree& child, UndoManager* undoManager)
933 {
934  if (object != nullptr)
935  object->removeChild (object->children.indexOf (child.object), undoManager);
936 }
937 
939 {
940  if (object != nullptr)
941  object->removeAllChildren (undoManager);
942 }
943 
944 void ValueTree::moveChild (int currentIndex, int newIndex, UndoManager* undoManager)
945 {
946  if (object != nullptr)
947  object->moveChild (currentIndex, newIndex, undoManager);
948 }
949 
950 //==============================================================================
951 void ValueTree::createListOfChildren (OwnedArray<ValueTree>& list) const
952 {
953  jassert (object != nullptr);
954 
955  for (auto* o : object->children)
956  {
957  jassert (o != nullptr);
958  list.add (new ValueTree (*o));
959  }
960 }
961 
962 void ValueTree::reorderChildren (const OwnedArray<ValueTree>& newOrder, UndoManager* undoManager)
963 {
964  jassert (object != nullptr);
965  object->reorderChildren (newOrder, undoManager);
966 }
967 
968 //==============================================================================
970 {
971  if (listener != nullptr)
972  {
973  if (listeners.isEmpty() && object != nullptr)
974  object->valueTreesWithListeners.add (this);
975 
976  listeners.add (listener);
977  }
978 }
979 
981 {
982  listeners.remove (listener);
983 
984  if (listeners.isEmpty() && object != nullptr)
985  object->valueTreesWithListeners.removeValue (this);
986 }
987 
989 {
990  if (object != nullptr)
991  object->sendPropertyChangeMessage (property);
992 }
993 
994 //==============================================================================
996 {
997  return object != nullptr ? object->createXml() : nullptr;
998 }
999 
1001 {
1002  if (! xml.isTextElement())
1003  {
1004  ValueTree v (xml.getTagName());
1005  v.object->properties.setFromXmlAttributes (xml);
1006 
1007  forEachXmlChildElement (xml, e)
1008  v.appendChild (fromXml (*e), nullptr);
1009 
1010  return v;
1011  }
1012 
1013  // ValueTrees don't have any equivalent to XML text elements!
1014  jassertfalse;
1015  return {};
1016 }
1017 
1019 {
1020  std::unique_ptr<XmlElement> xml (createXml());
1021 
1022  if (xml != nullptr)
1023  return xml->createDocument ({});
1024 
1025  return {};
1026 }
1027 
1028 //==============================================================================
1030 {
1031  SharedObject::writeObjectToStream (output, object.get());
1032 }
1033 
1035 {
1036  auto type = input.readString();
1037 
1038  if (type.isEmpty())
1039  return {};
1040 
1041  ValueTree v (type);
1042 
1043  auto numProps = input.readCompressedInt();
1044 
1045  if (numProps < 0)
1046  {
1047  jassertfalse; // trying to read corrupted data!
1048  return v;
1049  }
1050 
1051  for (int i = 0; i < numProps; ++i)
1052  {
1053  auto name = input.readString();
1054 
1055  if (name.isNotEmpty())
1056  v.object->properties.set (name, var::readFromStream (input));
1057  else
1058  jassertfalse; // trying to read corrupted data!
1059  }
1060 
1061  auto numChildren = input.readCompressedInt();
1062  v.object->children.ensureStorageAllocated (numChildren);
1063 
1064  for (int i = 0; i < numChildren; ++i)
1065  {
1066  auto child = readFromStream (input);
1067 
1068  if (! child.isValid())
1069  return v;
1070 
1071  v.object->children.add (child.object);
1072  child.object->parent = v.object.get();
1073  }
1074 
1075  return v;
1076 }
1077 
1078 ValueTree ValueTree::readFromData (const void* data, size_t numBytes)
1079 {
1080  MemoryInputStream in (data, numBytes, false);
1081  return readFromStream (in);
1082 }
1083 
1084 ValueTree ValueTree::readFromGZIPData (const void* data, size_t numBytes)
1085 {
1086  MemoryInputStream in (data, numBytes, false);
1087  GZIPDecompressorInputStream gzipStream (in);
1088  return readFromStream (gzipStream);
1089 }
1090 
1092 
1093 //==============================================================================
1094 #if JUCE_UNIT_TESTS
1095 
1096 class ValueTreeTests : public UnitTest
1097 {
1098 public:
1099  ValueTreeTests() : UnitTest ("ValueTrees", "Values") {}
1100 
1101  static String createRandomIdentifier (Random& r)
1102  {
1103  char buffer[50] = { 0 };
1104  const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-:";
1105 
1106  for (int i = 1 + r.nextInt (numElementsInArray (buffer) - 2); --i >= 0;)
1107  buffer[i] = chars[r.nextInt (sizeof (chars) - 1)];
1108 
1109  String result (buffer);
1110 
1111  if (! XmlElement::isValidXmlName (result))
1112  result = createRandomIdentifier (r);
1113 
1114  return result;
1115  }
1116 
1117  static String createRandomWideCharString (Random& r)
1118  {
1119  juce_wchar buffer[50] = { 0 };
1120 
1121  for (int i = r.nextInt (numElementsInArray (buffer) - 1); --i >= 0;)
1122  {
1123  if (r.nextBool())
1124  {
1125  do
1126  {
1127  buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
1128  }
1129  while (! CharPointer_UTF16::canRepresent (buffer[i]));
1130  }
1131  else
1132  buffer[i] = (juce_wchar) (1 + r.nextInt (0x7e));
1133  }
1134 
1135  return CharPointer_UTF32 (buffer);
1136  }
1137 
1138  static ValueTree createRandomTree (UndoManager* undoManager, int depth, Random& r)
1139  {
1140  ValueTree v (createRandomIdentifier (r));
1141 
1142  for (int i = r.nextInt (10); --i >= 0;)
1143  {
1144  switch (r.nextInt (5))
1145  {
1146  case 0: v.setProperty (createRandomIdentifier (r), createRandomWideCharString (r), undoManager); break;
1147  case 1: v.setProperty (createRandomIdentifier (r), r.nextInt(), undoManager); break;
1148  case 2: if (depth < 5) v.addChild (createRandomTree (undoManager, depth + 1, r), r.nextInt (v.getNumChildren() + 1), undoManager); break;
1149  case 3: v.setProperty (createRandomIdentifier (r), r.nextBool(), undoManager); break;
1150  case 4: v.setProperty (createRandomIdentifier (r), r.nextDouble(), undoManager); break;
1151  default: break;
1152  }
1153  }
1154 
1155  return v;
1156  }
1157 
1158  void runTest() override
1159  {
1160  {
1161  beginTest ("ValueTree");
1162 
1163  auto r = getRandom();
1164 
1165  for (int i = 10; --i >= 0;)
1166  {
1167  MemoryOutputStream mo;
1168  auto v1 = createRandomTree (nullptr, 0, r);
1169  v1.writeToStream (mo);
1170 
1171  MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
1172  auto v2 = ValueTree::readFromStream (mi);
1173  expect (v1.isEquivalentTo (v2));
1174 
1175  MemoryOutputStream zipped;
1176  {
1177  GZIPCompressorOutputStream zippedOut (zipped);
1178  v1.writeToStream (zippedOut);
1179  }
1180  expect (v1.isEquivalentTo (ValueTree::readFromGZIPData (zipped.getData(), zipped.getDataSize())));
1181 
1182  std::unique_ptr<XmlElement> xml1 (v1.createXml());
1183  std::unique_ptr<XmlElement> xml2 (v2.createCopy().createXml());
1184  expect (xml1->isEquivalentTo (xml2.get(), false));
1185 
1186  auto v4 = v2.createCopy();
1187  expect (v1.isEquivalentTo (v4));
1188  }
1189  }
1190 
1191  {
1192  beginTest ("Float formatting");
1193 
1194  ValueTree testVT ("Test");
1195  Identifier number ("number");
1196 
1197  std::map<double, String> tests;
1198  tests[1] = "1.0";
1199  tests[1.1] = "1.1";
1200  tests[1.01] = "1.01";
1201  tests[0.76378] = "0.76378";
1202  tests[-10] = "-10.0";
1203  tests[10.01] = "10.01";
1204  tests[0.0123] = "0.0123";
1205  tests[-3.7e-27] = "-3.7e-27";
1206  tests[1e+40] = "1.0e40";
1207  tests[-12345678901234567.0] = "-1.234567890123457e16";
1208  tests[192000] = "192000.0";
1209  tests[1234567] = "1.234567e6";
1210  tests[0.00006] = "0.00006";
1211  tests[0.000006] = "6.0e-6";
1212 
1213  for (auto& test : tests)
1214  {
1215  testVT.setProperty (number, test.first, nullptr);
1216  auto lines = StringArray::fromLines (testVT.toXmlString());
1217  lines.removeEmptyStrings();
1218  auto numLines = lines.size();
1219  expect (numLines > 1);
1220  expectEquals (lines[numLines - 1], "<Test number=\"" + test.second + "\"/>");
1221  }
1222  }
1223  }
1224 };
1225 
1226 static ValueTreeTests valueTreeTests;
1227 
1228 #endif
1229 
1230 } // namespace juce
juce::ValueTree::Listener::valueTreeParentChanged
virtual void valueTreeParentChanged(ValueTree &treeWhoseParentHasChanged)=0
This method is called when a tree has been added or removed from a parent.
juce::ValueTree
A powerful tree structure that can be used to hold free-form data, and which can handle its own undo ...
Definition: juce_ValueTree.h:76
juce::ValueTree::createCopy
ValueTree createCopy() const
Returns a deep copy of this tree and all its sub-trees.
Definition: juce_ValueTree.cpp:663
juce::ValueTree::getNumProperties
int getNumProperties() const noexcept
Returns the total number of properties that the tree contains.
Definition: juce_ValueTree.cpp:792
juce::ValueTree::SharedObject::AddOrRemoveChildAction
Definition: juce_ValueTree.cpp:476
juce::Value::ValueSource
Used internally by the Value class as the base class for its shared value objects.
Definition: juce_Value.h:182
juce::ValueTree::addListener
void addListener(Listener *listener)
Adds a listener to receive callbacks when this tree is changed in some way.
Definition: juce_ValueTree.cpp:969
juce::ValueTree::readFromGZIPData
static ValueTree readFromGZIPData(const void *data, size_t numBytes)
Reloads a tree from a data block that was written with writeToStream() and then zipped using GZIPComp...
Definition: juce_ValueTree.cpp:1084
juce::ValueTree::getChild
ValueTree getChild(int index) const
Returns one of this tree's sub-trees.
Definition: juce_ValueTree.cpp:857
juce::ValueTree::getOrCreateChildWithName
ValueTree getOrCreateChildWithName(const Identifier &type, UndoManager *undoManager)
Returns the first sub-tree with the specified type name, creating and adding a child with this name i...
Definition: juce_ValueTree.cpp:893
juce::ValueTree::SharedObject::MoveChildAction::undo
bool undo() override
Overridden by a subclass to undo the action.
Definition: juce_ValueTree.cpp:541
juce::NamedValueSet::contains
bool contains(const Identifier &name) const noexcept
Returns true if the set contains an item with the specified name.
Definition: juce_NamedValueSet.cpp:189
juce::NamedValueSet::getValueAt
const var & getValueAt(int index) const noexcept
Returns the value of the item at a given index.
Definition: juce_NamedValueSet.cpp:230
juce::UndoableAction
Used by the UndoManager class to store an action which can be done and undone.
Definition: juce_UndoableAction.h:43
juce::Value
Represents a shared variant value.
Definition: juce_Value.h:55
juce::ValueTree::copyPropertiesAndChildrenFrom
void copyPropertiesAndChildrenFrom(const ValueTree &source, UndoManager *undoManager)
Replaces all children and properties of this object with copies of those from the source object.
Definition: juce_ValueTree.cpp:681
juce::ReferenceCountedObject
A base class which provides methods for reference-counting.
Definition: juce_ReferenceCountedObject.h:64
juce::ValueTree::toXmlString
String toXmlString() const
This returns a string containing an XML representation of the tree.
Definition: juce_ValueTree.cpp:1018
juce::OwnedArray::size
int size() const noexcept
Returns the number of items currently in the array.
Definition: juce_OwnedArray.h:134
juce::ValueTree::removeAllChildren
void removeAllChildren(UndoManager *undoManager)
Removes all child-trees.
Definition: juce_ValueTree.cpp:938
juce::ValueTree::~ValueTree
~ValueTree()
Destructor.
Definition: juce_ValueTree.cpp:640
juce::ValueTree::SharedObject::SetPropertyAction::perform
bool perform() override
Overridden by a subclass to perform the action.
Definition: juce_ValueTree.cpp:424
juce::ValueTree::hasProperty
bool hasProperty(const Identifier &name) const noexcept
Returns true if the tree contains a named property.
Definition: juce_ValueTree.cpp:775
juce::ValueTree::removeProperty
void removeProperty(const Identifier &name, UndoManager *undoManager)
Removes a property from the tree.
Definition: juce_ValueTree.cpp:780
juce::Value::ValueSource::sendChangeMessage
void sendChangeMessage(bool dispatchSynchronously)
Delivers a change message to all the listeners that are registered with this value.
Definition: juce_Value.cpp:44
juce::NamedValueSet::getVarPointer
var * getVarPointer(const Identifier &name) const noexcept
Returns a pointer to the var that holds a named value, or null if there is no value with this name.
Definition: juce_NamedValueSet.cpp:150
juce::ValueTree::SharedObject::MoveChildAction
Definition: juce_ValueTree.cpp:528
juce::ValueTree::Listener::valueTreeChildAdded
virtual void valueTreeChildAdded(ValueTree &parentTree, ValueTree &childWhichHasBeenAdded)=0
This method is called when a child sub-tree is added.
juce::OwnedArray
An array designed for holding objects.
Definition: juce_OwnedArray.h:54
juce::NamedValueSet::getName
Identifier getName(int index) const noexcept
Returns the name of the value at a given index.
Definition: juce_NamedValueSet.cpp:221
juce::NamedValueSet
Holds a set of named var objects.
Definition: juce_NamedValueSet.h:38
juce::Random::nextInt
int nextInt() noexcept
Returns the next random 32 bit integer.
Definition: juce_Random.cpp:78
juce::InputStream
The base class for streams that read data.
Definition: juce_InputStream.h:40
juce::ValueTree::writeToStream
void writeToStream(OutputStream &output) const
Stores this tree (and all its children) in a binary format.
Definition: juce_ValueTree.cpp:1029
juce::ValueTree::createXml
XmlElement * createXml() const
Creates an XmlElement that holds a complete image of this tree and all its children.
Definition: juce_ValueTree.cpp:995
juce::ValueTree::setPropertyExcludingListener
ValueTree & setPropertyExcludingListener(Listener *listenerToExclude, const Identifier &name, const var &newValue, UndoManager *undoManager)
Changes a named property of the tree, but will not notify a specified listener of the change.
Definition: juce_ValueTree.cpp:763
juce::ValueTree::SharedObject::SetPropertyAction::createCoalescedAction
UndoableAction * createCoalescedAction(UndoableAction *nextAction) override
Allows multiple actions to be coalesced into a single action object, to reduce storage space.
Definition: juce_ValueTree.cpp:451
juce::NamedValueSet::remove
bool remove(const Identifier &name)
Removes a value from the set.
Definition: juce_NamedValueSet.cpp:205
juce::var::readFromStream
static var readFromStream(InputStream &input)
Reads back a stored binary representation of a value.
Definition: juce_Variant.cpp:772
juce::UndoManager
Manages a list of undo/redo commands.
Definition: juce_UndoManager.h:56
juce::SortedSet
Holds a set of unique primitive objects, such as ints or doubles.
Definition: juce_SortedSet.h:60
juce::ValueTree::getPropertyPointer
const var * getPropertyPointer(const Identifier &name) const noexcept
Returns a pointer to the value of a named property, or nullptr if the property doesn't exist.
Definition: juce_ValueTree.cpp:752
juce::ValueTree::SharedObject::MoveChildAction::perform
bool perform() override
Overridden by a subclass to perform the action.
Definition: juce_ValueTree.cpp:535
juce::ValueTree::sendPropertyChangeMessage
void sendPropertyChangeMessage(const Identifier &property)
Causes a property-change callback to be triggered for the specified property, calling any listeners t...
Definition: juce_ValueTree.cpp:988
juce::ValueTree::removeListener
void removeListener(Listener *listener)
Removes a listener that was previously added with addListener().
Definition: juce_ValueTree.cpp:980
juce::ValueTree::SharedObject::AddOrRemoveChildAction::perform
bool perform() override
Overridden by a subclass to perform the action.
Definition: juce_ValueTree.cpp:487
juce::ValueTree::addChild
void addChild(const ValueTree &child, int index, UndoManager *undoManager)
Adds a child to this tree.
Definition: juce_ValueTree.cpp:913
juce::ValueTree::SharedObject::SetPropertyAction::undo
bool undo() override
Overridden by a subclass to undo the action.
Definition: juce_ValueTree.cpp:436
juce::InputStream::readCompressedInt
virtual int readCompressedInt()
Reads an encoded 32-bit number from the stream using a space-saving compressed format.
Definition: juce_InputStream.cpp:88
juce::OutputStream::writeString
virtual bool writeString(const String &text)
Stores a string in the stream in a binary format.
Definition: juce_OutputStream.cpp:172
juce::ValueTree::operator==
bool operator==(const ValueTree &) const noexcept
Returns true if both this and the other tree refer to the same underlying structure.
Definition: juce_ValueTree.cpp:646
juce::ValueTree::SharedObject::SetPropertyAction::getSizeInUnits
int getSizeInUnits() override
Returns a value to indicate how much memory this object takes up.
Definition: juce_ValueTree.cpp:446
juce::ValueTree::getRoot
ValueTree getRoot() const noexcept
Recursively finds the highest-level parent tree that contains this one.
Definition: juce_ValueTree.cpp:712
juce::ValueTree::SharedObject::AddOrRemoveChildAction::undo
bool undo() override
Overridden by a subclass to undo the action.
Definition: juce_ValueTree.cpp:497
juce::Identifier::toString
const String & toString() const noexcept
Returns this identifier as a string.
Definition: juce_Identifier.h:106
juce::OutputStream::writeCompressedInt
virtual bool writeCompressedInt(int value)
Writes a condensed binary encoding of a 32-bit integer.
Definition: juce_OutputStream.cpp:110
juce::XmlElement
Used to build a tree of elements representing an XML document.
Definition: juce_XmlElement.h:141
juce::ValueTree::appendChild
void appendChild(const ValueTree &child, UndoManager *undoManager)
Appends a new child sub-tree to this tree.
Definition: juce_ValueTree.cpp:921
juce::ValueTree::getSibling
ValueTree getSibling(int delta) const noexcept
Returns one of this tree's siblings in its parent's child list.
Definition: juce_ValueTree.cpp:720
juce::CharPointer_UTF16::canRepresent
static bool canRepresent(juce_wchar character) noexcept
Returns true if the given unicode character can be represented in this encoding.
Definition: juce_CharPointer_UTF16.h:434
juce::ValueTree::setProperty
ValueTree & setProperty(const Identifier &name, const var &newValue, UndoManager *undoManager)
Changes a named property of the tree.
Definition: juce_ValueTree.cpp:758
juce::OutputStream
The base class for streams that write data to some kind of destination.
Definition: juce_OutputStream.h:41
juce::Random
A random number generator.
Definition: juce_Random.h:38
juce::ValueTree::SharedObject::MoveChildAction::createCoalescedAction
UndoableAction * createCoalescedAction(UndoableAction *nextAction) override
Allows multiple actions to be coalesced into a single action object, to reduce storage space.
Definition: juce_ValueTree.cpp:552
juce::NamedValueSet::set
bool set(const Identifier &name, const var &newValue)
Changes or adds a named value.
Definition: juce_NamedValueSet.cpp:174
juce::ValueTree::Listener::valueTreeChildOrderChanged
virtual void valueTreeChildOrderChanged(ValueTree &parentTreeWhoseChildrenHaveMoved, int oldIndex, int newIndex)=0
This method is called when a tree's children have been re-shuffled.
juce::ValueTree::hasType
bool hasType(const Identifier &typeName) const noexcept
Returns true if the tree has this type.
Definition: juce_ValueTree.cpp:693
juce::ValueTree::Listener::valueTreeRedirected
virtual void valueTreeRedirected(ValueTree &treeWhichHasBeenChanged)
This method is called when a tree is made to point to a different internal shared object.
Definition: juce_ValueTree.cpp:1091
juce::ReferenceCountedObject::ReferenceCountedObject
ReferenceCountedObject()=default
Creates the reference-counted object (with an initial ref count of zero).
juce::var
A variant class, that can be used to hold a range of primitive values.
Definition: juce_Variant.h:45
juce::StringArray::fromLines
static StringArray fromLines(StringRef stringToBreakUp)
Returns an array containing the lines in a given string.
Definition: juce_StringArray.cpp:402
juce::ValueTree::begin
Iterator begin() const noexcept
Returns a start iterator for the children in this tree.
Definition: juce_ValueTree.cpp:885
juce::ValueTree::getType
Identifier getType() const noexcept
Returns the type of this tree.
Definition: juce_ValueTree.cpp:698
juce::ValueTree::getChildWithName
ValueTree getChildWithName(const Identifier &type) const
Returns the first sub-tree with the specified type name.
Definition: juce_ValueTree.cpp:888
juce::ValueTree::removeAllProperties
void removeAllProperties(UndoManager *undoManager)
Removes all properties from the tree.
Definition: juce_ValueTree.cpp:786
juce::XmlElement::getTagName
const String & getTagName() const noexcept
Returns this element's tag type name.
Definition: juce_XmlElement.h:265
juce::var::writeToStream
void writeToStream(OutputStream &output) const
Writes a binary representation of this value to a stream.
Definition: juce_Variant.cpp:767
juce::ValueTree::SharedObject::SetPropertyAction
Definition: juce_ValueTree.cpp:412
juce::NamedValueSet::copyToXmlAttributes
void copyToXmlAttributes(XmlElement &xml) const
Sets attributes in an XML element corresponding to each of this object's properties.
Definition: juce_NamedValueSet.cpp:268
juce::ReferenceCountedArray
Holds a list of objects derived from ReferenceCountedObject, or which implement basic reference-count...
Definition: juce_ReferenceCountedArray.h:54
juce::ValueTree::readFromStream
static ValueTree readFromStream(InputStream &input)
Reloads a tree from a stream that was written with writeToStream().
Definition: juce_ValueTree.cpp:1034
juce::OwnedArray::getUnchecked
ObjectClass * getUnchecked(const int index) const noexcept
Returns a pointer to the object at this index in the array, without checking whether the index is in-...
Definition: juce_OwnedArray.h:164
juce::ValueTree::operator[]
const var & operator[](const Identifier &name) const noexcept
Returns the value of a named property.
Definition: juce_ValueTree.cpp:736
juce::ValueTree::getParent
ValueTree getParent() const noexcept
Returns the parent tree that contains this one.
Definition: juce_ValueTree.cpp:703
juce::MemoryInputStream
Allows a block of data to be accessed as a stream.
Definition: juce_MemoryInputStream.h:39
juce::ValueTree::getReferenceCount
int getReferenceCount() const noexcept
Returns the total number of references to the shared underlying data structure that this ValueTree is...
Definition: juce_ValueTree.cpp:803
juce::XmlElement::isValidXmlName
static bool isValidXmlName(StringRef possibleName) noexcept
Checks if a given string is a valid XML name.
Definition: juce_XmlElement.cpp:895
juce::ValueTree::SharedObject
Definition: juce_ValueTree.cpp:30
juce::Identifier
Represents a string identifier, designed for accessing properties by name.
Definition: juce_Identifier.h:42
juce::ReferenceCountedObjectPtr
A smart-pointer class which points to a reference-counted object.
Definition: juce_ReferenceCountedObject.h:245
juce::InputStream::readString
virtual String readString()
Reads a zero-terminated UTF-8 string from the stream.
Definition: juce_InputStream.cpp:162
juce::NamedValueSet::size
int size() const noexcept
Returns the total number of values that the set contains.
Definition: juce_NamedValueSet.cpp:125
juce::ValueTree::ValueTree
ValueTree() noexcept
Creates an empty, invalid ValueTree.
Definition: juce_ValueTree.cpp:579
juce::XmlElement::isTextElement
bool isTextElement() const noexcept
Returns true if this element is a section of text.
Definition: juce_XmlElement.cpp:840
juce::ValueTree::getPropertyName
Identifier getPropertyName(int index) const noexcept
Returns the identifier of the property with a given index.
Definition: juce_ValueTree.cpp:797
juce::ValueTree::SharedObject::AddOrRemoveChildAction::getSizeInUnits
int getSizeInUnits() override
Returns a value to indicate how much memory this object takes up.
Definition: juce_ValueTree.cpp:514
juce::UnitTest
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
juce::ValueTree::SharedObject::MoveChildAction::getSizeInUnits
int getSizeInUnits() override
Returns a value to indicate how much memory this object takes up.
Definition: juce_ValueTree.cpp:547
juce::ValueTree::indexOf
int indexOf(const ValueTree &child) const noexcept
Returns the index of a child item in this parent.
Definition: juce_ValueTree.cpp:908
juce::ValueTree::moveChild
void moveChild(int currentIndex, int newIndex, UndoManager *undoManager)
Moves one of the sub-trees to a different index.
Definition: juce_ValueTree.cpp:944
juce::ValueTreePropertyValueSource::getValue
var getValue() const override
Returns the current value of this object.
Definition: juce_ValueTree.cpp:823
juce::ValueTree::copyPropertiesFrom
void copyPropertiesFrom(const ValueTree &source, UndoManager *undoManager)
Overwrites all the properties in this tree with the properties of the source tree.
Definition: juce_ValueTree.cpp:671
juce::String::isNotEmpty
bool isNotEmpty() const noexcept
Returns true if the string contains at least one character.
Definition: juce_String.h:306
juce::ValueTree::operator!=
bool operator!=(const ValueTree &) const noexcept
Returns true if this and the other tree refer to different underlying structures.
Definition: juce_ValueTree.cpp:651
juce::ValueTree::getNumChildren
int getNumChildren() const noexcept
Returns the number of child trees inside this one.
Definition: juce_ValueTree.cpp:852
juce::ValueTree::fromXml
static ValueTree fromXml(const XmlElement &xml)
Tries to recreate a tree from its XML representation.
Definition: juce_ValueTree.cpp:1000
juce::String
The JUCE String class!
Definition: juce_String.h:42
juce::GZIPDecompressorInputStream
This stream will decompress a source-stream using zlib.
Definition: juce_GZIPDecompressorInputStream.h:42
juce::ValueTree::isAChildOf
bool isAChildOf(const ValueTree &possibleParent) const noexcept
Returns true if this tree is a sub-tree (at any depth) of the given parent.
Definition: juce_ValueTree.cpp:903
juce::ValueTree::Iterator
Iterator for a ValueTree.
Definition: juce_ValueTree.h:405
juce::UndoManager::perform
bool perform(UndoableAction *action)
Performs an action and adds it to the undo history list.
Definition: juce_UndoManager.cpp:112
juce::ValueTree::getChildWithProperty
ValueTree getChildWithProperty(const Identifier &propertyName, const var &propertyValue) const
Looks for the first sub-tree that has the specified property value.
Definition: juce_ValueTree.cpp:898
juce::ValueTree::end
Iterator end() const noexcept
Returns an end iterator for the children in this tree.
Definition: juce_ValueTree.cpp:886
juce::ValueTree::Listener::valueTreePropertyChanged
virtual void valueTreePropertyChanged(ValueTree &treeWhosePropertyHasChanged, const Identifier &property)=0
This method is called when a property of this tree (or of one of its sub-trees) is changed.
juce::OwnedArray::add
ObjectClass * add(ObjectClass *newObject) noexcept
Appends a new object to the end of the array.
Definition: juce_OwnedArray.h:274
juce::ValueTree::operator=
ValueTree & operator=(const ValueTree &)
Changes this object to be a reference to the given tree.
Definition: juce_ValueTree.cpp:608
juce::ValueTree::Listener
Listener class for events that happen to a ValueTree.
Definition: juce_ValueTree.h:478
juce::ValueTreePropertyValueSource
Definition: juce_ValueTree.cpp:809
juce::ValueTree::getPropertyAsValue
Value getPropertyAsValue(const Identifier &name, UndoManager *undoManager, bool shouldUpdateSynchronously=false)
Returns a Value object that can be used to control and respond to one of the tree's properties.
Definition: juce_ValueTree.cpp:846
juce::ValueTreePropertyValueSource::setValue
void setValue(const var &newValue) override
Changes the current value.
Definition: juce_ValueTree.cpp:824
juce::ValueTree::Listener::valueTreeChildRemoved
virtual void valueTreeChildRemoved(ValueTree &parentTree, ValueTree &childWhichHasBeenRemoved, int indexFromWhichChildWasRemoved)=0
This method is called when a child sub-tree is removed.
juce::ValueTree::getProperty
const var & getProperty(const Identifier &name) const noexcept
Returns the value of a named property.
Definition: juce_ValueTree.cpp:741
juce::ValueTree::isEquivalentTo
bool isEquivalentTo(const ValueTree &) const
Performs a deep comparison between the properties and children of two trees.
Definition: juce_ValueTree.cpp:656
juce::ValueTree::removeChild
void removeChild(const ValueTree &child, UndoManager *undoManager)
Removes the specified child from this tree's child-list.
Definition: juce_ValueTree.cpp:932
juce::ValueTree::readFromData
static ValueTree readFromData(const void *data, size_t numBytes)
Reloads a tree from a data block that was written with writeToStream().
Definition: juce_ValueTree.cpp:1078