]> git.mxchange.org Git - simgear.git/blobdiff - simgear/canvas/Canvas.cxx
canvas::Layout: clear parent/canvas after calling onRemove.
[simgear.git] / simgear / canvas / Canvas.cxx
index 5a1e09cb02471e7d42a140d591ddeed6844a5881..c7898b4535df604b07de4b0ccda9fa545af708af 100644 (file)
@@ -19,8 +19,8 @@
 #include "Canvas.hxx"
 #include "CanvasEventManager.hxx"
 #include "CanvasEventVisitor.hxx"
-#include <simgear/canvas/MouseEvent.hxx>
-#include <simgear/canvas/CanvasPlacement.hxx>
+#include "CanvasPlacement.hxx"
+#include <simgear/canvas/events/MouseEvent.hxx>
 #include <simgear/scene/util/parse_color.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
 
@@ -48,8 +48,12 @@ namespace canvas
   void Canvas::CullCallback::operator()( osg::Node* node,
                                          osg::NodeVisitor* nv )
   {
-    if( (nv->getTraversalMask() & simgear::MODEL_BIT) && !_canvas.expired() )
-      _canvas.lock()->enableRendering();
+    if( (nv->getTraversalMask() & simgear::MODEL_BIT) )
+    {
+      CanvasPtr canvas = _canvas.lock();
+      if( canvas )
+        canvas->enableRendering();
+    }
 
     traverse(node, nv);
   }
@@ -72,6 +76,13 @@ namespace canvas
   {
     _status = 0;
     setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
+
+    _root_group.reset( new Group(this, _node) );
+
+    // Remove automatically created property listener as we forward them on our
+    // own
+    _root_group->removeListener();
+    _cull_callback = new CullCallback(this);
   }
 
   //----------------------------------------------------------------------------
@@ -180,6 +191,14 @@ namespace canvas
     return _root_group;
   }
 
+  //----------------------------------------------------------------------------
+  void Canvas::setLayout(const LayoutRef& layout)
+  {
+    _layout = layout;
+    _layout->setCanvas(this);
+    _status |= LAYOUT_DIRTY;
+  }
+
   //----------------------------------------------------------------------------
   void Canvas::enableRendering(bool force)
   {
@@ -191,11 +210,10 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Canvas::update(double delta_time_sec)
   {
-    if(    (!_texture.serviceable() && _status != STATUS_DIRTY)
-        || (_status & CREATE_FAILED) )
+    if( _status & (CREATE_FAILED | MISSING_SIZE) )
       return;
 
-    if( _status == STATUS_DIRTY )
+    if( _status & STATUS_DIRTY )
     {
       _texture.setSize(_size_x, _size_y);
 
@@ -237,23 +255,36 @@ namespace canvas
       }
     }
 
+    if( _layout )
+    {
+      if( (_status & LAYOUT_DIRTY) )
+      {
+        _layout->setGeometry(SGRecti(0, 0, _view_width, _view_height));
+        _status &= ~LAYOUT_DIRTY;
+      }
+      else
+        _layout->update();
+    }
+
     if( _visible || _render_always )
     {
-      BOOST_FOREACH(CanvasWeakPtr canvas, _child_canvases)
+      BOOST_FOREACH(CanvasWeakPtr canvas_weak, _child_canvases)
       {
         // TODO should we check if the image the child canvas is displayed
         //      within is really visible?
-        if( !canvas.expired() )
-          canvas.lock()->_visible = true;
+        CanvasPtr canvas = canvas_weak.lock();
+        if( canvas )
+          canvas->_visible = true;
       }
 
       if( _render_dirty )
       {
         // Also mark all canvases this canvas is displayed within as dirty
-        BOOST_FOREACH(CanvasWeakPtr canvas, _parent_canvases)
+        BOOST_FOREACH(CanvasWeakPtr canvas_weak, _parent_canvases)
         {
-          if( !canvas.expired() )
-            canvas.lock()->_render_dirty = true;
+          CanvasPtr canvas = canvas_weak.lock();
+          if( canvas )
+            canvas->_render_dirty = true;
         }
       }
 
@@ -296,11 +327,7 @@ namespace canvas
       if( placement_factory != _placement_factories.end() )
       {
         Placements& placements = _placements[ node->getIndex() ] =
-          placement_factory->second
-          (
-            node,
-            boost::static_pointer_cast<Canvas>(_self.lock())
-          );
+          placement_factory->second(node, this);
         node->setStringValue
         (
           "status-msg",
@@ -317,11 +344,20 @@ namespace canvas
                                  const EventListener& cb )
   {
     if( !_root_group.get() )
-      throw std::runtime_error("Canvas::AddEventListener: no root group!");
+      throw std::runtime_error("Canvas::addEventListener: no root group!");
 
     return _root_group->addEventListener(type, cb);
   }
 
+  //----------------------------------------------------------------------------
+  bool Canvas::dispatchEvent(const EventPtr& event)
+  {
+    if( !_root_group.get() )
+      throw std::runtime_error("Canvas::dispatchEvent: no root group!");
+
+    return _root_group->dispatchEvent(event);
+  }
+
   //----------------------------------------------------------------------------
   void Canvas::setSizeX(int sx)
   {
@@ -374,6 +410,7 @@ namespace canvas
     if( _view_width == w )
       return;
     _view_width = w;
+    _status |= LAYOUT_DIRTY;
 
     _texture.setViewSize(_view_width, _view_height);
   }
@@ -384,6 +421,7 @@ namespace canvas
     if( _view_height == h )
       return;
     _view_height = h;
+    _status |= LAYOUT_DIRTY;
 
     _texture.setViewSize(_view_width, _view_height);
   }
@@ -409,12 +447,11 @@ namespace canvas
   //----------------------------------------------------------------------------
   bool Canvas::handleMouseEvent(const MouseEventPtr& event)
   {
-    if( !_root_group.get() )
+    if( !_root_group )
       return false;
 
     EventVisitor visitor( EventVisitor::TRAVERSE_DOWN,
                           event->getClientPos(),
-                          event->getDelta(),
                           _root_group );
     if( !_root_group->accept(visitor) )
       return false;
@@ -422,6 +459,13 @@ namespace canvas
     return _event_manager->handleEvent(event, visitor.getPropagationPath());
   }
 
+  //----------------------------------------------------------------------------
+  bool Canvas::propagateEvent( EventPtr const& event,
+                               EventPropagationPath const& path )
+  {
+    return _event_manager->propagateEvent(event, path);
+  }
+
   //----------------------------------------------------------------------------
   void Canvas::childAdded( SGPropertyNode * parent,
                            SGPropertyNode * child )
@@ -453,8 +497,10 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Canvas::valueChanged(SGPropertyNode* node)
   {
-    if(    boost::starts_with(node->getNameString(), "status")
-        || node->getParent()->getNameString() == "bounding-box" )
+    const std::string& name = node->getNameString();
+
+    if(    boost::starts_with(name, "status")
+        || boost::starts_with(name, "data-") )
       return;
     _render_dirty = true;
 
@@ -493,7 +539,7 @@ namespace canvas
     }
     else if( node->getParent() == _node )
     {
-      if( node->getNameString() == "background" )
+      if( name == "background" )
       {
         osg::Vec4 color;
         if( _texture.getCamera() && parseColor(node->getStringValue(), color) )
@@ -502,35 +548,41 @@ namespace canvas
           _render_dirty = true;
         }
       }
-      else if(    node->getNameString() == "mipmapping"
-              || node->getNameString() == "coverage-samples"
-              || node->getNameString() == "color-samples" )
+      else if(   name == "mipmapping"
+              || name == "coverage-samples"
+              || name == "color-samples" )
       {
         _sampling_dirty = true;
       }
-      else if( node->getNameString() == "additive-blend" )
+      else if( name == "additive-blend" )
       {
         _texture.useAdditiveBlend( node->getBoolValue() );
       }
-      else if( node->getNameString() == "render-always" )
+      else if( name == "render-always" )
       {
         _render_always = node->getBoolValue();
       }
-      else if( node->getNameString() == "size" )
+      else if( name == "size" )
       {
         if( node->getIndex() == 0 )
           setSizeX( node->getIntValue() );
         else if( node->getIndex() == 1 )
           setSizeY( node->getIntValue() );
       }
-      else if( node->getNameString() == "view" )
+      else if( name == "update" )
+      {
+        if( _root_group )
+          _root_group->update(0);
+        return update(0);
+      }
+      else if( name == "view" )
       {
         if( node->getIndex() == 0 )
           setViewWidth( node->getIntValue() );
         else if( node->getIndex() == 1 )
           setViewHeight( node->getIntValue() );
       }
-      else if( node->getNameString() == "freeze" )
+      else if( name == "freeze" )
         _texture.setRender( node->getBoolValue() );
       else
         handled = false;
@@ -615,23 +667,6 @@ namespace canvas
     return _system_adapter;
   }
 
-  //----------------------------------------------------------------------------
-  void Canvas::setSelf(const PropertyBasedElementPtr& self)
-  {
-    PropertyBasedElement::setSelf(self);
-
-    CanvasPtr canvas = boost::static_pointer_cast<Canvas>(self);
-
-    _root_group.reset( new Group(canvas, _node) );
-    _root_group->setSelf(_root_group);
-
-    // Remove automatically created property listener as we forward them on our
-    // own
-    _root_group->removeListener();
-
-    _cull_callback = new CullCallback(canvas);
-  }
-
   //----------------------------------------------------------------------------
   void Canvas::setStatusFlags(unsigned int flags, bool set)
   {
@@ -648,7 +683,7 @@ namespace canvas
       _status_msg = "Missing size-y";
     else if( _status & CREATE_FAILED )
       _status_msg = "Creating render target failed";
-    else if( _status == STATUS_DIRTY )
+    else if( _status & STATUS_DIRTY )
       _status_msg = "Creation pending...";
     else
       _status_msg = "Ok";