1
0
Fork 0

Canvas GUI: refactor and simplify based on canvas::Group

This commit is contained in:
Thomas Geymayer 2013-06-14 20:19:52 +02:00
parent acddd0b0cf
commit 4f129a283b
4 changed files with 101 additions and 126 deletions

View file

@ -34,6 +34,7 @@
#include <osgGA/GUIEventHandler>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
/**
* 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<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
(
@ -148,7 +144,14 @@ GUIMgr::GUIMgr():
//------------------------------------------------------------------------------
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;
}
//------------------------------------------------------------------------------
@ -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<canvas::Window>(element);
if( type == "window" )
return &Element::create<canvas::Window>;
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);
}
}
layer->addChild(window->getGroup());
}
//------------------------------------------------------------------------------
canvas::WindowPtr GUIMgr::getWindow(size_t i)
{
return boost::static_pointer_cast<canvas::Window>(_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<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))
);
@ -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<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 )
@ -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 );
}

View file

@ -22,6 +22,7 @@
#include "canvas_fwd.hpp"
#include <simgear/canvas/canvas_fwd.hxx>
#include <simgear/canvas/elements/CanvasGroup.hxx>
#include <simgear/props/PropertyBasedMgr.hxx>
#include <simgear/props/propertyObject.hxx>
@ -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<GUIEventHandler> _event_handler;
osg::ref_ptr<osg::MatrixTransform> _transform;
SGPropertyChangeCallback<GUIMgr> _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);

View file

@ -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<int>("z-index", get<int>("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<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)
{

View file

@ -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<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: