]> git.mxchange.org Git - simgear.git/commitdiff
Significant improvements to the change-listener support. There are
authordavid <david>
Tue, 18 Jun 2002 21:17:42 +0000 (21:17 +0000)
committerdavid <david>
Tue, 18 Jun 2002 21:17:42 +0000 (21:17 +0000)
now three different change events, and the listener base class removes
itself from the parent in the destructor.

simgear/misc/props.cxx
simgear/misc/props.hxx

index be18a0ddfc8c76fed740c95f7d0da4aa3e60723f..bb13712414c91db125634f1e204a369a20129a15 100644 (file)
@@ -17,6 +17,7 @@
 #include <iostream>
 using std::cerr;
 using std::endl;
+using std::find;
 using std::sort;
 
 #else
@@ -361,14 +362,14 @@ SGPropertyNode::set_bool (bool val)
 {
   if (_tied) {
     if (_value.bool_val->setValue(val)) {
-      firePropertyChange();
+      fireValueChanged();
       return true;
     } else {
       return false;
     }
   } else {
     _local_val.bool_val = val;
-    firePropertyChange();
+    fireValueChanged();
     return true;
   }
 }
@@ -378,14 +379,14 @@ SGPropertyNode::set_int (int val)
 {
   if (_tied) {
     if (_value.int_val->setValue(val)) {
-      firePropertyChange();
+      fireValueChanged();
       return true;
     } else {
       return false;
     }
   } else {
     _local_val.int_val = val;
-    firePropertyChange();
+    fireValueChanged();
     return true;
   }
 }
@@ -395,14 +396,14 @@ SGPropertyNode::set_long (long val)
 {
   if (_tied) {
     if (_value.long_val->setValue(val)) {
-      firePropertyChange();
+      fireValueChanged();
       return true;
     } else {
       return false;
     }
   } else {
     _local_val.long_val = val;
-    firePropertyChange();
+    fireValueChanged();
     return true;
   }
 }
@@ -412,14 +413,14 @@ SGPropertyNode::set_float (float val)
 {
   if (_tied) {
     if (_value.float_val->setValue(val)) {
-      firePropertyChange();
+      fireValueChanged();
       return true;
     } else {
       return false;
     }
   } else {
     _local_val.float_val = val;
-    firePropertyChange();
+    fireValueChanged();
     return true;
   }
 }
@@ -429,14 +430,14 @@ SGPropertyNode::set_double (double val)
 {
   if (_tied) {
     if (_value.double_val->setValue(val)) {
-      firePropertyChange();
+      fireValueChanged();
       return true;
     } else {
       return false;
     }
   } else {
     _local_val.double_val = val;
-    firePropertyChange();
+    fireValueChanged();
     return true;
   }
 }
@@ -446,7 +447,7 @@ SGPropertyNode::set_string (const char * val)
 {
   if (_tied) {
     if (_value.string_val->setValue(val)) {
-      firePropertyChange();
+      fireValueChanged();
       return true;
     } else {
       return false;
@@ -454,7 +455,7 @@ SGPropertyNode::set_string (const char * val)
   } else {
     delete [] _local_val.string_val;
     _local_val.string_val = copy_string(val);
-    firePropertyChange();
+    fireValueChanged();
     return true;
   }
 }
@@ -852,9 +853,8 @@ SGPropertyNode::getChild (const char * name, int index, bool create)
       node = new SGPropertyNode(name, index, this);
     }
     _children.push_back(node);
-    if (_parent != 0)
-      _parent->firePropertyChange();
-    return _children[_children.size()-1];
+    fireChildAdded(node);
+    return node;
   } else {
     return 0;
   }
@@ -911,9 +911,8 @@ SGPropertyNode::removeChild (const char * name, int index, bool keep)
     }
     node->setAttribute(REMOVED, true);
     ret = node;
+    fireChildRemoved(node);
   }
-  if (_parent != 0)
-    _parent->firePropertyChange();
   return ret;
 }
 
@@ -1989,18 +1988,79 @@ SGPropertyNode::addChangeListener (SGPropertyChangeListener * listener)
   if (_listeners == 0)
     _listeners = new vector<SGPropertyChangeListener *>;
   _listeners->push_back(listener);
+  listener->register_property(this);
+}
+
+void
+SGPropertyNode::removeChangeListener (SGPropertyChangeListener * listener)
+{
+  vector<SGPropertyChangeListener *>::iterator it =
+    find(_listeners->begin(), _listeners->end(), listener);
+  if (it != _listeners->end()) {
+    _listeners->erase(it);
+    listener->unregister_property(this);
+    if (_listeners->empty()) {
+      vector<SGPropertyChangeListener *> * tmp = _listeners;
+      _listeners = 0;
+      delete tmp;
+    }
+  }
+}
+
+void
+SGPropertyNode::fireValueChanged ()
+{
+  fireValueChanged(this);
+}
+
+void
+SGPropertyNode::fireChildAdded (SGPropertyNode * child)
+{
+  fireChildAdded(this, child);
+}
+
+void
+SGPropertyNode::fireChildRemoved (SGPropertyNode * child)
+{
+  fireChildRemoved(this, child);
+}
+
+void
+SGPropertyNode::fireValueChanged (SGPropertyNode * node)
+{
+  if (_listeners != 0) {
+    for (int i = 0; i < _listeners->size(); i++) {
+      (*_listeners)[i]->valueChanged(node);
+    }
+  }
+  if (_parent != 0)
+    _parent->fireValueChanged(node);
+}
+
+void
+SGPropertyNode::fireChildAdded (SGPropertyNode * parent,
+                               SGPropertyNode * child)
+{
+  if (_listeners != 0) {
+    for (int i = 0; i < _listeners->size(); i++) {
+      (*_listeners)[i]->childAdded(parent, child);
+    }
+  }
+  if (_parent != 0)
+    _parent->fireChildAdded(parent, child);
 }
 
 void
-SGPropertyNode::firePropertyChange (SGPropertyNode * node)
+SGPropertyNode::fireChildRemoved (SGPropertyNode * parent,
+                                 SGPropertyNode * child)
 {
   if (_listeners != 0) {
     for (int i = 0; i < _listeners->size(); i++) {
-      (*_listeners)[i]->propertyChanged(node);
+      (*_listeners)[i]->childRemoved(parent, child);
     }
   }
   if (_parent != 0)
-    _parent->firePropertyChange(node);
+    _parent->fireChildRemoved(parent, child);
 }
 
 
@@ -2226,4 +2286,55 @@ SGPropertyNode_ptr::valid() const
 }
 
 
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of SGPropertyChangeListener.
+////////////////////////////////////////////////////////////////////////
+
+SGPropertyChangeListener::~SGPropertyChangeListener ()
+{
+                               // This will come back and remove
+                               // the current item each time.  Is
+                               // that OK?
+  vector<SGPropertyNode *>::iterator it;
+  for (it = _properties.begin(); it != _properties.end(); it++)
+    (*it)->removeChangeListener(this);
+}
+
+void
+SGPropertyChangeListener::valueChanged (SGPropertyNode * node)
+{
+  // NO-OP
+}
+
+void
+SGPropertyChangeListener::childAdded (SGPropertyNode * node,
+                                     SGPropertyNode * child)
+{
+  // NO-OP
+}
+
+void
+SGPropertyChangeListener::childRemoved (SGPropertyNode * parent,
+                                       SGPropertyNode * child)
+{
+  // NO-OP
+}
+
+void
+SGPropertyChangeListener::register_property (SGPropertyNode * node)
+{
+  _properties.push_back(node);
+}
+
+void
+SGPropertyChangeListener::unregister_property (SGPropertyNode * node)
+{
+  vector<SGPropertyNode *>::iterator it =
+    find(_properties.begin(), _properties.end(), node);
+  if (it != _properties.end())
+    _properties.erase(it);
+}
+
+
 // end of props.cxx
index a077faca89b16a6d36be4726fe0df6375425cf87..b4a429974c5b5ea485a10d4ed47b2f474949ccb9 100644 (file)
@@ -529,9 +529,18 @@ private:
 class SGPropertyChangeListener
 {
 public:
+  virtual ~SGPropertyChangeListener ();
+  virtual void valueChanged (SGPropertyNode * node);
+  virtual void childAdded (SGPropertyNode * parent, SGPropertyNode * child);
+  virtual void childRemoved (SGPropertyNode * parent, SGPropertyNode * child);
 
-  virtual void propertyChanged (SGPropertyNode * node) = 0;
+protected:
+  friend class SGPropertyNode;
+  virtual void register_property (SGPropertyNode * node);
+  virtual void unregister_property (SGPropertyNode * node);
 
+private:
+  vector<SGPropertyNode *> _properties;
 };
 
 
@@ -1127,22 +1136,34 @@ public:
 
 
   /**
-   * Fire a property change to all listeners.
+   * Remove a change listener from the property.
    */
-  void firePropertyChange ()
-  {
-    firePropertyChange(this);
-  }
+  void removeChangeListener (SGPropertyChangeListener * listener);
 
 
-protected:
+  /**
+   * Fire a value change event to all listeners.
+   */
+  void fireValueChanged ();
 
 
   /**
-   * Fire a property change with an explicit target node.
+   * Fire a child-added event to all listeners.
    */
-  void firePropertyChange (SGPropertyNode * node);
+  void fireChildAdded (SGPropertyNode * child);
+
+
+  /**
+   * Fire a child-removed event to all listeners.
+   */
+  void fireChildRemoved (SGPropertyNode * child);
+
+
+protected:
 
+  void fireValueChanged (SGPropertyNode * node);
+  void fireChildAdded (SGPropertyNode * parent, SGPropertyNode * child);
+  void fireChildRemoved (SGPropertyNode * parent, SGPropertyNode * child);
 
   /**
    * Protected constructor for making new nodes on demand.