]> git.mxchange.org Git - flightgear.git/commitdiff
Canvas GUI: refactor and simplify based on canvas::Group
authorThomas Geymayer <tomgey@gmail.com>
Fri, 14 Jun 2013 18:19:52 +0000 (20:19 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Fri, 14 Jun 2013 18:20:17 +0000 (20:20 +0200)
src/Canvas/gui_mgr.cxx
src/Canvas/gui_mgr.hxx
src/Canvas/window.cxx
src/Canvas/window.hxx

index 77ae16bdeb77aa4aea5e1bc894f6cd159513df73..de9cf2d0b056bc02b267c0e53ffcdd4b735f6bb6 100644 (file)
@@ -34,6 +34,7 @@
 #include <osgGA/GUIEventHandler>
 
 #include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
 
 /**
  * Event handler
@@ -83,8 +84,8 @@ class WindowPlacement:
       canvas::WindowPtr window = _window.lock();
       simgear::canvas::CanvasPtr canvas = _canvas.lock();
 
-      if( window && canvas && canvas == window->getCanvas().lock() )
-        window->setCanvas( simgear::canvas::CanvasPtr() );
+      if( window && canvas && canvas == window->getCanvasContent().lock() )
+        window->setCanvasContent( simgear::canvas::CanvasPtr() );
     }
 
   private:
@@ -92,36 +93,31 @@ class WindowPlacement:
     simgear::canvas::CanvasWeakPtr _canvas;
 };
 
-//------------------------------------------------------------------------------
-typedef boost::shared_ptr<canvas::Window> WindowPtr;
-WindowPtr windowFactory(SGPropertyNode* node)
-{
-  return WindowPtr(new canvas::Window(node));
-}
-
 //------------------------------------------------------------------------------
 GUIMgr::GUIMgr():
-  PropertyBasedMgr( fgGetNode("/sim/gui/canvas", true),
-                    "window",
-                    &windowFactory ),
+  Group(simgear::canvas::CanvasPtr(), fgGetNode("/sim/gui/canvas", true)),
   _event_handler( new GUIEventHandler(this) ),
-  _transform( new osg::MatrixTransform ),
   _cb_mouse_mode( this,
                   &GUIMgr::handleMouseMode,
                   fgGetNode("/devices/status/mice/mouse[0]/mode") ),
   _handle_events(true),
-  _width(_props, "size[0]"),
-  _height(_props, "size[1]"),
+  _width(_node, "size[0]"),
+  _height(_node, "size[1]"),
   _resize(canvas::Window::NONE),
   _last_cursor(MOUSE_CURSOR_NONE),
+  _last_x(-1),
+  _last_y(-1),
   _last_scroll_time(0)
 {
+  // We handle the property listener manually within ::init and ::shutdown.
+  removeListener();
+
   _width = _height = -1;
 
   osg::Camera* camera =
     flightgear::getGUICamera( flightgear::CameraGroup::getDefault() );
   assert(camera);
-  camera->addChild(_transform);
+  camera->addChild( getMatrixTransform() );
 
   simgear::canvas::Canvas::addPlacementFactory
   (
@@ -148,7 +144,14 @@ GUIMgr::GUIMgr():
 //------------------------------------------------------------------------------
 canvas::WindowPtr GUIMgr::createWindow(const std::string& name)
 {
-  return boost::static_pointer_cast<canvas::Window>( createElement(name) );
+  canvas::WindowPtr window = createChild<canvas::Window>(name);
+  if( name.empty() )
+    window->set<std::string>
+    (
+      "id",
+      boost::lexical_cast<std::string>(window->getProps()->getIndex())
+    );
+  return window;
 }
 
 //------------------------------------------------------------------------------
@@ -162,25 +165,32 @@ void GUIMgr::init()
     fgGetInt("/sim/startup/ysize")
   );
 
-  PropertyBasedMgr::init();
-
   globals->get_renderer()
          ->getViewer()
          ->getEventHandlers()
          // GUI is on top of everything so lets install as first event handler
          .push_front( _event_handler );
+
+  _node->addChangeListener(this);
+  _node->fireCreatedRecursive();
 }
 
 //------------------------------------------------------------------------------
 void GUIMgr::shutdown()
 {
-  PropertyBasedMgr::shutdown();
+  _node->removeChangeListener(this);
 
   globals->get_renderer()
          ->getViewer()
          ->removeEventHandler( _event_handler );
 }
 
+//------------------------------------------------------------------------------
+void GUIMgr::update(double dt)
+{
+  Group::update(dt);
+}
+
 //------------------------------------------------------------------------------
 bool GUIMgr::handleEvent(const osgGA::GUIEventAdapter& ea)
 {
@@ -206,35 +216,12 @@ bool GUIMgr::handleEvent(const osgGA::GUIEventAdapter& ea)
 }
 
 //------------------------------------------------------------------------------
-void GUIMgr::elementCreated(simgear::PropertyBasedElementPtr element)
+GUIMgr::ElementFactory GUIMgr::getChildFactory(const std::string& type) const
 {
-  canvas::WindowPtr window =
-    boost::static_pointer_cast<canvas::Window>(element);
-
-  size_t layer_index = std::max(0, window->getProps()->getIntValue("layer", 1));
-  osg::Group *layer = 0;
-
-  if( layer_index < _transform->getNumChildren() )
-  {
-    layer = _transform->getChild(layer_index)->asGroup();
-    assert(layer);
-  }
-  else
-  {
-    while( _transform->getNumChildren() <= layer_index )
-    {
-      layer = new osg::Group;
-      _transform->addChild(layer);
-    }
-  }
+  if( type == "window" )
+    return &Element::create<canvas::Window>;
 
-  layer->addChild(window->getGroup());
-}
-
-//------------------------------------------------------------------------------
-canvas::WindowPtr GUIMgr::getWindow(size_t i)
-{
-  return boost::static_pointer_cast<canvas::Window>(_elements[i]);
+  return Group::getChildFactory(type);
 }
 
 //------------------------------------------------------------------------------
@@ -242,19 +229,13 @@ simgear::canvas::Placements
 GUIMgr::addPlacement( SGPropertyNode* node,
                       simgear::canvas::CanvasPtr canvas )
 {
-  int placement_index = node->getIntValue("index", -1);
+  const std::string& id = node->getStringValue("id");
 
   simgear::canvas::Placements placements;
-  for( size_t i = 0; i < _elements.size(); ++i )
+  canvas::WindowPtr window = getChild<canvas::Window>(id);
+  if( window )
   {
-    if( placement_index >= 0 && static_cast<int>(i) != placement_index )
-      continue;
-
-    canvas::WindowPtr window = getWindow(i);
-    if( !window )
-      continue;
-
-    window->setCanvas(canvas);
+    window->setCanvasContent(canvas);
     placements.push_back(
       simgear::canvas::PlacementPtr(new WindowPlacement(node, window, canvas))
     );
@@ -323,38 +304,28 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
   canvas::WindowPtr window_at_cursor;
   for( int i = _transform->getNumChildren() - 1; i >= 0; --i )
   {
-    osg::Group *layer = _transform->getChild(i)->asGroup();
-    assert(layer);
-    if( !layer->getNumChildren() )
+    osg::Group *element = _transform->getChild(i)->asGroup();
+
+    assert(element);
+    assert(element->getUserData());
+
+    canvas::WindowPtr window =
+      boost::static_pointer_cast<canvas::Window>
+      (
+        static_cast<sc::Element::OSGUserData*>(element->getUserData())->element
+      );
+
+    if( !window->isCapturingEvents() || !window->isVisible() )
       continue;
 
-    for( int j = layer->getNumChildren() - 1; j >= 0; --j )
+    float margin = window->isResizable() ? resize_margin_pos : 0;
+    if( window->getScreenRegion().contains( event->getScreenX(),
+                                            event->getScreenY(),
+                                            margin ) )
     {
-      assert(layer->getChild(j)->getUserData());
-      canvas::WindowPtr window =
-        boost::static_pointer_cast<canvas::Window>
-        (
-          static_cast<sc::Element::OSGUserData*>
-          (
-            layer->getChild(j)->getUserData()
-          )->element
-        );
-
-      if( !window->isCapturingEvents() || !window->isVisible() )
-        continue;
-
-      float margin = window->isResizable() ? resize_margin_pos : 0;
-      if( window->getScreenRegion().contains( event->getScreenX(),
-                                              event->getScreenY(),
-                                              margin ) )
-      {
-        window_at_cursor = window;
-        break;
-      }
-    }
-
-    if( window_at_cursor )
+      window_at_cursor = window;
       break;
+    }
   }
 
   if( window_at_cursor )
@@ -400,7 +371,7 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
       if( ea.getEventType() == osgGA::GUIEventAdapter::PUSH )
       {
         _resize_window = window_at_cursor;
-        window_at_cursor->doRaise();
+        window_at_cursor->raise();
         window_at_cursor->handleResize( _resize | canvas::Window::INIT,
                                         event->delta );
       }
index 408dd62c56ef377804e4bf58dd2ea496ffe81c4c..bc4c17fcbdb2145b3580c7b0bb637f6e8c9281c5 100644 (file)
@@ -22,6 +22,7 @@
 #include "canvas_fwd.hpp"
 
 #include <simgear/canvas/canvas_fwd.hxx>
+#include <simgear/canvas/elements/CanvasGroup.hxx>
 #include <simgear/props/PropertyBasedMgr.hxx>
 #include <simgear/props/propertyObject.hxx>
 
@@ -36,7 +37,8 @@ namespace osgGA
 
 class GUIEventHandler;
 class GUIMgr:
-  public simgear::PropertyBasedMgr
+  public simgear::canvas::Group,
+  public SGSubsystem
 {
   public:
     GUIMgr();
@@ -46,12 +48,15 @@ class GUIMgr:
     virtual void init();
     virtual void shutdown();
 
+    virtual void update(double dt);
+
     bool handleEvent(const osgGA::GUIEventAdapter& ea);
 
   protected:
 
+    typedef simgear::canvas::ElementFactory ElementFactory;
+
     osg::ref_ptr<GUIEventHandler>       _event_handler;
-    osg::ref_ptr<osg::MatrixTransform>  _transform;
     SGPropertyChangeCallback<GUIMgr>    _cb_mouse_mode;
     bool                                _handle_events;
 
@@ -68,9 +73,8 @@ class GUIMgr:
           _last_y;
     double _last_scroll_time;
 
-    virtual void elementCreated(simgear::PropertyBasedElementPtr element);
+    virtual ElementFactory getChildFactory(const std::string& type) const;
 
-    canvas::WindowPtr getWindow(size_t i);
     simgear::canvas::Placements
     addPlacement(SGPropertyNode*, simgear::canvas::CanvasPtr canvas);
 
index 3b5556a19a6cd129a74df9511438ac604cda61bd..b3cae2c1ddcf6b370353b471f8ea0a38b35bb5c7 100644 (file)
@@ -32,8 +32,14 @@ namespace canvas
   namespace sc = simgear::canvas;
 
   //----------------------------------------------------------------------------
-  Window::Window(SGPropertyNode* node):
-    Image(sc::CanvasPtr(), node),
+  const std::string Window::TYPE_NAME = "window";
+
+  //----------------------------------------------------------------------------
+  Window::Window( const simgear::canvas::CanvasWeakPtr& canvas,
+                  const SGPropertyNode_ptr& node,
+                  const Style& parent_style,
+                  Element* parent ):
+    Image(canvas, node, parent_style, parent),
     _attributes_dirty(0),
     _resizable(false),
     _capture_events(true),
@@ -75,9 +81,7 @@ namespace canvas
     {
       handled = true;
       const std::string& name = node->getNameString();
-      if( name == "raise-top" )
-        doRaise(node);
-      else if( name  == "resize" )
+      if( name  == "resize" )
         _resizable = node->getBoolValue();
       else if( name == "update" )
         update(0);
@@ -115,16 +119,16 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  void Window::setCanvas(sc::CanvasPtr canvas)
+  void Window::setCanvasContent(sc::CanvasPtr canvas)
   {
     _canvas_content = canvas;
     setSrcCanvas(canvas);
   }
 
   //----------------------------------------------------------------------------
-  sc::CanvasWeakPtr Window::getCanvas() const
+  sc::CanvasWeakPtr Window::getCanvasContent() const
   {
-    return getSrcCanvas();
+    return _canvas_content;
   }
 
   //----------------------------------------------------------------------------
@@ -145,6 +149,14 @@ namespace canvas
     return _capture_events;
   }
 
+  //----------------------------------------------------------------------------
+  void Window::raise()
+  {
+    // on writing the z-index the window always is moved to the top of all other
+    // windows with the same z-index.
+    set<int>("z-index", get<int>("z-index", 0));
+  }
+
   //----------------------------------------------------------------------------
   void Window::handleResize(uint8_t mode, const osg::Vec2f& delta)
   {
@@ -173,29 +185,6 @@ namespace canvas
       _resize_left += delta.x();
   }
 
-  //----------------------------------------------------------------------------
-  void Window::doRaise(SGPropertyNode* node_raise)
-  {
-    if( node_raise && !node_raise->getBoolValue() )
-      return;
-
-    // Keep a reference to ensure the window is not deleted between removing and
-    // adding it back to the scenegraph
-    osg::ref_ptr<osg::Group> window = getGroup();
-
-    BOOST_FOREACH(osg::Group* parent, getGroup()->getParents())
-    {
-      // Remove window...
-      parent->removeChild(window);
-
-      // ...and add again as topmost window
-      parent->addChild(window);
-    }
-
-    if( node_raise )
-      node_raise->setBoolValue(false);
-  }
-
   //----------------------------------------------------------------------------
   void Window::parseDecorationBorder(const std::string& str)
   {
index 9e47c4884e05cc7b6ee3b8f9ca8ef0357339b818..23c483522cb48694893f8cd81c4e6958c5fd08fd 100644 (file)
@@ -34,6 +34,7 @@ namespace canvas
     public simgear::canvas::Image
   {
     public:
+      static const std::string TYPE_NAME;
 
       enum Resize
       {
@@ -45,7 +46,12 @@ namespace canvas
         INIT    = BOTTOM << 1
       };
 
-      Window(SGPropertyNode* node);
+      typedef simgear::canvas::Style Style;
+
+      Window( const simgear::canvas::CanvasWeakPtr& canvas,
+              const SGPropertyNode_ptr& node,
+              const Style& parent_style = Style(),
+              Element* parent = 0 );
       virtual ~Window();
 
       virtual void update(double delta_time_sec);
@@ -55,17 +61,22 @@ namespace canvas
       const SGVec2<float> getPosition() const;
       const SGRect<float>  getScreenRegion() const;
 
-      void setCanvas(simgear::canvas::CanvasPtr canvas);
-      simgear::canvas::CanvasWeakPtr getCanvas() const;
+      void setCanvasContent(simgear::canvas::CanvasPtr canvas);
+      simgear::canvas::CanvasWeakPtr getCanvasContent() const;
 
       simgear::canvas::CanvasPtr getCanvasDecoration();
 
       bool isResizable() const;
       bool isCapturingEvents() const;
 
-      void handleResize(uint8_t mode, const osg::Vec2f& delta = osg::Vec2f());
+      /**
+       * Moves window on top of all other windows with the same z-index.
+       *
+       * @note If no z-index is set it defaults to 0.
+       */
+      void raise();
 
-      void doRaise(SGPropertyNode* node_raise = 0);
+      void handleResize(uint8_t mode, const osg::Vec2f& delta = osg::Vec2f());
 
     protected: