From 6962de4b1f69d0be5a7fa766f8430582d4a59e8c Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Tue, 2 Jul 2013 22:42:46 +0200 Subject: [PATCH] Canvas: fix property inheritance. - 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 | 135 ++++++++++++++++------ simgear/canvas/elements/CanvasElement.hxx | 11 +- simgear/canvas/elements/CanvasGroup.cxx | 14 +-- simgear/canvas/elements/CanvasGroup.hxx | 3 +- simgear/canvas/elements/CanvasImage.cxx | 5 +- simgear/canvas/elements/CanvasPath.cxx | 4 +- 6 files changed, 126 insertions(+), 46 deletions(-) diff --git a/simgear/canvas/elements/CanvasElement.cxx b/simgear/canvas/elements/CanvasElement.cxx index 3bada0c0..85327b2a 100644 --- a/simgear/canvas/elements/CanvasElement.cxx +++ b/simgear/canvas/elements/CanvasElement.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -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(_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(_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 ) { diff --git a/simgear/canvas/elements/CanvasElement.hxx b/simgear/canvas/elements/CanvasElement.hxx index deb57f67..a624bb22 100644 --- a/simgear/canvas/elements/CanvasElement.hxx +++ b/simgear/canvas/elements/CanvasElement.hxx @@ -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){} diff --git a/simgear/canvas/elements/CanvasGroup.cxx b/simgear/canvas/elements/CanvasGroup.cxx index f910315d..7199a976 100644 --- a/simgear/canvas/elements/CanvasGroup.cxx +++ b/simgear/canvas/elements/CanvasGroup.cxx @@ -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; } diff --git a/simgear/canvas/elements/CanvasGroup.hxx b/simgear/canvas/elements/CanvasGroup.hxx index 81c6e639..cf40e8ef 100644 --- a/simgear/canvas/elements/CanvasGroup.hxx +++ b/simgear/canvas/elements/CanvasGroup.hxx @@ -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; diff --git a/simgear/canvas/elements/CanvasImage.cxx b/simgear/canvas/elements/CanvasImage.cxx index 43afd8e6..9f1f5758 100644 --- a/simgear/canvas/elements/CanvasImage.cxx +++ b/simgear/canvas/elements/CanvasImage.cxx @@ -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; diff --git a/simgear/canvas/elements/CanvasPath.cxx b/simgear/canvas/elements/CanvasPath.cxx index 1580285e..d801c68a 100644 --- a/simgear/canvas/elements/CanvasPath.cxx +++ b/simgear/canvas/elements/CanvasPath.cxx @@ -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; } -- 2.39.5