#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
+class DesktopGroup;
+typedef boost::shared_ptr<DesktopGroup> DesktopPtr;
+typedef boost::weak_ptr<DesktopGroup> DesktopWeakPtr;
+
/**
* Event handler
*/
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;
};
/**
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<DesktopGroup> _cb_mouse_mode;
+ bool _handle_events;
+
+ simgear::PropertyObject<int> _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<canvas::Window>;
+
+ 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]"),
_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");
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<canvas::Window>(name);
- if( name.empty() )
- window->set<std::string>
- (
- "id",
- boost::lexical_cast<std::string>(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() )
{
}
}
-//------------------------------------------------------------------------------
-GUIMgr::ElementFactory GUIMgr::getChildFactory(const std::string& type) const
-{
- if( type == "window" )
- return &Element::create<canvas::Window>;
-
- 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<canvas::Window>(id);
- if( window )
- {
- window->setCanvasContent(canvas);
- placements.push_back(
- simgear::canvas::PlacementPtr(new WindowPlacement(node, window, canvas))
- );
- }
- return placements;
-}
-
/*
RESIZE AREAS
============
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;
_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;
assert(element->getUserData());
canvas::WindowPtr window =
- boost::static_pointer_cast<canvas::Window>
+ boost::dynamic_pointer_cast<canvas::Window>
(
static_cast<sc::Element::OSGUserData*>(element->getUserData())->element
);
- if( !window->isCapturingEvents() || !window->isVisible() )
+ if( !window || !window->isCapturingEvents() || !window->isVisible() )
continue;
float margin = window->isResizable() ? resize_margin_pos : 0;
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;
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;
}
//------------------------------------------------------------------------------
-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;
}
//------------------------------------------------------------------------------
-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<canvas::Window>(name);
+ if( name.empty() )
+ window->set<std::string>
+ (
+ "id",
+ boost::lexical_cast<std::string>(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<canvas::Window>(id);
+ if( window )
+ {
+ window->setCanvasContent(canvas);
+ placements.push_back(
+ simgear::canvas::PlacementPtr(
+ new WindowPlacement(placement, window, canvas)
+ ));
+ }
+ return placements;
+}