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/CanvasEventListener.hxx>
|
||||||
#include <simgear/canvas/CanvasEventVisitor.hxx>
|
#include <simgear/canvas/CanvasEventVisitor.hxx>
|
||||||
#include <simgear/canvas/MouseEvent.hxx>
|
#include <simgear/canvas/MouseEvent.hxx>
|
||||||
|
#include <simgear/misc/strutils.hxx>
|
||||||
#include <simgear/scene/material/parseBlendFunc.hxx>
|
#include <simgear/scene/material/parseBlendFunc.hxx>
|
||||||
|
|
||||||
#include <osg/Drawable>
|
#include <osg/Drawable>
|
||||||
@ -315,29 +316,38 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
|
void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
|
||||||
{
|
{
|
||||||
if( parent == _node && child->getNameString() == NAME_TRANSFORM )
|
if( parent == _node )
|
||||||
{
|
{
|
||||||
if( !_transform.valid() )
|
if( child->getNameString() == NAME_TRANSFORM )
|
||||||
return;
|
|
||||||
|
|
||||||
if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
|
|
||||||
{
|
{
|
||||||
SG_LOG
|
if( !_transform.valid() )
|
||||||
(
|
return;
|
||||||
SG_GENERAL,
|
|
||||||
SG_WARN,
|
if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
|
||||||
"Element::childRemoved: unknown transform: " << child->getPath()
|
{
|
||||||
);
|
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;
|
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);
|
childRemoved(child);
|
||||||
@ -350,8 +360,17 @@ namespace canvas
|
|||||||
if( parent == _node )
|
if( parent == _node )
|
||||||
{
|
{
|
||||||
const std::string& name = child->getNameString();
|
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;
|
return;
|
||||||
|
}
|
||||||
else if( name == "update" )
|
else if( name == "update" )
|
||||||
return update(0);
|
return update(0);
|
||||||
else if( name == "visible" )
|
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 =
|
return canApplyStyle(child) && setStyleImpl(child, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -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 )
|
void Element::setDrawable( osg::Drawable* drawable )
|
||||||
{
|
{
|
||||||
|
@ -117,7 +117,8 @@ namespace canvas
|
|||||||
SGPropertyNode * child );
|
SGPropertyNode * child );
|
||||||
virtual void valueChanged(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
|
* 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 childAdded(SGPropertyNode * child) {}
|
||||||
virtual void childRemoved(SGPropertyNode * child){}
|
virtual void childRemoved(SGPropertyNode * child){}
|
||||||
virtual void childChanged(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( !canApplyStyle(style) )
|
||||||
if( Element::setStyle(style) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if( style->getParent() != _node
|
|
||||||
&& _style.find(style->getNameString()) != _style.end() )
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Don't propagate styles directly applicable to this group
|
||||||
|
if( setStyleImpl(style, setter) )
|
||||||
|
return true;
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
|
||||||
{
|
{
|
||||||
if( getChildByIndex(i)->setStyle(style) )
|
if( getChildByIndex(i)->setStyle(style, setter) )
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,8 @@ namespace canvas
|
|||||||
|
|
||||||
virtual bool traverse(EventVisitor& visitor);
|
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;
|
virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const;
|
||||||
|
|
||||||
|
@ -400,8 +400,9 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Image::setFill(const std::string& fill)
|
void Image::setFill(const std::string& fill)
|
||||||
{
|
{
|
||||||
osg::Vec4 color;
|
osg::Vec4 color(1,1,1,1);
|
||||||
if( !parseColor(fill, color) )
|
if( !fill.empty() // If no color is given default to white
|
||||||
|
&& !parseColor(fill, color) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_colors->front() = color;
|
_colors->front() = color;
|
||||||
|
@ -110,7 +110,7 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
void setFill(const std::string& fill)
|
void setFill(const std::string& fill)
|
||||||
{
|
{
|
||||||
if( fill == "none" )
|
if( fill.empty() || fill == "none" )
|
||||||
{
|
{
|
||||||
_mode &= ~VG_FILL_PATH;
|
_mode &= ~VG_FILL_PATH;
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ namespace canvas
|
|||||||
*/
|
*/
|
||||||
void setStroke(const std::string& stroke)
|
void setStroke(const std::string& stroke)
|
||||||
{
|
{
|
||||||
if( stroke == "none" )
|
if( stroke.empty() || stroke == "none" )
|
||||||
{
|
{
|
||||||
_mode &= ~VG_STROKE_PATH;
|
_mode &= ~VG_STROKE_PATH;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user