X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fcanvas%2Felements%2FCanvasGroup.cxx;h=9bfb8c2f26d3df44be309cc8815c591423dde953;hb=1f431323635de0dd86d60a0fc58efa9557983ef8;hp=375c171fd6545ae01f69b4357f289bde41a8c0ad;hpb=81bee2bbc6b3cb4c4971bc72a0ea10d8ffbf9609;p=simgear.git diff --git a/simgear/canvas/elements/CanvasGroup.cxx b/simgear/canvas/elements/CanvasGroup.cxx index 375c171f..9bfb8c2f 100644 --- a/simgear/canvas/elements/CanvasGroup.cxx +++ b/simgear/canvas/elements/CanvasGroup.cxx @@ -21,8 +21,12 @@ #include "CanvasMap.hxx" #include "CanvasPath.hxx" #include "CanvasText.hxx" +#include +#include +#include #include +#include namespace simgear { @@ -34,22 +38,32 @@ namespace canvas template 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; - _child_factories["image"] = &createElement; - _child_factories["map" ] = &createElement; - _child_factories["path" ] = &createElement; - _child_factories["text" ] = &createElement; + if( !isInit() ) + { + _child_factories["group"] = &createElement; + _child_factories["image"] = &createElement; + _child_factories["map" ] = &createElement; + _child_factories["path" ] = &createElement; + _child_factories["text" ] = &createElement; + } } //---------------------------------------------------------------------------- @@ -58,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) { @@ -68,56 +129,90 @@ 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; - 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); + } } - //---------------------------------------------------------------------------- - 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) { @@ -126,10 +221,7 @@ namespace canvas 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