#include "CanvasMap.hxx"
#include "CanvasPath.hxx"
#include "CanvasText.hxx"
+#include <simgear/canvas/CanvasEventVisitor.hxx>
+#include <simgear/canvas/MouseEvent.hxx>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
template<typename T>
ElementPtr createElement( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
- const Style& style )
+ const Style& style,
+ Element* parent )
{
- return ElementPtr( new T(canvas, node, style) );
+ ElementPtr el( new T(canvas, node, style, parent) );
+ el->setSelf(el);
+ return el;
}
+ //----------------------------------------------------------------------------
+ ElementFactories Group::_child_factories;
+
//----------------------------------------------------------------------------
Group::Group( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
- const Style& parent_style ):
- Element(canvas, node, parent_style)
+ const Style& parent_style,
+ Element* parent ):
+ Element(canvas, node, parent_style, parent)
{
- _child_factories["group"] = &createElement<Group>;
- _child_factories["image"] = &createElement<Image>;
- _child_factories["map" ] = &createElement<Map >;
- _child_factories["path" ] = &createElement<Path >;
- _child_factories["text" ] = &createElement<Text >;
+ if( !isInit<Group>() )
+ {
+ _child_factories["group"] = &createElement<Group>;
+ _child_factories["image"] = &createElement<Image>;
+ _child_factories["map" ] = &createElement<Map >;
+ _child_factories["path" ] = &createElement<Path >;
+ _child_factories["text" ] = &createElement<Text >;
+ }
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
ElementPtr Group::createChild( const std::string& type,
- const std::string& name )
+ const std::string& id )
{
SGPropertyNode* node = _node->addChild(type, 0, false);
- if( !name.empty() )
- node->setStringValue("name", name);
+ if( !id.empty() )
+ node->setStringValue("id", id);
return getChild(node);
}
return child->second;
}
+ //----------------------------------------------------------------------------
+ ElementPtr Group::getElementById(const std::string& id)
+ {
+ std::vector<GroupPtr> groups;
+
+ BOOST_FOREACH( ChildList::value_type child, _children )
+ {
+ const ElementPtr& el = child.second;
+ if( el->getProps()->getStringValue("id") == id )
+ return el;
+
+ GroupPtr group = boost::dynamic_pointer_cast<Group>(el);
+ if( group )
+ groups.push_back(group);
+ }
+
+ BOOST_FOREACH( GroupPtr group, groups )
+ {
+ ElementPtr el = group->getElementById(id);
+ if( el )
+ return el;
+ }
+
+ return ElementPtr();
+ }
+
//----------------------------------------------------------------------------
void Group::update(double dt)
{
}
//----------------------------------------------------------------------------
- bool Group::handleLocalMouseEvent(const canvas::MouseEvent& event)
+ bool Group::traverse(EventVisitor& visitor)
{
// Iterate in reverse order as last child is displayed on top
BOOST_REVERSE_FOREACH( ChildList::value_type child, _children )
{
- if( child.second->handleMouseEvent(event) )
+ if( child.second->accept(visitor) )
return true;
}
return false;
}
+ //----------------------------------------------------------------------------
+ bool Group::setStyle(const SGPropertyNode* style)
+ {
+ // 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() )
+ return false;
+
+ bool handled = false;
+ BOOST_FOREACH( ChildList::value_type child, _children )
+ {
+ if( child.second->setStyle(style) )
+ handled = true;
+ }
+
+ return handled;
+ }
+
+ //----------------------------------------------------------------------------
+ osg::BoundingBox Group::getTransformedBounds(const osg::Matrix& m) const
+ {
+ osg::BoundingBox bb;
+
+ BOOST_FOREACH( ChildList::value_type child, _children )
+ {
+ if( !child.second->getMatrixTransform()->getNodeMask() )
+ continue;
+
+ bb.expandBy
+ (
+ child.second->getTransformedBounds
+ (
+ child.second->getMatrixTransform()->getMatrix() * m
+ )
+ );
+ }
+
+ return bb;
+ }
+
//----------------------------------------------------------------------------
void Group::childAdded(SGPropertyNode* child)
{
if( child->getParent() != _node )
return;
- ChildFactories::iterator child_factory =
+ ElementFactories::iterator child_factory =
_child_factories.find( child->getNameString() );
if( child_factory != _child_factories.end() )
{
- ElementPtr element = child_factory->second(_canvas, child, _style);
+ ElementPtr element = child_factory->second(_canvas, child, _style, this);
// Add to osg scene graph...
_transform->addChild( element->getMatrixTransform() );
_children.push_back( ChildList::value_type(child, element) );
+ // ...and ensure correct ordering
+ handleZIndexChanged( --_children.end() );
+
return;
}
- _style[ child->getNameString() ] = child;
+ if( !Element::setStyle(child) )
+ {
+ // Only add style if not applicable to group itself
+ _style[ child->getNameString() ] = child;
+ setStyle(child);
+ }
}
//----------------------------------------------------------------------------
{
if( node->getParent()->getParent() == _node
&& node->getNameString() == "z-index" )
- return handleZIndexChanged(node->getParent(), node->getIntValue());
+ return handleZIndexChanged( findChild(node->getParent()),
+ node->getIntValue() );
}
//----------------------------------------------------------------------------
- void Group::handleZIndexChanged(SGPropertyNode* node, int z_index)
+ void Group::handleZIndexChanged(ChildList::iterator child, int z_index)
{
- ChildList::iterator child = findChild(node);
if( child == _children.end() )
return;