X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fcanvas%2Felements%2FCanvasGroup.cxx;h=9bfb8c2f26d3df44be309cc8815c591423dde953;hb=1f431323635de0dd86d60a0fc58efa9557983ef8;hp=ff4be60ff0ac56530e4c4a5996636e0d114e36fd;hpb=b99f53fda3b06378668bdccd4a9d07161f263366;p=simgear.git diff --git a/simgear/canvas/elements/CanvasGroup.cxx b/simgear/canvas/elements/CanvasGroup.cxx index ff4be60f..9bfb8c2f 100644 --- a/simgear/canvas/elements/CanvasGroup.cxx +++ b/simgear/canvas/elements/CanvasGroup.cxx @@ -21,21 +21,49 @@ #include "CanvasMap.hxx" #include "CanvasPath.hxx" #include "CanvasText.hxx" +#include +#include +#include #include +#include namespace simgear { namespace canvas { + /** + * Create an canvas Element of type T + */ + template + ElementPtr createElement( const CanvasWeakPtr& canvas, + const SGPropertyNode_ptr& node, + const Style& style, + Element* parent ) + { + ElementPtr el( new T(canvas, node, style, parent) ); + el->setSelf(el); + return el; + } + + //---------------------------------------------------------------------------- + ElementFactories Group::_child_factories; //---------------------------------------------------------------------------- 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) { - + if( !isInit() ) + { + _child_factories["group"] = &createElement; + _child_factories["image"] = &createElement; + _child_factories["map" ] = &createElement; + _child_factories["path" ] = &createElement; + _child_factories["text" ] = &createElement; + } } //---------------------------------------------------------------------------- @@ -44,6 +72,53 @@ namespace canvas } + //---------------------------------------------------------------------------- + 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 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(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) { @@ -54,82 +129,99 @@ namespace canvas } //---------------------------------------------------------------------------- - 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; - boost::shared_ptr 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 ) + ElementFactories::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) ); + + // ...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); + } } - //---------------------------------------------------------------------------- - 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 ( @@ -156,16 +248,13 @@ namespace canvas { 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) { - ChildFinder pred(node); - ChildList::iterator child = - std::find_if(_children.begin(), _children.end(), pred); - if( child == _children.end() ) return; @@ -215,5 +304,16 @@ namespace canvas ); } + //---------------------------------------------------------------------------- + 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