From: david Date: Tue, 18 Jun 2002 21:17:42 +0000 (+0000) Subject: Significant improvements to the change-listener support. There are X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=0833a1168615814690ab936fa2c7f8f02b63fd16;p=simgear.git Significant improvements to the change-listener support. There are now three different change events, and the listener base class removes itself from the parent in the destructor. --- diff --git a/simgear/misc/props.cxx b/simgear/misc/props.cxx index be18a0dd..bb137124 100644 --- a/simgear/misc/props.cxx +++ b/simgear/misc/props.cxx @@ -17,6 +17,7 @@ #include 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; _listeners->push_back(listener); + listener->register_property(this); +} + +void +SGPropertyNode::removeChangeListener (SGPropertyChangeListener * listener) +{ + vector::iterator it = + find(_listeners->begin(), _listeners->end(), listener); + if (it != _listeners->end()) { + _listeners->erase(it); + listener->unregister_property(this); + if (_listeners->empty()) { + vector * 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 } + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGPropertyChangeListener. +//////////////////////////////////////////////////////////////////////// + +SGPropertyChangeListener::~SGPropertyChangeListener () +{ + // This will come back and remove + // the current item each time. Is + // that OK? + vector::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::iterator it = + find(_properties.begin(), _properties.end(), node); + if (it != _properties.end()) + _properties.erase(it); +} + + // end of props.cxx diff --git a/simgear/misc/props.hxx b/simgear/misc/props.hxx index a077faca..b4a42997 100644 --- a/simgear/misc/props.hxx +++ b/simgear/misc/props.hxx @@ -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 _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.