void shValidateInputStops(SHPaint *p)
{
- SHStop *instop, stop;
+ SHStop *instop, stop = {0, {0,0,0,0}};
SHfloat lastOffset=0.0f;
int i;
set(HEADERS
AtomicChangeListener.hxx
ExtendedPropertyAdapter.hxx
+ PropertyBasedElement.hxx
+ PropertyBasedMgr.hxx
condition.hxx
propertyObject.hxx
props.hxx
set(SOURCES
AtomicChangeListener.cxx
+ PropertyBasedElement.cxx
+ PropertyBasedMgr.cxx
condition.cxx
propertyObject.cxx
props.cxx
--- /dev/null
+// 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
--- /dev/null
+// 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_ */
--- /dev/null
+// 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
--- /dev/null
+// 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_ */
using namespace simgear;
-\f
////////////////////////////////////////////////////////////////////////
// Local classes.
////////////////////////////////////////////////////////////////////////
};
-\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.
is_alnum() || is_any_of("_-."));
}
-\f
////////////////////////////////////////////////////////////////////////
// Other static utility functions.
////////////////////////////////////////////////////////////////////////
return find_node_aux(current, itr, create, last_index);
}
-\f
////////////////////////////////////////////////////////////////////////
// Private methods from SGPropertyNode (may be inlined for speed).
////////////////////////////////////////////////////////////////////////
#endif
}
-\f
////////////////////////////////////////////////////////////////////////
// Public methods from SGPropertyNode.
////////////////////////////////////////////////////////////////////////
return ((SGPropertyNode *)this)->getNode(relative_path, index, false);
}
-\f
////////////////////////////////////////////////////////////////////////
// Convenience methods using relative paths.
////////////////////////////////////////////////////////////////////////
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)
{
_parent->fireChildRemoved(parent, child);
}
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGPropertyChangeListener.
////////////////////////////////////////////////////////////////////////
-\f
////////////////////////////////////////////////////////////////////////
// A raw value.
//
return stream;
}
-\f
/**
* The smart pointer that manage reference counting
*/
typedef std::vector<SGPropertyNode_ptr> PropertyList;
}
-\f
/**
* The property change listener interface.
*
};
-\f
/**
* A node in a property tree.
*/
*/
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.
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);