]> git.mxchange.org Git - simgear.git/commitdiff
Helper for property controlled subsystems
authorThomas Geymayer <tomgey@gmail.com>
Mon, 29 Oct 2012 15:10:10 +0000 (16:10 +0100)
committerThomas Geymayer <tomgey@gmail.com>
Mon, 29 Oct 2012 15:11:35 +0000 (16:11 +0100)
 - 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
simgear/props/CMakeLists.txt
simgear/props/PropertyBasedElement.cxx [new file with mode: 0644]
simgear/props/PropertyBasedElement.hxx [new file with mode: 0644]
simgear/props/PropertyBasedMgr.cxx [new file with mode: 0644]
simgear/props/PropertyBasedMgr.hxx [new file with mode: 0644]
simgear/props/props.cxx
simgear/props/props.hxx

index 406a889b86930dce658b67cc6008ef75ba497471..2a147266bc6e41219aa4fa40234bee1d98a30ab4 100644 (file)
@@ -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;
   
index 7657b4451f2ab805206790bc78b6a03f0720f2a9..7a888d282ad482707039e702f4a0176228ebf82c 100644 (file)
@@ -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 (file)
index 0000000..88a0ad2
--- /dev/null
@@ -0,0 +1,49 @@
+// Base class for elements of property controlled subsystems
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 (file)
index 0000000..23558e7
--- /dev/null
@@ -0,0 +1,60 @@
+// Base class for elements of property controlled subsystems
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 <simgear/props/props.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+
+namespace simgear
+{
+
+  class PropertyBasedElement;
+  typedef boost::shared_ptr<PropertyBasedElement> PropertyBasedElementPtr;
+  typedef boost::weak_ptr<PropertyBasedElement> 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 (file)
index 0000000..893eb34
--- /dev/null
@@ -0,0 +1,129 @@
+// Base class for property controlled subsystems
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 <stdexcept>
+#include <string>
+
+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 (file)
index 0000000..bb189bb
--- /dev/null
@@ -0,0 +1,82 @@
+// Base class for property controlled subsystems
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 <simgear/structure/subsystem_mgr.hxx>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <vector>
+
+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<PropertyBasedElementPtr(SGPropertyNode*)>
+              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<PropertyBasedElementPtr> _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_ */
index 09b71fb44c6b91a158fdefd0a86707d65f665cd7..c01650feb2d9952c24f6665b4ff130b1dba2acb4 100644 (file)
@@ -57,7 +57,6 @@ using std::stringstream;
 
 using namespace simgear;
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Local classes.
 ////////////////////////////////////////////////////////////////////////
@@ -74,14 +73,12 @@ public:
 };
 
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Convenience macros for value access.
 ////////////////////////////////////////////////////////////////////////
 
 #define TEST_READ(dflt) if (!getAttribute(READ)) return dflt
 #define TEST_WRITE if (!getAttribute(WRITE)) return false
-\f
 
 ////////////////////////////////////////////////////////////////////////
 // Local path normalization code.
@@ -153,7 +150,6 @@ inline bool validateName(const string& name)
              is_alnum() || is_any_of("_-."));
 }
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Other static utility functions.
 ////////////////////////////////////////////////////////////////////////
@@ -370,7 +366,6 @@ find_node (SGPropertyNode * current,
      return find_node_aux(current, itr, create, last_index);
 }
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Private methods from SGPropertyNode (may be inlined for speed).
 ////////////////////////////////////////////////////////////////////////
@@ -654,7 +649,6 @@ SGPropertyNode::trace_read () const
 #endif
 }
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // 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);
 }
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // 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);
 }
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGPropertyChangeListener.
 ////////////////////////////////////////////////////////////////////////
index e0a1d0c6fef68aa425a8723a0a2850bec7fc281b..6a0f1f93785c541cf79b3308706837203535fd57 100644 (file)
@@ -162,7 +162,6 @@ DEFINTERNALPROP(const char[], STRING);
 
 
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // A raw value.
 //
@@ -669,7 +668,6 @@ std::istream& SGRawBase<T, 0>::readFrom(std::istream& stream)
     return stream;
 }
 
-\f
 /**
  * The smart pointer that manage reference counting
  */
@@ -682,7 +680,6 @@ namespace simgear
 typedef std::vector<SGPropertyNode_ptr> PropertyList;
 }
 
-\f
 /**
  * The property change listener interface.
  *
@@ -707,7 +704,6 @@ private:
 };
 
 
-\f
 /**
  * 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<SGPropertyChangeListener *> * _listeners;
 
-\f
   // Pass name as a pair of iterators
   template<typename Itr>
   SGPropertyNode * getChildImpl (Itr begin, Itr end, int index = 0, bool create = false);