X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FCanvas%2Fgui_mgr.cxx;h=453893886ba6ca100590fb8b7135c330242ab758;hb=b0dcb657e77579ecc79798ff365737095f96f9e2;hp=de9cf2d0b056bc02b267c0e53ffcdd4b735f6bb6;hpb=4f129a283b1a37493fb0ddc3ff35d41f1908be06;p=flightgear.git diff --git a/src/Canvas/gui_mgr.cxx b/src/Canvas/gui_mgr.cxx index de9cf2d0b..453893886 100644 --- a/src/Canvas/gui_mgr.cxx +++ b/src/Canvas/gui_mgr.cxx @@ -36,6 +36,10 @@ #include #include +class DesktopGroup; +typedef boost::shared_ptr DesktopPtr; +typedef boost::weak_ptr DesktopWeakPtr; + /** * Event handler */ @@ -43,22 +47,15 @@ class GUIEventHandler: public osgGA::GUIEventHandler { public: - GUIEventHandler(GUIMgr* gui_mgr): - _gui_mgr( gui_mgr ) - {} + GUIEventHandler(const DesktopWeakPtr& desktop_group); bool handle( const osgGA::GUIEventAdapter& ea, - osgGA::GUIActionAdapter& aa, + osgGA::GUIActionAdapter&, osg::Object*, - osg::NodeVisitor* ) - { - if( ea.getHandled() ) - return false; - return _gui_mgr->handleEvent(ea); - } + osg::NodeVisitor* ); protected: - GUIMgr *_gui_mgr; + DesktopWeakPtr _desktop; }; /** @@ -93,12 +90,79 @@ class WindowPlacement: simgear::canvas::CanvasWeakPtr _canvas; }; +/** + * Desktop root group + */ +class DesktopGroup: + public simgear::canvas::Group +{ + public: + DesktopGroup(); + bool handleEvent(const osgGA::GUIEventAdapter& ea); + + protected: + + friend class GUIMgr; + + SGPropertyChangeCallback _cb_mouse_mode; + bool _handle_events; + + simgear::PropertyObject _width, + _height; + + canvas::WindowWeakPtr _last_push, + _last_mouse_over, + _resize_window; + uint8_t _resize; + int _last_cursor; + + osg::Vec2 _drag_start; + float _last_x, + _last_y; + double _last_scroll_time; + + bool handleMouse(const osgGA::GUIEventAdapter& ea); + void handleResize(int x, int y, int width, int height); + void handleMouseMode(SGPropertyNode* node); + + /** + * + */ + simgear::canvas::ElementFactory + getChildFactory(const std::string& type) const + { + if( type == "window" ) + return &Element::create; + + return Group::getChildFactory(type); + } +}; + +//------------------------------------------------------------------------------ +GUIEventHandler::GUIEventHandler(const DesktopWeakPtr& desktop_group): + _desktop( desktop_group ) +{ + +} + +//------------------------------------------------------------------------------ +bool GUIEventHandler::handle( const osgGA::GUIEventAdapter& ea, + osgGA::GUIActionAdapter&, + osg::Object*, + osg::NodeVisitor* ) +{ + if( ea.getHandled() ) + return false; + + DesktopPtr desktop = _desktop.lock(); + return desktop && desktop->handleEvent(ea); +} + //------------------------------------------------------------------------------ -GUIMgr::GUIMgr(): +DesktopGroup::DesktopGroup(): Group(simgear::canvas::CanvasPtr(), fgGetNode("/sim/gui/canvas", true)), - _event_handler( new GUIEventHandler(this) ), _cb_mouse_mode( this, - &GUIMgr::handleMouseMode, + &DesktopGroup::handleMouseMode, fgGetNode("/devices/status/mice/mouse[0]/mode") ), _handle_events(true), _width(_node, "size[0]"), @@ -109,22 +173,11 @@ GUIMgr::GUIMgr(): _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( getMatrixTransform() ); - simgear::canvas::Canvas::addPlacementFactory - ( - "window", - boost::bind(&GUIMgr::addPlacement, this, _1, _2) - ); - osg::StateSet* stateSet = _transform->getOrCreateStateSet(); stateSet->setDataVariance(osg::Object::STATIC); stateSet->setRenderBinDetails(1000, "RenderBin"); @@ -139,60 +192,20 @@ GUIMgr::GUIMgr(): stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); stateSet->setMode(GL_FOG, osg::StateAttribute::OFF); stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); -} - -//------------------------------------------------------------------------------ -canvas::WindowPtr GUIMgr::createWindow(const std::string& name) -{ - canvas::WindowPtr window = createChild(name); - if( name.empty() ) - window->set - ( - "id", - boost::lexical_cast(window->getProps()->getIndex()) - ); - return window; -} - -//------------------------------------------------------------------------------ -void GUIMgr::init() -{ - handleResize - ( - 0, - 0, - fgGetInt("/sim/startup/xsize"), - fgGetInt("/sim/startup/ysize") - ); - 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(); -} + _width = _height = -1; -//------------------------------------------------------------------------------ -void GUIMgr::shutdown() -{ - _node->removeChangeListener(this); + // Do not change values on reinit + _width.node()->setAttribute(SGPropertyNode::PRESERVE, true); + _height.node()->setAttribute(SGPropertyNode::PRESERVE, true); - globals->get_renderer() - ->getViewer() - ->removeEventHandler( _event_handler ); + // Do not restore windows on reinit (all windows will need to be recreated, + // but hey it's a reset ;-)) + _node->setAttribute(SGPropertyNode::PRESERVE, true); } //------------------------------------------------------------------------------ -void GUIMgr::update(double dt) -{ - Group::update(dt); -} - -//------------------------------------------------------------------------------ -bool GUIMgr::handleEvent(const osgGA::GUIEventAdapter& ea) +bool DesktopGroup::handleEvent(const osgGA::GUIEventAdapter& ea) { switch( ea.getEventType() ) { @@ -215,34 +228,6 @@ bool GUIMgr::handleEvent(const osgGA::GUIEventAdapter& ea) } } -//------------------------------------------------------------------------------ -GUIMgr::ElementFactory GUIMgr::getChildFactory(const std::string& type) const -{ - if( type == "window" ) - return &Element::create; - - return Group::getChildFactory(type); -} - -//------------------------------------------------------------------------------ -simgear::canvas::Placements -GUIMgr::addPlacement( SGPropertyNode* node, - simgear::canvas::CanvasPtr canvas ) -{ - const std::string& id = node->getStringValue("id"); - - simgear::canvas::Placements placements; - canvas::WindowPtr window = getChild(id); - if( window ) - { - window->setCanvasContent(canvas); - placements.push_back( - simgear::canvas::PlacementPtr(new WindowPlacement(node, window, canvas)) - ); - } - return placements; -} - /* RESIZE AREAS ============ @@ -263,7 +248,7 @@ const float resize_margin_neg = 2; const float resize_corner = 20; //------------------------------------------------------------------------------ -bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea) +bool DesktopGroup::handleMouse(const osgGA::GUIEventAdapter& ea) { if( !_transform->getNumChildren() || !_handle_events ) return false; @@ -294,7 +279,8 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea) _resize_window.reset(); break; case osgGA::GUIEventAdapter::DRAG: - _resize_window.lock()->handleResize(_resize, event->delta); + _resize_window.lock()->handleResize( _resize, + event->screen_pos - _drag_start ); return true; default: return false; @@ -310,12 +296,12 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea) assert(element->getUserData()); canvas::WindowPtr window = - boost::static_pointer_cast + boost::dynamic_pointer_cast ( static_cast(element->getUserData())->element ); - if( !window->isCapturingEvents() || !window->isVisible() ) + if( !window || !window->isCapturingEvents() || !window->isVisible() ) continue; float margin = window->isResizable() ? resize_margin_pos : 0; @@ -371,9 +357,10 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea) if( ea.getEventType() == osgGA::GUIEventAdapter::PUSH ) { _resize_window = window_at_cursor; + _drag_start = event->screen_pos; + window_at_cursor->raise(); - window_at_cursor->handleResize( _resize | canvas::Window::INIT, - event->delta ); + window_at_cursor->handleResize(_resize | canvas::Window::INIT); } return true; @@ -433,11 +420,24 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea) break; } case osgGA::GUIEventAdapter::RELEASE: - target_window = _last_push.lock(); - _last_push.reset(); + { event->type = sc::Event::MOUSE_UP; - break; + canvas::WindowPtr last_push = _last_push.lock(); + _last_push.reset(); + + if( last_push && last_push != target_window ) + { + // Leave old window + sc::MouseEventPtr leave_event( new sc::MouseEvent(*event) ); + leave_event->type = sc::Event::MOUSE_LEAVE; + leave_event->client_pos -= toOsg(last_push->getPosition()); + leave_event->local_pos = leave_event->client_pos; + + last_push->handleEvent(leave_event); + } + break; + } case osgGA::GUIEventAdapter::DRAG: target_window = _last_push.lock(); event->type = sc::Event::DRAG; @@ -458,7 +458,7 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea) } //------------------------------------------------------------------------------ -void GUIMgr::handleResize(int x, int y, int width, int height) +void DesktopGroup::handleResize(int x, int y, int width, int height) { if( _width == width && _height == height ) return; @@ -476,9 +476,102 @@ void GUIMgr::handleResize(int x, int y, int width, int height) } //------------------------------------------------------------------------------ -void GUIMgr::handleMouseMode(SGPropertyNode* node) +void DesktopGroup::handleMouseMode(SGPropertyNode* node) { // pass-through indicates events should pass through to the UI _handle_events = fgGetNode("/input/mice/mouse[0]/mode", node->getIntValue()) ->getBoolValue("pass-through"); } + +//------------------------------------------------------------------------------ +GUIMgr::GUIMgr() +{ + +} + +//------------------------------------------------------------------------------ +canvas::WindowPtr GUIMgr::createWindow(const std::string& name) +{ + canvas::WindowPtr window = _desktop->createChild(name); + if( name.empty() ) + window->set + ( + "id", + boost::lexical_cast(window->getProps()->getIndex()) + ); + return window; +} + +//------------------------------------------------------------------------------ +void GUIMgr::init() +{ + DesktopPtr desktop( new DesktopGroup ); + desktop->handleResize + ( + 0, + 0, + fgGetInt("/sim/startup/xsize"), + fgGetInt("/sim/startup/ysize") + ); + _desktop = desktop; + + _event_handler = new GUIEventHandler(desktop); + globals->get_renderer() + ->getViewer() + ->getEventHandlers() + // GUI is on top of everything so lets install as first event handler + .push_front( _event_handler ); + + simgear::canvas::Canvas::addPlacementFactory + ( + "window", + boost::bind(&GUIMgr::addWindowPlacement, this, _1, _2) + ); + + _desktop->getProps()->fireCreatedRecursive(); +} + +//------------------------------------------------------------------------------ +void GUIMgr::shutdown() +{ + _desktop->destroy(); + _desktop.reset(); + simgear::canvas::Canvas::removePlacementFactory("window"); + + globals->get_renderer() + ->getViewer() + ->removeEventHandler( _event_handler ); + _event_handler = 0; +} + +//------------------------------------------------------------------------------ +void GUIMgr::update(double dt) +{ + _desktop->update(dt); +} + +//------------------------------------------------------------------------------ +simgear::canvas::GroupPtr GUIMgr::getDesktop() +{ + return _desktop; +} + +//------------------------------------------------------------------------------ +simgear::canvas::Placements +GUIMgr::addWindowPlacement( SGPropertyNode* placement, + simgear::canvas::CanvasPtr canvas ) +{ + const std::string& id = placement->getStringValue("id"); + + simgear::canvas::Placements placements; + canvas::WindowPtr window = _desktop->getChild(id); + if( window ) + { + window->setCanvasContent(canvas); + placements.push_back( + simgear::canvas::PlacementPtr( + new WindowPlacement(placement, window, canvas) + )); + } + return placements; +}