]> git.mxchange.org Git - simgear.git/blobdiff - simgear/misc/props.cxx
MSVC++ bug work-around from Frederic Bouvier.
[simgear.git] / simgear / misc / props.cxx
index fd1fb6c3fb78e92cec917080632c34d3338f1de5..6b8ce67753b4e25034d2a74d16acdbd3a8ba608e 100644 (file)
@@ -17,7 +17,9 @@
 #include <iostream>
 using std::cerr;
 using std::endl;
+using std::find;
 using std::sort;
+using std::vector;
 
 #else
 
@@ -25,6 +27,15 @@ using std::sort;
 #include <simgear/debug/logstream.hxx>
 
 SG_USING_STD(sort);
+SG_USING_STD(find);
+SG_USING_STD(vector);
+
+#ifdef _MSC_VER
+// MSVC is buggy, and needs something strange here
+SG_USING_STD(vector<SGPropertyNode_ptr>);
+SG_USING_STD(vector<SGPropertyChangeListener *>);
+SG_USING_STD(vector<SGPropertyNode *>);
+#endif
 
 #endif
 
@@ -360,9 +371,15 @@ inline bool
 SGPropertyNode::set_bool (bool val)
 {
   if (_tied) {
-    return _value.bool_val->setValue(val);
+    if (_value.bool_val->setValue(val)) {
+      fireValueChanged();
+      return true;
+    } else {
+      return false;
+    }
   } else {
     _local_val.bool_val = val;
+    fireValueChanged();
     return true;
   }
 }
@@ -371,9 +388,15 @@ inline bool
 SGPropertyNode::set_int (int val)
 {
   if (_tied) {
-    return _value.int_val->setValue(val);
+    if (_value.int_val->setValue(val)) {
+      fireValueChanged();
+      return true;
+    } else {
+      return false;
+    }
   } else {
     _local_val.int_val = val;
+    fireValueChanged();
     return true;
   }
 }
@@ -382,9 +405,15 @@ inline bool
 SGPropertyNode::set_long (long val)
 {
   if (_tied) {
-    return _value.long_val->setValue(val);
+    if (_value.long_val->setValue(val)) {
+      fireValueChanged();
+      return true;
+    } else {
+      return false;
+    }
   } else {
     _local_val.long_val = val;
+    fireValueChanged();
     return true;
   }
 }
@@ -393,9 +422,15 @@ inline bool
 SGPropertyNode::set_float (float val)
 {
   if (_tied) {
-    return _value.float_val->setValue(val);
+    if (_value.float_val->setValue(val)) {
+      fireValueChanged();
+      return true;
+    } else {
+      return false;
+    }
   } else {
     _local_val.float_val = val;
+    fireValueChanged();
     return true;
   }
 }
@@ -404,9 +439,15 @@ inline bool
 SGPropertyNode::set_double (double val)
 {
   if (_tied) {
-    return _value.double_val->setValue(val);
+    if (_value.double_val->setValue(val)) {
+      fireValueChanged();
+      return true;
+    } else {
+      return false;
+    }
   } else {
     _local_val.double_val = val;
+    fireValueChanged();
     return true;
   }
 }
@@ -415,10 +456,16 @@ inline bool
 SGPropertyNode::set_string (const char * val)
 {
   if (_tied) {
-    return _value.string_val->setValue(val);
+    if (_value.string_val->setValue(val)) {
+      fireValueChanged();
+      return true;
+    } else {
+      return false;
+    }
   } else {
     delete [] _local_val.string_val;
     _local_val.string_val = copy_string(val);
+    fireValueChanged();
     return true;
   }
 }
@@ -592,7 +639,8 @@ SGPropertyNode::SGPropertyNode ()
     _type(NONE),
     _tied(false),
     _attr(READ|WRITE),
-    _count(0)
+    _count(0),
+    _listeners(0)
 {
   _local_val.string_val = 0;
 }
@@ -608,7 +656,8 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node)
     _type(node._type),
     _tied(node._tied),
     _attr(node._attr),
-    _count(0)
+    _count(0),
+    _listeners(0)              // CHECK!!
 {
   _name = copy_string(node._name);
   _local_val.string_val = 0;
@@ -690,7 +739,8 @@ SGPropertyNode::SGPropertyNode (const char * name,
     _type(NONE),
     _tied(false),
     _attr(READ|WRITE),
-    _count(0)
+    _count(0),
+    _listeners(0)
 {
   _name = copy_string(name);
   _local_val.string_val = 0;
@@ -705,6 +755,7 @@ SGPropertyNode::~SGPropertyNode ()
   delete [] _name;
   delete _path_cache;
   clear_value();
+  delete _listeners;
 }
 
 
@@ -803,7 +854,7 @@ SGPropertyNode::getChild (const char * name, int index, bool create)
     SGPropertyNode_ptr node;
     pos = find_child(name, index, _removedChildren);
     if (pos >= 0) {
-      std::vector<SGPropertyNode_ptr>::iterator it = _removedChildren.begin();
+      vector<SGPropertyNode_ptr>::iterator it = _removedChildren.begin();
       it += pos;
       node = _removedChildren[pos];
       _removedChildren.erase(it);
@@ -812,7 +863,8 @@ SGPropertyNode::getChild (const char * name, int index, bool create)
       node = new SGPropertyNode(name, index, this);
     }
     _children.push_back(node);
-    return _children[_children.size()-1];
+    fireChildAdded(node);
+    return node;
   } else {
     return 0;
   }
@@ -860,7 +912,7 @@ SGPropertyNode::removeChild (const char * name, int index, bool keep)
   SGPropertyNode_ptr ret;
   int pos = find_child(name, index, _children);
   if (pos >= 0) {
-    std::vector<SGPropertyNode_ptr>::iterator it = _children.begin();
+    vector<SGPropertyNode_ptr>::iterator it = _children.begin();
     it += pos;
     SGPropertyNode_ptr node = _children[pos];
     _children.erase(it);
@@ -869,6 +921,7 @@ SGPropertyNode::removeChild (const char * name, int index, bool keep)
     }
     node->setAttribute(REMOVED, true);
     ret = node;
+    fireChildRemoved(node);
   }
   return ret;
 }
@@ -888,7 +941,8 @@ SGPropertyNode::getPath (bool simplify) const
     sprintf(buffer, "[%d]", _index);
     path += buffer;
   }
-  return path.c_str();
+  strncpy(_buffer, path.c_str(), MAX_STRING_LEN);
+  return _buffer;
 }
 
 SGPropertyNode::Type
@@ -1939,6 +1993,87 @@ SGPropertyNode::untie (const char * relative_path)
   return (node == 0 ? false : node->untie());
 }
 
+void
+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::fireChildRemoved (SGPropertyNode * parent,
+                                 SGPropertyNode * child)
+{
+  if (_listeners != 0) {
+    for (int i = 0; i < _listeners->size(); i++) {
+      (*_listeners)[i]->childRemoved(parent, child);
+    }
+  }
+  if (_parent != 0)
+    _parent->fireChildRemoved(parent, child);
+}
+
 
 \f
 ////////////////////////////////////////////////////////////////////////
@@ -2162,4 +2297,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