]> git.mxchange.org Git - simgear.git/commitdiff
Canvas: fix property inheritance.
authorThomas Geymayer <tomgey@gmail.com>
Tue, 2 Jul 2013 20:42:46 +0000 (22:42 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Tue, 2 Jul 2013 22:05:20 +0000 (00:05 +0200)
 - Do not override style of children if they have own values set.
 - Retrieve style of parent if own style value has been removed.

simgear/canvas/elements/CanvasElement.cxx
simgear/canvas/elements/CanvasElement.hxx
simgear/canvas/elements/CanvasGroup.cxx
simgear/canvas/elements/CanvasGroup.hxx
simgear/canvas/elements/CanvasImage.cxx
simgear/canvas/elements/CanvasPath.cxx

index 3bada0c081d84f78f360cff9a6a16c6db3eb5dde..85327b2a45c5e01790c4bf02f49721db6953fb78 100644 (file)
@@ -21,6 +21,7 @@
 #include <simgear/canvas/CanvasEventListener.hxx>
 #include <simgear/canvas/CanvasEventVisitor.hxx>
 #include <simgear/canvas/MouseEvent.hxx>
+#include <simgear/misc/strutils.hxx>
 #include <simgear/scene/material/parseBlendFunc.hxx>
 
 #include <osg/Drawable>
@@ -315,29 +316,38 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
   {
-    if( parent == _node && child->getNameString() == NAME_TRANSFORM )
+    if( parent == _node )
     {
-      if( !_transform.valid() )
-        return;
-
-      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
+      if( child->getNameString() == NAME_TRANSFORM )
       {
-        SG_LOG
-        (
-          SG_GENERAL,
-          SG_WARN,
-          "Element::childRemoved: unknown transform: " << child->getPath()
-        );
-        return;
-      }
+        if( !_transform.valid() )
+          return;
 
-      _transform_types[ child->getIndex() ] = TT_NONE;
+        if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
+        {
+          SG_LOG
+          (
+            SG_GENERAL,
+            SG_WARN,
+            "Element::childRemoved: unknown transform: " << child->getPath()
+          );
+          return;
+        }
 
-      while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
-        _transform_types.pop_back();
+        _transform_types[ child->getIndex() ] = TT_NONE;
 
-      _transform_dirty = true;
-      return;
+        while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
+          _transform_types.pop_back();
+
+        _transform_dirty = true;
+        return;
+      }
+      else if( StyleSetter const* setter =
+                 getStyleSetter(child->getNameString()) )
+      {
+        setStyle(getParentStyle(child), setter);
+        return;
+      }
     }
 
     childRemoved(child);
@@ -350,8 +360,17 @@ namespace canvas
     if( parent == _node )
     {
       const std::string& name = child->getNameString();
-      if( setStyle(child) )
+      if( StyleSetter const* setter = getStyleSetter(name) )
+      {
+        SGPropertyNode const* style = child;
+        if( isStyleEmpty(child) )
+        {
+          child->clearValue();
+          style = getParentStyle(child);
+        }
+        setStyle(style, setter);
         return;
+      }
       else if( name == "update" )
         return update(0);
       else if( name == "visible" )
@@ -371,21 +390,10 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  bool Element::setStyle(const SGPropertyNode* child)
+  bool Element::setStyle( const SGPropertyNode* child,
+                          const StyleSetter* setter )
   {
-    StyleSetters::const_iterator setter =
-      _style_setters.find(child->getNameString());
-    if( setter == _style_setters.end() )
-      return false;
-
-    const StyleSetter* style_setter = &setter->second.setter;
-    while( style_setter )
-    {
-      if( style_setter->func(*this, child) )
-        return true;
-      style_setter = style_setter->next;
-    }
-    return false;
+    return canApplyStyle(child) && setStyleImpl(child, setter);
   }
 
   //----------------------------------------------------------------------------
@@ -516,6 +524,67 @@ namespace canvas
     }
   }
 
+  //----------------------------------------------------------------------------
+  bool Element::isStyleEmpty(const SGPropertyNode* child) const
+  {
+    return !child
+        || simgear::strutils::strip(child->getStringValue()).empty();
+  }
+
+  //----------------------------------------------------------------------------
+  bool Element::canApplyStyle(const SGPropertyNode* child) const
+  {
+    if( _node == child->getParent() )
+      return true;
+
+    // Parent values do not override if element has own value
+    return isStyleEmpty( _node->getChild(child->getName()) );
+  }
+
+  //----------------------------------------------------------------------------
+  bool Element::setStyleImpl( const SGPropertyNode* child,
+                              const StyleSetter* setter )
+  {
+    const StyleSetter* style_setter = setter
+                                    ? setter
+                                    : getStyleSetter(child->getNameString());
+    while( style_setter )
+    {
+      if( style_setter->func(*this, child) )
+        return true;
+      style_setter = style_setter->next;
+    }
+    return false;
+  }
+
+  //----------------------------------------------------------------------------
+  const Element::StyleSetter*
+  Element::getStyleSetter(const std::string& name) const
+  {
+    StyleSetters::const_iterator setter = _style_setters.find(name);
+    if( setter == _style_setters.end() )
+      return 0;
+
+    return &setter->second.setter;
+  }
+
+  //----------------------------------------------------------------------------
+  const SGPropertyNode*
+  Element::getParentStyle(const SGPropertyNode* child) const
+  {
+    // Try to get value from parent...
+    if( _parent )
+    {
+      Style::const_iterator style =
+        _parent->_style.find(child->getNameString());
+      if( style != _parent->_style.end() )
+        return style->second;
+    }
+
+    // ...or reset to default if none is available
+    return child; // TODO somehow get default value for each style?
+  }
+
   //----------------------------------------------------------------------------
   void Element::setDrawable( osg::Drawable* drawable )
   {
index deb57f6775bfe839602863d8905e3979559ab7dd..a624bb22f8364eac49fd5983cf16b235f06d5ad9 100644 (file)
@@ -117,7 +117,8 @@ namespace canvas
                                  SGPropertyNode * child );
       virtual void valueChanged(SGPropertyNode * child);
 
-      virtual bool setStyle(const SGPropertyNode* child);
+      virtual bool setStyle( const SGPropertyNode* child,
+                             const StyleSetter* setter = 0 );
 
       /**
        * Set clipping shape
@@ -441,6 +442,14 @@ namespace canvas
         );
       }
 
+      bool isStyleEmpty(const SGPropertyNode* child) const;
+      bool canApplyStyle(const SGPropertyNode* child) const;
+      bool setStyleImpl( const SGPropertyNode* child,
+                         const StyleSetter* setter = 0 );
+
+      const StyleSetter* getStyleSetter(const std::string& name) const;
+      const SGPropertyNode* getParentStyle(const SGPropertyNode* child) const;
+
       virtual void childAdded(SGPropertyNode * child)  {}
       virtual void childRemoved(SGPropertyNode * child){}
       virtual void childChanged(SGPropertyNode * child){}
index f910315deca4f9d5c67961b0c946ca21506e2c2e..7199a97689b346b5e9c05f48f1094790b37f73b5 100644 (file)
@@ -174,20 +174,20 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  bool Group::setStyle(const SGPropertyNode* style)
+  bool Group::setStyle( const SGPropertyNode* style,
+                        const StyleSetter* setter )
   {
+    if( !canApplyStyle(style) )
+      return false;
+
     // Don't propagate styles directly applicable to this group
-    if( Element::setStyle(style) )
+    if( setStyleImpl(style, setter) )
       return true;
 
-    if(    style->getParent() != _node
-        && _style.find(style->getNameString()) != _style.end() )
-      return false;
-
     bool handled = false;
     for(size_t i = 0; i < _transform->getNumChildren(); ++i)
     {
-      if( getChildByIndex(i)->setStyle(style) )
+      if( getChildByIndex(i)->setStyle(style, setter) )
         handled = true;
     }
 
index 81c6e639ab192b62647c27f13bc5b4a086fd42df..cf40e8efb517be331651b0e00cb492453610e454 100644 (file)
@@ -92,7 +92,8 @@ namespace canvas
 
       virtual bool traverse(EventVisitor& visitor);
 
-      virtual bool setStyle(const SGPropertyNode* child);
+      virtual bool setStyle( const SGPropertyNode* child,
+                             const StyleSetter* setter = 0 );
 
       virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const;
 
index 43afd8e680411afef87494499fc6e5125e93da6e..9f1f57586b502decd808de633880506a6ae6218c 100644 (file)
@@ -400,8 +400,9 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Image::setFill(const std::string& fill)
   {
-    osg::Vec4 color;
-    if( !parseColor(fill, color) )
+    osg::Vec4 color(1,1,1,1);
+    if(    !fill.empty() // If no color is given default to white
+        && !parseColor(fill, color) )
       return;
 
     _colors->front() = color;
index 1580285ed561b56a93e99988c6af91eefb4cb2d7..d801c68ac95aff1fe9847aebe197a231581f8b8e 100644 (file)
@@ -110,7 +110,7 @@ namespace canvas
        */
       void setFill(const std::string& fill)
       {
-        if( fill == "none" )
+        if( fill.empty() || fill == "none" )
         {
           _mode &= ~VG_FILL_PATH;
         }
@@ -150,7 +150,7 @@ namespace canvas
        */
       void setStroke(const std::string& stroke)
       {
-        if( stroke == "none" )
+        if( stroke.empty() || stroke == "none" )
         {
           _mode &= ~VG_STROKE_PATH;
         }