From 5330dc34bcde0b3d01490fdbc05af4435a0d111c Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Mon, 29 Oct 2012 16:10:10 +0100 Subject: [PATCH] Helper for property controlled subsystems - Subsystem which manages a list of elements which are controlled through the property tree. - Fix a ShivaVG compiler warning. - Add some helper functions to trigger property removed/add events for a whole property tree. --- simgear/canvas/ShivaVG/src/shPaint.c | 2 +- simgear/props/CMakeLists.txt | 4 + simgear/props/PropertyBasedElement.cxx | 49 ++++++++++ simgear/props/PropertyBasedElement.hxx | 60 ++++++++++++ simgear/props/PropertyBasedMgr.cxx | 129 +++++++++++++++++++++++++ simgear/props/PropertyBasedMgr.hxx | 82 ++++++++++++++++ simgear/props/props.cxx | 31 ++++-- simgear/props/props.hxx | 22 ++++- 8 files changed, 365 insertions(+), 14 deletions(-) create mode 100644 simgear/props/PropertyBasedElement.cxx create mode 100644 simgear/props/PropertyBasedElement.hxx create mode 100644 simgear/props/PropertyBasedMgr.cxx create mode 100644 simgear/props/PropertyBasedMgr.hxx diff --git a/simgear/canvas/ShivaVG/src/shPaint.c b/simgear/canvas/ShivaVG/src/shPaint.c index 406a889b..2a147266 100644 --- a/simgear/canvas/ShivaVG/src/shPaint.c +++ b/simgear/canvas/ShivaVG/src/shPaint.c @@ -187,7 +187,7 @@ void shUpdateColorRampTexture(SHPaint *p) void shValidateInputStops(SHPaint *p) { - SHStop *instop, stop; + SHStop *instop, stop = {0, {0,0,0,0}}; SHfloat lastOffset=0.0f; int i; diff --git a/simgear/props/CMakeLists.txt b/simgear/props/CMakeLists.txt index 7657b445..7a888d28 100644 --- a/simgear/props/CMakeLists.txt +++ b/simgear/props/CMakeLists.txt @@ -4,6 +4,8 @@ include (SimGearComponent) set(HEADERS AtomicChangeListener.hxx ExtendedPropertyAdapter.hxx + PropertyBasedElement.hxx + PropertyBasedMgr.hxx condition.hxx propertyObject.hxx props.hxx @@ -15,6 +17,8 @@ set(HEADERS set(SOURCES AtomicChangeListener.cxx + PropertyBasedElement.cxx + PropertyBasedMgr.cxx condition.cxx propertyObject.cxx props.cxx diff --git a/simgear/props/PropertyBasedElement.cxx b/simgear/props/PropertyBasedElement.cxx new file mode 100644 index 00000000..88a0ad2c --- /dev/null +++ b/simgear/props/PropertyBasedElement.cxx @@ -0,0 +1,49 @@ +// Base class for elements of property controlled subsystems +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#include "PropertyBasedElement.hxx" + +namespace simgear +{ + + //------------------------------------------------------------------------------ + PropertyBasedElement::PropertyBasedElement(SGPropertyNode* node): + _node(node) + { + _node->addChangeListener(this); + } + + //------------------------------------------------------------------------------ + PropertyBasedElement::~PropertyBasedElement() + { + _node->removeChangeListener(this); + } + + //------------------------------------------------------------------------------ + SGConstPropertyNode_ptr PropertyBasedElement::getProps() const + { + return _node; + } + + //------------------------------------------------------------------------------ + SGPropertyNode_ptr PropertyBasedElement::getProps() + { + return _node; + } + +} // namespace simgear diff --git a/simgear/props/PropertyBasedElement.hxx b/simgear/props/PropertyBasedElement.hxx new file mode 100644 index 00000000..23558e70 --- /dev/null +++ b/simgear/props/PropertyBasedElement.hxx @@ -0,0 +1,60 @@ +// Base class for elements of property controlled subsystems +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef SG_PROPERTY_BASED_ELEMENT_HXX_ +#define SG_PROPERTY_BASED_ELEMENT_HXX_ + +#include + +#include +#include + + +namespace simgear +{ + + class PropertyBasedElement; + typedef boost::shared_ptr PropertyBasedElementPtr; + typedef boost::weak_ptr PropertyBasedElementWeakPtr; + + /** + * Base class for a property controlled element + */ + class PropertyBasedElement: + public SGPropertyChangeListener + { + public: + PropertyBasedElement(SGPropertyNode* node); + virtual ~PropertyBasedElement(); + + virtual void update(double delta_time_sec) = 0; + + SGConstPropertyNode_ptr getProps() const; + SGPropertyNode_ptr getProps(); + + protected: + + friend class PropertyBasedMgr; + + SGPropertyNode_ptr _node; + PropertyBasedElementWeakPtr _self; + }; + +} // namespace simgear + +#endif /* SG_PROPERTY_BASED_ELEMENT_HXX_ */ diff --git a/simgear/props/PropertyBasedMgr.cxx b/simgear/props/PropertyBasedMgr.cxx new file mode 100644 index 00000000..893eb34b --- /dev/null +++ b/simgear/props/PropertyBasedMgr.cxx @@ -0,0 +1,129 @@ +// Base class for property controlled subsystems +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#include "PropertyBasedMgr.hxx" + +#include +#include + +namespace simgear +{ + + //---------------------------------------------------------------------------- + void PropertyBasedMgr::init() + { + _props->addChangeListener(this); + _props->fireCreatedRecursive(); + } + + //---------------------------------------------------------------------------- + void PropertyBasedMgr::shutdown() + { + _props->removeChangeListener(this); + } + + //---------------------------------------------------------------------------- + void PropertyBasedMgr::update(double delta_time_sec) + { + for( size_t i = 0; i < _elements.size(); ++i ) + if( _elements[i] ) + _elements[i]->update(delta_time_sec); + } + + //---------------------------------------------------------------------------- + void PropertyBasedMgr::childAdded( SGPropertyNode * parent, + SGPropertyNode * child ) + { + if( parent != _props || child->getNameString() != _name_elements ) + return; + + size_t index = child->getIndex(); + + if( index >= _elements.size() ) + { + if( index > _elements.size() ) + SG_LOG + ( + SG_GENERAL, + SG_WARN, + "Skipping unused " << _name_elements << " slot(s)!" + ); + + _elements.resize(index + 1); + } + else if( _elements[index] ) + SG_LOG + ( + SG_GENERAL, + SG_WARN, + _name_elements << "[" << index << "] already exists!" + ); + + PropertyBasedElementPtr el = _element_factory(child); + el->_self = el; + _elements[index] = el; + elementCreated( el ); + } + + //---------------------------------------------------------------------------- + void PropertyBasedMgr::childRemoved( SGPropertyNode * parent, + SGPropertyNode * child ) + { + if( parent != _props ) + return child->fireChildrenRemovedRecursive(); + else if( child->getNameString() != _name_elements ) + return; + + size_t index = child->getIndex(); + + if( index >= _elements.size() ) + SG_LOG + ( + SG_GENERAL, + SG_WARN, + "can't removed unknown " << _name_elements << "[" << index << "]!" + ); + else + // remove the element... + _elements[index].reset(); + } + + //---------------------------------------------------------------------------- + const SGPropertyNode* PropertyBasedMgr::getPropertyRoot() const + { + return _props; + } + + //---------------------------------------------------------------------------- + PropertyBasedMgr::PropertyBasedMgr( SGPropertyNode_ptr props, + const std::string& name_elements, + ElementFactory element_factory ): + _props( props ), + _name_elements( name_elements ), + _element_factory( element_factory ) + { + + } + + //---------------------------------------------------------------------------- + PropertyBasedMgr::~PropertyBasedMgr() + { + + } + +} // namespace simgear diff --git a/simgear/props/PropertyBasedMgr.hxx b/simgear/props/PropertyBasedMgr.hxx new file mode 100644 index 00000000..bb189bbc --- /dev/null +++ b/simgear/props/PropertyBasedMgr.hxx @@ -0,0 +1,82 @@ +// Base class for property controlled subsystems +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef SG_PROPERTY_BASED_MGR_HXX_ +#define SG_PROPERTY_BASED_MGR_HXX_ + +#include "PropertyBasedElement.hxx" +#include + +#include +#include +#include + +namespace simgear +{ + + class PropertyBasedMgr: + public SGSubsystem, + public SGPropertyChangeListener + { + public: + virtual void init(); + virtual void shutdown(); + + virtual void update (double delta_time_sec); + + virtual void childAdded( SGPropertyNode * parent, + SGPropertyNode * child ); + virtual void childRemoved( SGPropertyNode * parent, + SGPropertyNode * child ); + + virtual void elementCreated(PropertyBasedElementPtr element) {} + + virtual const SGPropertyNode* getPropertyRoot() const; + + protected: + + typedef boost::function + ElementFactory; + + /** Branch in the property tree for this property managed subsystem */ + SGPropertyNode_ptr _props; + + /** Property name of managed elements */ + const std::string _name_elements; + + /** The actually managed elements */ + std::vector _elements; + + /** Function object which creates a new element */ + ElementFactory _element_factory; + + /** + * @param props Root node of property branch used for controlling + * this subsystem + * @param name_elements The name of the nodes for the managed elements + */ + PropertyBasedMgr( SGPropertyNode_ptr props, + const std::string& name_elements, + ElementFactory element_factory ); + virtual ~PropertyBasedMgr() = 0; + + }; + +} // namespace simgear + +#endif /* SG_PROPERTY_BASED_MGR_HXX_ */ diff --git a/simgear/props/props.cxx b/simgear/props/props.cxx index 09b71fb4..c01650fe 100644 --- a/simgear/props/props.cxx +++ b/simgear/props/props.cxx @@ -57,7 +57,6 @@ using std::stringstream; using namespace simgear; - //////////////////////////////////////////////////////////////////////// // Local classes. //////////////////////////////////////////////////////////////////////// @@ -74,14 +73,12 @@ public: }; - //////////////////////////////////////////////////////////////////////// // Convenience macros for value access. //////////////////////////////////////////////////////////////////////// #define TEST_READ(dflt) if (!getAttribute(READ)) return dflt #define TEST_WRITE if (!getAttribute(WRITE)) return false - //////////////////////////////////////////////////////////////////////// // Local path normalization code. @@ -153,7 +150,6 @@ inline bool validateName(const string& name) is_alnum() || is_any_of("_-.")); } - //////////////////////////////////////////////////////////////////////// // Other static utility functions. //////////////////////////////////////////////////////////////////////// @@ -370,7 +366,6 @@ find_node (SGPropertyNode * current, return find_node_aux(current, itr, create, last_index); } - //////////////////////////////////////////////////////////////////////// // Private methods from SGPropertyNode (may be inlined for speed). //////////////////////////////////////////////////////////////////////// @@ -654,7 +649,6 @@ SGPropertyNode::trace_read () const #endif } - //////////////////////////////////////////////////////////////////////// // Public methods from SGPropertyNode. //////////////////////////////////////////////////////////////////////// @@ -1839,7 +1833,6 @@ SGPropertyNode::getNode (const char * relative_path, int index) const return ((SGPropertyNode *)this)->getNode(relative_path, index, false); } - //////////////////////////////////////////////////////////////////////// // Convenience methods using relative paths. //////////////////////////////////////////////////////////////////////// @@ -2145,12 +2138,35 @@ SGPropertyNode::fireChildAdded (SGPropertyNode * child) fireChildAdded(this, child); } +void +SGPropertyNode::fireCreatedRecursive() +{ + _parent->fireChildAdded(this); + + if( _children.empty() && getType() != simgear::props::NONE ) + return fireValueChanged(); + + for(size_t i = 0; i < _children.size(); ++i) + _children[i]->fireCreatedRecursive(); +} + void SGPropertyNode::fireChildRemoved (SGPropertyNode * child) { fireChildRemoved(this, child); } +void +SGPropertyNode::fireChildrenRemovedRecursive() +{ + for(size_t i = 0; i < _children.size(); ++i) + { + SGPropertyNode* child = _children[i]; + fireChildRemoved(this, child); + child->fireChildrenRemovedRecursive(); + } +} + void SGPropertyNode::fireValueChanged (SGPropertyNode * node) { @@ -2189,7 +2205,6 @@ SGPropertyNode::fireChildRemoved (SGPropertyNode * parent, _parent->fireChildRemoved(parent, child); } - //////////////////////////////////////////////////////////////////////// // Implementation of SGPropertyChangeListener. //////////////////////////////////////////////////////////////////////// diff --git a/simgear/props/props.hxx b/simgear/props/props.hxx index e0a1d0c6..6a0f1f93 100644 --- a/simgear/props/props.hxx +++ b/simgear/props/props.hxx @@ -162,7 +162,6 @@ DEFINTERNALPROP(const char[], STRING); - //////////////////////////////////////////////////////////////////////// // A raw value. // @@ -669,7 +668,6 @@ std::istream& SGRawBase::readFrom(std::istream& stream) return stream; } - /** * The smart pointer that manage reference counting */ @@ -682,7 +680,6 @@ namespace simgear typedef std::vector PropertyList; } - /** * The property change listener interface. * @@ -707,7 +704,6 @@ private: }; - /** * A node in a property tree. */ @@ -1587,12 +1583,29 @@ public: */ void fireChildAdded (SGPropertyNode * child); + /** + * Trigger a child-added and value-changed event for every child (Unlimited + * depth) and the node itself. + * + * It can be used to simulating the creation of a property tree, eg. for + * (re)initializing a subsystem which is controlled through the property tree. + */ + void fireCreatedRecursive(); /** * Fire a child-removed event to all listeners. */ void fireChildRemoved (SGPropertyNode * child); + /** + * Fire a child-removed event for every child of this node (Unlimited depth) + * + * Upon removal of a child node only for this single node a child-removed + * event is triggered. If eg. resource cleanup relies on receiving a + * child-removed event for every child this method can be used. + */ + void fireChildrenRemovedRecursive(); + /** * Clear any existing value and set the type to NONE. @@ -1687,7 +1700,6 @@ private: std::vector * _listeners; - // Pass name as a pair of iterators template SGPropertyNode * getChildImpl (Itr begin, Itr end, int index = 0, bool create = false); -- 2.39.5