]> git.mxchange.org Git - simgear.git/blobdiff - simgear/props/props.hxx
Fix #1783: repeated error message on console
[simgear.git] / simgear / props / props.hxx
index 5103e8c0f9130a30b0805eb0e21e2f7f23e8b467..52a2bf91ec49b4b9a821481d71103afedc07a6f4 100644 (file)
 #include <string>
 #include <iostream>
 #include <sstream>
+#include <typeinfo>
 
 #include <boost/utility.hpp>
+#include <boost/type_traits/is_enum.hpp>
 
 #if PROPS_STANDALONE
 #else
@@ -250,15 +252,14 @@ class SGRawBase<T, 0> : public SGRawExtended
 /**
  * Abstract base class for a raw value.
  *
- * <p>The property manager is implemented in two layers.  The {@link
- * SGPropertyNode} is the highest and most abstract layer,
- * representing an LValue/RValue pair: it records the position of the
- * property in the property tree and contains facilities for
- * navigation to other nodes.  It is guaranteed to be persistent: the
- * {@link SGPropertyNode} will not change during a session, even if
- * the property is bound and unbound multiple times.</p>
+ * The property manager is implemented in two layers. The SGPropertyNode is the
+ * highest and most abstract layer, representing an LValue/RValue pair: it
+ * records the position of the property in the property tree and contains
+ * facilities for navigation to other nodes. It is guaranteed to be persistent:
+ * the SGPropertyNode will not change during a session, even if the property is
+ * bound and unbound multiple times.
  *
- * <p>When the property value is not managed internally in the
+ * When the property value is not managed internally in the
  * SGPropertyNode, the SGPropertyNode will contain a reference to an
  * SGRawValue (this class), which provides an abstract way to get,
  * set, and clone the underlying value.  The SGRawValue may change
@@ -266,13 +267,12 @@ class SGRawBase<T, 0> : public SGRawExtended
  * unbound to various data source, but the abstract SGPropertyNode
  * layer insulates the application from those changes.
  *
- * <p>The SGPropertyNode class always keeps a *copy* of a raw value,
- * not the original one passed to it; if you override a derived class
- * but do not replace the {@link #clone} method, strange things will
- * happen.</p>
+ * The SGPropertyNode class always keeps a *copy* of a raw value, not the
+ * original one passed to it; if you override a derived class but do not replace
+ * the {@link SGRaw::clone clone()} method, strange things will happen.
  *
- * <p>All derived SGRawValue classes must implement {@link #getValue},
- * {@link #setValue}, and {@link #clone} for the appropriate type.</p>
+ * All derived SGRawValue classes must implement getValue(), setValue(), and
+ * {@link SGRaw::clone clone()} for the appropriate type.
  *
  * @see SGPropertyNode
  * @see SGRawValuePointer
@@ -694,9 +694,15 @@ class SGPropertyChangeListener
 {
 public:
   virtual ~SGPropertyChangeListener ();
-  virtual void valueChanged (SGPropertyNode * node);
-  virtual void childAdded (SGPropertyNode * parent, SGPropertyNode * child);
-  virtual void childRemoved (SGPropertyNode * parent, SGPropertyNode * child);
+
+  /// Called if value of \a node has changed.
+  virtual void valueChanged(SGPropertyNode * node);
+
+  /// Called if \a child has been added to the given \a parent.
+  virtual void childAdded(SGPropertyNode * parent, SGPropertyNode * child);
+
+  /// Called if \a child has been removed from its \a parent.
+  virtual void childRemoved(SGPropertyNode * parent, SGPropertyNode * child);
 
 protected:
   friend class SGPropertyNode;
@@ -729,6 +735,7 @@ public:
    * whether the property should normally be saved and restored.</p>
    */
   enum Attribute {
+    NO_ATTR = 0,
     READ = 1,
     WRITE = 2,
     ARCHIVE = 4,
@@ -908,36 +915,46 @@ public:
   simgear::PropertyList getChildren (const std::string& name) const
   { return getChildren(name.c_str()); }
 
+  /**
+   * Remove child by pointer (if it is a child of this node).
+   *
+   * @return true, if the node was deleted.
+   */
+  bool removeChild(SGPropertyNode* node);
+
+  // TODO do we need the removeXXX methods to return the deleted nodes?
   /**
    * Remove child by position.
    */
-  SGPropertyNode_ptr removeChild (int pos, bool keep = true);
+  SGPropertyNode_ptr removeChild(int pos);
 
 
   /**
    * Remove a child node
    */
-  SGPropertyNode_ptr removeChild (const char * name, int index = 0,
-                                  bool keep = true);
+  SGPropertyNode_ptr removeChild(const char * name, int index = 0);
 
   /**
    * Remove a child node
    */
-  SGPropertyNode_ptr removeChild (const std::string& name, int index = 0,
-                                  bool keep = true)
-  { return removeChild(name.c_str(), index, keep); }
+  SGPropertyNode_ptr removeChild(const std::string& name, int index = 0)
+  { return removeChild(name.c_str(), index); }
 
   /**
    * Remove all children with the specified name.
    */
-  simgear::PropertyList removeChildren (const char * name, bool keep = true);
+  simgear::PropertyList removeChildren(const char * name);
 
   /**
    * Remove all children with the specified name.
    */
-  simgear::PropertyList removeChildren (const std::string& name,
-                                        bool keep = true)
-  { return removeChildren(name.c_str(), keep); }
+  simgear::PropertyList removeChildren(const std::string& name)
+  { return removeChildren(name.c_str()); }
+
+  /**
+   * Remove all children (does not change the value of the node)
+   */
+  void removeAllChildren();
 
   //
   // Alias support.
@@ -1241,6 +1258,23 @@ public:
     return setValue(&val[0]);
   }
   
+  /**
+   * Set relative node to given value and afterwards make read only.
+   *
+   * @param relative_path   Path to node
+   * @param value           Value to set
+   *
+   * @return whether value could be set
+   */
+  template<typename T>
+  bool setValueReadOnly(const std::string& relative_path, const T& value)
+  {
+    SGPropertyNode* node = getNode(relative_path, true);
+    bool ret = node->setValue(value);
+    node->setAttributes(READ);
+    return ret;
+  }
+
   /**
    * Interpolate current value to target value within given time.
    *
@@ -1259,7 +1293,7 @@ public:
    *
    * @param type        Type of interpolation ("numeric", "color", etc.)
    * @param values      Nodes containing intermediate and target values
-   * @param duration    Durations for each interpolation step (in seconds)
+   * @param deltas      Durations for each interpolation step (in seconds)
    * @param easing      Easing function (http://easings.net/)
    */
   bool interpolate( const std::string& type,
@@ -1272,6 +1306,11 @@ public:
    */
   static void setInterpolationMgr(simgear::PropertyInterpolationMgr* mgr);
 
+  /**
+   * Get the interpolation manager
+   */
+  static simgear::PropertyInterpolationMgr* getInterpolationMgr();
+
   /**
    * Print the value of the property to a stream.
    */
@@ -1678,6 +1717,8 @@ protected:
   void fireChildAdded (SGPropertyNode * parent, SGPropertyNode * child);
   void fireChildRemoved (SGPropertyNode * parent, SGPropertyNode * child);
 
+  SGPropertyNode_ptr eraseChild(simgear::PropertyList::iterator child);
+
   /**
    * Protected constructor for making new nodes on demand.
    */
@@ -1728,7 +1769,6 @@ private:
   /// counted pointer
   SGPropertyNode * _parent;
   simgear::PropertyList _children;
-  simgear::PropertyList _removedChildren;
   mutable std::string _buffer;
   simgear::props::Type _type;
   bool _tied;
@@ -1756,7 +1796,7 @@ private:
   SGPropertyNode * getChildImpl (Itr begin, Itr end, int index = 0, bool create = false);
   // very internal method
   template<typename Itr>
-  SGPropertyNode* getExistingChild (Itr begin, Itr end, int index, bool create);
+  SGPropertyNode* getExistingChild (Itr begin, Itr end, int index);
   // very internal path parsing function
   template<typename SplitItr>
   friend SGPropertyNode* find_node_aux(SGPropertyNode * current, SplitItr& itr,
@@ -1767,7 +1807,8 @@ private:
 
 // Convenience functions for use in templates
 template<typename T>
-T getValue(const SGPropertyNode*);
+typename boost::disable_if<boost::is_enum<T>, T>::type
+getValue(const SGPropertyNode*);
 
 template<>
 inline bool getValue<bool>(const SGPropertyNode* node) { return node->getBoolValue(); }
@@ -1802,6 +1843,52 @@ inline std::string getValue<std::string>(const SGPropertyNode* node)
     return node->getStringValue();
 }
 
+namespace simgear
+{
+  /**
+   * Default trait for extracting enum values from SGPropertyNode. Create your
+   * own specialization for specific enum types to enable validation of values.
+   */
+  template<class T>
+  struct enum_traits
+  {
+    /**
+     * Typename of the enum
+     */
+    static const char* name() { return typeid(T).name(); }
+
+    /**
+     * @return Default value (will be used if validation fails)
+     */
+    static T defVal() { return T(); }
+
+    /**
+     * @return Whether the given integer value has an enum value defined
+     */
+    static bool validate(int) { return true; }
+  };
+} // namespace simgear
+
+/** Extract enum from SGPropertyNode */
+template<typename T>
+inline typename boost::enable_if<boost::is_enum<T>, T>::type
+getValue(const SGPropertyNode* node)
+{
+  typedef simgear::enum_traits<T> Traits;
+  int val = node->getIntValue();
+  if( !Traits::validate(val) )
+  {
+    SG_LOG
+    (
+      SG_GENERAL,
+      SG_WARN,
+      "Invalid value for enum (" << Traits::name() << ", val = " << val << ")"
+    );
+    return Traits::defVal();
+  }
+  return static_cast<T>(node->getIntValue());
+}
+
 inline bool setValue(SGPropertyNode* node, bool value)
 {
     return node->setBoolValue(value);
@@ -2039,6 +2126,13 @@ public:
     {
         _property->addChangeListener(this,initial);
     }
+
+       SGPropertyChangeCallback(const SGPropertyChangeCallback<T>& other) :
+               _obj(other._obj), _callback(other._callback), _property(other._property)
+       {
+                _property->addChangeListener(this,false);
+       }
+
     virtual ~SGPropertyChangeCallback()
     {
         _property->removeChangeListener(this);