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.
This commit is contained in:
parent
6f7c0c23d1
commit
6962de4b1f
@ -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()
|
||||
);
|
||||
if( !_transform.valid() )
|
||||
return;
|
||||
|
||||
if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
|
||||
{
|
||||
SG_LOG
|
||||
(
|
||||
SG_GENERAL,
|
||||
SG_WARN,
|
||||
"Element::childRemoved: unknown transform: " << child->getPath()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
_transform_types[ child->getIndex() ] = TT_NONE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
_transform_types[ child->getIndex() ] = TT_NONE;
|
||||
|
||||
while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
|
||||
_transform_types.pop_back();
|
||||
|
||||
_transform_dirty = true;
|
||||
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 )
|
||||
{
|
||||
|
@ -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){}
|
||||
|
@ -174,20 +174,20 @@ namespace canvas
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Group::setStyle(const SGPropertyNode* style)
|
||||
bool Group::setStyle( const SGPropertyNode* style,
|
||||
const StyleSetter* setter )
|
||||
{
|
||||
// Don't propagate styles directly applicable to this group
|
||||
if( Element::setStyle(style) )
|
||||
return true;
|
||||
|
||||
if( style->getParent() != _node
|
||||
&& _style.find(style->getNameString()) != _style.end() )
|
||||
if( !canApplyStyle(style) )
|
||||
return false;
|
||||
|
||||
// Don't propagate styles directly applicable to this group
|
||||
if( setStyleImpl(style, setter) )
|
||||
return true;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user