Bug in ValueTree::Listener


#1

Left base folder: w:\hugh\apps\stvle
Right base folder: c:\hugh\apps\stvle
--- JuceLibraryCode\modules\juce_data_structures\values\juce_ValueTree.cpp	2013-06-27 13:07:43.000000000 +0100
+++ JuceLibraryCode\modules\juce_data_structures\values\juce_ValueTree.cpp	2013-09-19 03:30:31.000000000 +0100
@@ -56,60 +56,56 @@
             c->sendParentChangeMessage();
         }
     }
 
     void sendPropertyChangeMessage (ValueTree& tree, const Identifier property)
     {
-        for (int i = valueTreesWithListeners.size(); --i >= 0;)
-            if (ValueTree* const v = valueTreesWithListeners[i])
-                v->listeners.call (&ValueTree::Listener::valueTreePropertyChanged, tree, property);
+        for (ValueTree::iterator it = valueTreesWithListeners.begin(); it != valueTreesWithListeners.end(); ++it)
+            it->listeners.call (&ValueTree::Listener::valueTreePropertyChanged, tree, property);
     }
 
     void sendPropertyChangeMessage (const Identifier property)
     {
         ValueTree tree (this);
 
         for (ValueTree::SharedObject* t = this; t != nullptr; t = t->parent)
             t->sendPropertyChangeMessage (tree, property);
     }
 
     void sendChildAddedMessage (ValueTree& tree, ValueTree& child)
     {
-        for (int i = valueTreesWithListeners.size(); --i >= 0;)
-            if (ValueTree* const v = valueTreesWithListeners[i])
-                v->listeners.call (&ValueTree::Listener::valueTreeChildAdded, tree, child);
+        for (ValueTree::iterator it = valueTreesWithListeners.begin(); it != valueTreesWithListeners.end(); ++it)
+            it->listeners.call (&ValueTree::Listener::valueTreeChildAdded, tree, child);
     }
 
     void sendChildAddedMessage (ValueTree child)
     {
         ValueTree tree (this);
 
         for (ValueTree::SharedObject* t = this; t != nullptr; t = t->parent)
             t->sendChildAddedMessage (tree, child);
     }
 
     void sendChildRemovedMessage (ValueTree& tree, ValueTree& child)
     {
-        for (int i = valueTreesWithListeners.size(); --i >= 0;)
-            if (ValueTree* const v = valueTreesWithListeners[i])
-                v->listeners.call (&ValueTree::Listener::valueTreeChildRemoved, tree, child);
+        for (ValueTree::iterator it = valueTreesWithListeners.begin(); it != valueTreesWithListeners.end(); ++it)
+            it->listeners.call (&ValueTree::Listener::valueTreeChildRemoved, tree, child);
     }
 
     void sendChildRemovedMessage (ValueTree child)
     {
         ValueTree tree (this);
 
         for (ValueTree::SharedObject* t = this; t != nullptr; t = t->parent)
             t->sendChildRemovedMessage (tree, child);
     }
 
     void sendChildOrderChangedMessage (ValueTree& tree)
     {
-        for (int i = valueTreesWithListeners.size(); --i >= 0;)
-            if (ValueTree* const v = valueTreesWithListeners[i])
-                v->listeners.call (&ValueTree::Listener::valueTreeChildOrderChanged, tree);
+        for (ValueTree::iterator it = valueTreesWithListeners.begin(); it != valueTreesWithListeners.end(); ++it)
+            it->listeners.call (&ValueTree::Listener::valueTreeChildOrderChanged, tree);
     }
 
     void sendChildOrderChangedMessage()
     {
         ValueTree tree (this);
 
@@ -122,15 +118,14 @@
         ValueTree tree (this);
 
         for (int j = children.size(); --j >= 0;)
             if (SharedObject* const child = children.getObjectPointer (j))
                 child->sendParentChangeMessage();
 
-        for (int i = valueTreesWithListeners.size(); --i >= 0;)
-            if (ValueTree* const v = valueTreesWithListeners[i])
-                v->listeners.call (&ValueTree::Listener::valueTreeParentChanged, tree);
+        for (ValueTree::iterator it = valueTreesWithListeners.begin(); it != valueTreesWithListeners.end(); ++it)
+            it->listeners.call (&ValueTree::Listener::valueTreeParentChanged, tree);
     }
 
     const var& getProperty (const Identifier name) const noexcept
     {
         return properties [name];
     }
@@ -597,13 +592,15 @@
     };
 
     //==============================================================================
     const Identifier type;
     NamedValueSet properties;
     ReferenceCountedArray<SharedObject> children;
-    SortedSet<ValueTree*> valueTreesWithListeners;
+    ValueTree::List valueTreesWithListeners;
+    
+
     SharedObject* parent;
 
 private:
     SharedObject& operator= (const SharedObject&);
     JUCE_LEAK_DETECTOR (SharedObject)
 };
@@ -632,14 +629,13 @@
 }
 
 ValueTree& ValueTree::operator= (const ValueTree& other)
 {
     if (listeners.size() > 0)
     {
-        if (object != nullptr)
-            object->valueTreesWithListeners.removeValue (this);
+        remove();
 
         if (other.object != nullptr)
             other.object->valueTreesWithListeners.add (this);
     }
 
     object = other.object;
@@ -654,14 +650,12 @@
 {
 }
 #endif
 
 ValueTree::~ValueTree()
 {
-    if (listeners.size() > 0 && object != nullptr)
-        object->valueTreesWithListeners.removeValue (this);
 }
 
 bool ValueTree::operator== (const ValueTree& other) const noexcept
 {
     return object == other.object;
 }
@@ -916,13 +910,13 @@
 
 void ValueTree::removeListener (Listener* listener)
 {
     listeners.remove (listener);
 
     if (listeners.size() == 0 && object != nullptr)
-        object->valueTreesWithListeners.removeValue (this);
+        remove();
 }
 
 void ValueTree::sendPropertyChangeMessage (const Identifier property)
 {
     if (object != nullptr)
         object->sendPropertyChangeMessage (property);
--- JuceLibraryCode\modules\juce_data_structures\values\juce_ValueTree.h	2013-07-19 11:54:59.000000000 +0100
+++ JuceLibraryCode\modules\juce_data_structures\values\juce_ValueTree.h	2013-09-19 02:14:59.000000000 +0100
@@ -24,12 +24,13 @@
 
 #ifndef JUCE_VALUETREE_H_INCLUDED
 #define JUCE_VALUETREE_H_INCLUDED
 
 #include "juce_Value.h"
 #include "../undomanager/juce_UndoManager.h"
+#include "dl.h"
 
 
 //==============================================================================
 /**
     A powerful tree structure that can be used to hold free-form data, and which can
     handle its own undo and redo behaviour.
@@ -61,13 +62,13 @@
 
     Listeners can be added to a ValueTree to be told when properies change and when
     nodes are added or removed.
 
     @see var, XmlElement
 */
-class JUCE_API  ValueTree
+class JUCE_API  ValueTree: public DL<ValueTree>
 {
 public:
     //==============================================================================
     /** Creates an empty, invalid ValueTree.
 
         A ValueTree that is created with this constructor can't actually be used for anything,

#2

Damn. That's tricky. Thanks, I'll have to have a hard think about that..