]> git.mxchange.org Git - simgear.git/blobdiff - simgear/canvas/elements/CanvasGroup.cxx
First working version of DOM like Canvas event handling
[simgear.git] / simgear / canvas / elements / CanvasGroup.cxx
index 89c62a628142bef555e4ab7bc3e3f3c7ea0507e8..0740026828c721d9146eeba92e56ea6a3e793514 100644 (file)
 #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/make_shared.hpp>
 #include <boost/lambda/core.hpp>
 
 namespace simgear
@@ -32,33 +33,29 @@ namespace simgear
 namespace canvas
 {
   /**
-   * Create an ElementFactory for elements of type T
+   * Create an canvas Element of type T
    */
   template<typename T>
-  ElementFactory createElementFactory()
+  ElementPtr createElement( const CanvasWeakPtr& canvas,
+                            const SGPropertyNode_ptr& node,
+                            const Style& style,
+                            Element* parent )
   {
-    return boost::bind
-    (
-      &boost::make_shared<T, const CanvasWeakPtr&,
-                             const SGPropertyNode_ptr&,
-                             const Style&>,
-      boost::lambda::_1,
-      boost::lambda::_2,
-      boost::lambda::_3
-    );
+    return ElementPtr( new T(canvas, node, style, parent) );
   }
 
   //----------------------------------------------------------------------------
   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"] = createElementFactory<Group>();
-    _child_factories["image"] = createElementFactory<Image>();
-    _child_factories["map"  ] = createElementFactory<Map  >();
-    _child_factories["path" ] = createElementFactory<Path >();
-    _child_factories["text" ] = createElementFactory<Text >();
+    _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 >;
   }
 
   //----------------------------------------------------------------------------
@@ -67,6 +64,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<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)
   {
@@ -77,12 +121,12 @@ 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;
@@ -98,7 +142,7 @@ namespace canvas
       _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() );
@@ -110,23 +154,6 @@ namespace canvas
     _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)
   {
@@ -135,10 +162,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
         (
@@ -171,10 +195,7 @@ namespace canvas
   //----------------------------------------------------------------------------
   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;
 
@@ -224,5 +245,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