#include <osgGA/GUIEventHandler>
#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
/**
* Event handler
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:
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
(
//------------------------------------------------------------------------------
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;
}
//------------------------------------------------------------------------------
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)
{
}
//------------------------------------------------------------------------------
-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);
}
//------------------------------------------------------------------------------
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))
);
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 )
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 );
}
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),
{
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);
}
//----------------------------------------------------------------------------
- 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;
}
//----------------------------------------------------------------------------
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)
{
_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)
{
public simgear::canvas::Image
{
public:
+ static const std::string TYPE_NAME;
enum Resize
{
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);
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: