From 4f129a283b1a37493fb0ddc3ff35d41f1908be06 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Fri, 14 Jun 2013 20:19:52 +0200 Subject: [PATCH] Canvas GUI: refactor and simplify based on canvas::Group --- src/Canvas/gui_mgr.cxx | 143 ++++++++++++++++------------------------- src/Canvas/gui_mgr.hxx | 12 ++-- src/Canvas/window.cxx | 51 ++++++--------- src/Canvas/window.hxx | 21 ++++-- 4 files changed, 101 insertions(+), 126 deletions(-) diff --git a/src/Canvas/gui_mgr.cxx b/src/Canvas/gui_mgr.cxx index 77ae16bde..de9cf2d0b 100644 --- a/src/Canvas/gui_mgr.cxx +++ b/src/Canvas/gui_mgr.cxx @@ -34,6 +34,7 @@ #include #include +#include /** * 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 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( createElement(name) ); + canvas::WindowPtr window = createChild(name); + if( name.empty() ) + window->set + ( + "id", + boost::lexical_cast(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(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; - layer->addChild(window->getGroup()); -} - -//------------------------------------------------------------------------------ -canvas::WindowPtr GUIMgr::getWindow(size_t i) -{ - return boost::static_pointer_cast(_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(id); + if( window ) { - if( placement_index >= 0 && static_cast(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 + ( + static_cast(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 - ( - static_cast - ( - 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 ); } diff --git a/src/Canvas/gui_mgr.hxx b/src/Canvas/gui_mgr.hxx index 408dd62c5..bc4c17fcb 100644 --- a/src/Canvas/gui_mgr.hxx +++ b/src/Canvas/gui_mgr.hxx @@ -22,6 +22,7 @@ #include "canvas_fwd.hpp" #include +#include #include #include @@ -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 _event_handler; - osg::ref_ptr _transform; SGPropertyChangeCallback _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); diff --git a/src/Canvas/window.cxx b/src/Canvas/window.cxx index 3b5556a19..b3cae2c1d 100644 --- a/src/Canvas/window.cxx +++ b/src/Canvas/window.cxx @@ -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("z-index", get("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 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) { diff --git a/src/Canvas/window.hxx b/src/Canvas/window.hxx index 9e47c4884..23c483522 100644 --- a/src/Canvas/window.hxx +++ b/src/Canvas/window.hxx @@ -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 getPosition() const; const SGRect 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: -- 2.39.5