]> git.mxchange.org Git - flightgear.git/commitdiff
Canvas: Basic support for window stacking
authorThomas Geymayer <tomgey@gmail.com>
Sat, 11 Aug 2012 21:35:33 +0000 (23:35 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Sat, 11 Aug 2012 21:38:04 +0000 (23:38 +0200)
src/Canvas/gui_mgr.cxx
src/Canvas/gui_mgr.hxx
src/Canvas/property_based_element.cxx
src/Canvas/property_based_element.hxx
src/Canvas/window.cxx
src/Canvas/window.hxx

index 7d581e6c91ee1b96d21e1037604c39e4a421f055..4fa66febd24830533b1c932d5a0145f1b2c5edad 100644 (file)
@@ -83,6 +83,19 @@ class WindowPlacement:
     CanvasWeakPtr _canvas;
 };
 
+/**
+ * Store pointer to window as user data
+ */
+class WindowUserData:
+  public osg::Referenced
+{
+  public:
+    canvas::WindowPtr window;
+    WindowUserData(canvas::WindowPtr window):
+      window(window)
+    {}
+};
+
 //------------------------------------------------------------------------------
 typedef boost::shared_ptr<canvas::Window> WindowPtr;
 WindowPtr windowFactory(SGPropertyNode* node)
@@ -96,8 +109,7 @@ GUIMgr::GUIMgr():
   _event_handler( new GUIEventHandler(this) ),
   _transform( new osg::MatrixTransform ),
   _width(_props, "size[0]"),
-  _height(_props, "size[1]"),
-  _last_push(-1)
+  _height(_props, "size[1]")
 {
   _width = _height = -1;
 
@@ -154,10 +166,27 @@ void GUIMgr::shutdown()
 //------------------------------------------------------------------------------
 void GUIMgr::elementCreated(PropertyBasedElementPtr element)
 {
-  _transform->addChild
-  (
-    static_cast<canvas::Window*>(element.get())->getGroup()
-  );
+  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);
+    }
+  }
+  window->getGroup()->setUserData(new WindowUserData(window));
+  layer->addChild(window->getGroup());
 }
 
 //------------------------------------------------------------------------------
@@ -220,6 +249,9 @@ canvas::Placements GUIMgr::addPlacement( const SGPropertyNode* node,
 //------------------------------------------------------------------------------
 bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
 {
+  if( !_transform->getNumChildren() )
+    return false;
+
   canvas::MouseEvent event( ea.getEventType() );
 
   event.x = 0.5 * (ea.getXnormalized() + 1) * _width + 0.5;
@@ -233,18 +265,31 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
   event.mod = ea.getModKeyMask();
   event.scroll = ea.getScrollingMotion();
 
-  int window_at_cursor = -1;
-  for( size_t i = 0; i < _elements.size(); ++i )
+  canvas::WindowPtr window_at_cursor;
+  for( int i = _transform->getNumChildren() - 1; i >= 0; --i )
   {
-    if(    _elements[i]
-        && getWindow(i)->getRegion().contains(event.x, event.y) )
+    osg::Group *layer = _transform->getChild(i)->asGroup();
+    assert(layer);
+    if( !layer->getNumChildren() )
+      continue;
+
+    for( int j = layer->getNumChildren() - 1; j >= 0; --j )
     {
-      window_at_cursor = i;
-      break;
+      assert(layer->getChild(j)->getUserData());
+      canvas::WindowPtr window =
+        static_cast<WindowUserData*>(layer->getChild(j)->getUserData())->window;
+      if( window->getRegion().contains(event.x, event.y) )
+      {
+        window_at_cursor = window;
+        break;
+      }
     }
+
+    if( window_at_cursor )
+      break;
   }
 
-  int target_window = window_at_cursor;
+  canvas::WindowPtr target_window = window_at_cursor;
   switch( ea.getEventType() )
   {
     case osgGA::GUIEventAdapter::PUSH:
@@ -255,25 +300,23 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
       break;
 
     case osgGA::GUIEventAdapter::RELEASE:
-      if( _last_push < 0 )
+      if( !_last_push.expired() )
         return false;
 
-      target_window = _last_push;
-      _last_push = -1;
+      target_window = _last_push.lock();
+      _last_push.reset();
       break;
 
     case osgGA::GUIEventAdapter::DRAG:
-      target_window = _last_push;
+      target_window = _last_push.lock();
       break;
 
     default:
       return false;
   }
 
-  if( target_window >= 0 )
+  if( target_window )
   {
-    canvas::WindowPtr window = getWindow(target_window);
-
     event.dx = event.x - _last_x;
     event.dy = event.y - _last_y;
 
@@ -281,10 +324,10 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
     _last_y = event.y;
 
     // Let the event position be always relative to the top left window corner
-    event.x -= window->getRegion().x();
-    event.y -= window->getRegion().y();
+    event.x -= target_window->getRegion().x();
+    event.y -= target_window->getRegion().y();
 
-    return window->handleMouseEvent(event);
+    return target_window->handleMouseEvent(event);
   }
   else
     return false;
index 76722ec7dc4b2709831faf80a6e9e98bdacc209a..8a1ccf786e405aa8874037d14b79e400c4ce1457 100644 (file)
@@ -55,9 +55,9 @@ class GUIMgr:
     simgear::PropertyObject<int>        _width,
                                         _height;
 
-    int _last_push,
-        _last_x,
-        _last_y;
+    canvas::WindowWeakPtr _last_push;
+    float _last_x,
+          _last_y;
 
     canvas::WindowPtr getWindow(size_t i);
     canvas::Placements addPlacement( const SGPropertyNode*,
index 3b801a7c1a5e5e8acbd45d744b46278bb368f055..8672539c026829f988ea819b66e7ea136690c1c6 100644 (file)
@@ -30,3 +30,15 @@ PropertyBasedElement::~PropertyBasedElement()
 {
   _node->removeChangeListener(this);
 }
+
+//------------------------------------------------------------------------------
+SGConstPropertyNode_ptr PropertyBasedElement::getProps() const
+{
+  return _node;
+}
+
+//------------------------------------------------------------------------------
+SGPropertyNode_ptr PropertyBasedElement::getProps()
+{
+  return _node;
+}
index 358ae7d0c43003e5ae5f2890265bf4c65fd02a1c..a41914df97e24e4b033576957133a09793168c75 100644 (file)
@@ -34,6 +34,9 @@ class PropertyBasedElement:
 
     virtual void update(double delta_time_sec) = 0;
 
+    SGConstPropertyNode_ptr getProps() const;
+    SGPropertyNode_ptr getProps();
+
   protected:
 
     friend class PropertyBasedMgr;
index 43c9a1654b764942c445792c64d619375831c43f..e6db4c30adef56af61625f5102d045a8273cabb0 100644 (file)
@@ -59,7 +59,10 @@ namespace canvas
   //----------------------------------------------------------------------------
   void Window::valueChanged(SGPropertyNode * node)
   {
-    _image.valueChanged(node);
+    if( node->getParent() == _node && node->getNameString() == "raise-top" )
+      doRaise(node);
+    else
+      _image.valueChanged(node);
   }
 
   //----------------------------------------------------------------------------
@@ -95,4 +98,22 @@ namespace canvas
       return false;
   }
 
+  //----------------------------------------------------------------------------
+  void Window::doRaise(SGPropertyNode* node_raise)
+  {
+    if( !node_raise->getBoolValue() )
+      return;
+
+    BOOST_FOREACH(osg::Group* parent, getGroup()->getParents())
+    {
+      // Remove window...
+      parent->removeChild(getGroup());
+
+      // ...and add again as topmost window
+      parent->addChild(getGroup());
+    }
+
+    node_raise->setBoolValue(false);
+  }
+
 } // namespace canvas
index 3a94f4c8e1dacf5b01a6d2e14c05c134f73809fd..cce5b1aa9c96792a1a8a437379bd51ba1035b2e2 100644 (file)
@@ -51,6 +51,8 @@ namespace canvas
     protected:
 
       Image _image;
+
+      void doRaise(SGPropertyNode* node_raise);
   };
 } // namespace canvas