#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>
+#include <boost/lambda/core.hpp>
namespace simgear
{
namespace canvas
{
+ /**
+ * Create an canvas Element of type T
+ */
+ template<typename T>
+ ElementPtr createElement( const CanvasWeakPtr& canvas,
+ const SGPropertyNode_ptr& node,
+ const Style& style,
+ Element* parent )
+ {
+ return ElementPtr( new T(canvas, node, style, parent) );
+ }
//----------------------------------------------------------------------------
Group::Group( const CanvasWeakPtr& canvas,
- SGPropertyNode_ptr node,
- const Style& parent_style ):
- Element(canvas, node, parent_style)
+ const SGPropertyNode_ptr& node,
+ 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 >;
}
//----------------------------------------------------------------------------
}
+ //----------------------------------------------------------------------------
+ ElementPtr Group::createChild( const std::string& type,
+ const std::string& id )
+ {
+ SGPropertyNode* node = _node->addChild(type, 0, false);
+ if( !id.empty() )
+ node->setStringValue("id", id);
+
+ return getChild(node);
+ }
+
+ //----------------------------------------------------------------------------
+ ElementPtr Group::getChild(const SGPropertyNode* node)
+ {
+ ChildList::iterator child = findChild(node);
+ if( child == _children.end() )
+ return ElementPtr();
+
+ 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;
if( child->getParent() != _node )
return;
- boost::shared_ptr<Element> element;
-
- // TODO create map of child factories and use also to check for element
- // on deletion in ::childRemoved
- if( child->getNameString() == "text" )
- element.reset( new Text(_canvas, child, _style) );
- else if( child->getNameString() == "group" )
- element.reset( new Group(_canvas, child, _style) );
- else if( child->getNameString() == "map" )
- element.reset( new Map(_canvas, child, _style) );
- else if( child->getNameString() == "path" )
- element.reset( new Path(_canvas, child, _style) );
- else if( child->getNameString() == "image" )
- element.reset( new Image(_canvas, child, _style) );
-
- if( element )
+ ChildFactories::iterator child_factory =
+ _child_factories.find( child->getNameString() );
+ if( child_factory != _child_factories.end() )
{
+ 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) );
+
return;
}
_style[ child->getNameString() ] = child;
}
- //----------------------------------------------------------------------------
- struct ChildFinder
- {
- public:
- ChildFinder(SGPropertyNode *node):
- _node(node)
- {}
-
- bool operator()(const Group::ChildList::value_type& el) const
- {
- return el.first == _node;
- }
-
- private:
- SGPropertyNode *_node;
- };
-
//----------------------------------------------------------------------------
void Group::childRemoved(SGPropertyNode* node)
{
if( node->getParent() != _node )
return;
- if( node->getNameString() == "text"
- || node->getNameString() == "group"
- || node->getNameString() == "map"
- || node->getNameString() == "path"
- || node->getNameString() == "image" )
+ if( _child_factories.find(node->getNameString()) != _child_factories.end() )
{
- ChildFinder pred(node);
- ChildList::iterator child =
- std::find_if(_children.begin(), _children.end(), pred);
-
+ ChildList::iterator child = findChild(node);
if( child == _children.end() )
SG_LOG
(
//----------------------------------------------------------------------------
void Group::handleZIndexChanged(SGPropertyNode* node, int z_index)
{
- ChildFinder pred(node);
- ChildList::iterator child =
- std::find_if(_children.begin(), _children.end(), pred);
-
+ ChildList::iterator child = findChild(node);
if( child == _children.end() )
return;
);
}
+ //----------------------------------------------------------------------------
+ Group::ChildList::iterator Group::findChild(const SGPropertyNode* node)
+ {
+ return std::find_if
+ (
+ _children.begin(),
+ _children.end(),
+ boost::bind(&ChildList::value_type::first, _1) == node
+ );
+ }
+
} // namespace canvas
} // namespace simgear