1
0
Fork 0

Canvas: Basic support for window stacking

This commit is contained in:
Thomas Geymayer 2012-08-11 23:35:33 +02:00
parent 9c2d01189e
commit 948d87e561
6 changed files with 108 additions and 27 deletions

View file

@ -83,6 +83,19 @@ class WindowPlacement:
CanvasWeakPtr _canvas; CanvasWeakPtr _canvas;
}; };
/**
* Store pointer to window as user data
*/
class WindowUserData:
public osg::Referenced
{
public:
canvas::WindowPtr window;
WindowUserData(canvas::WindowPtr window):
window(window)
{}
};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
typedef boost::shared_ptr<canvas::Window> WindowPtr; typedef boost::shared_ptr<canvas::Window> WindowPtr;
WindowPtr windowFactory(SGPropertyNode* node) WindowPtr windowFactory(SGPropertyNode* node)
@ -96,8 +109,7 @@ GUIMgr::GUIMgr():
_event_handler( new GUIEventHandler(this) ), _event_handler( new GUIEventHandler(this) ),
_transform( new osg::MatrixTransform ), _transform( new osg::MatrixTransform ),
_width(_props, "size[0]"), _width(_props, "size[0]"),
_height(_props, "size[1]"), _height(_props, "size[1]")
_last_push(-1)
{ {
_width = _height = -1; _width = _height = -1;
@ -154,10 +166,27 @@ void GUIMgr::shutdown()
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void GUIMgr::elementCreated(PropertyBasedElementPtr element) void GUIMgr::elementCreated(PropertyBasedElementPtr element)
{ {
_transform->addChild canvas::WindowPtr window =
( boost::static_pointer_cast<canvas::Window>(element);
static_cast<canvas::Window*>(element.get())->getGroup()
); 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);
}
}
window->getGroup()->setUserData(new WindowUserData(window));
layer->addChild(window->getGroup());
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -220,6 +249,9 @@ canvas::Placements GUIMgr::addPlacement( const SGPropertyNode* node,
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea) bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
{ {
if( !_transform->getNumChildren() )
return false;
canvas::MouseEvent event( ea.getEventType() ); canvas::MouseEvent event( ea.getEventType() );
event.x = 0.5 * (ea.getXnormalized() + 1) * _width + 0.5; event.x = 0.5 * (ea.getXnormalized() + 1) * _width + 0.5;
@ -233,18 +265,31 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
event.mod = ea.getModKeyMask(); event.mod = ea.getModKeyMask();
event.scroll = ea.getScrollingMotion(); event.scroll = ea.getScrollingMotion();
int window_at_cursor = -1; canvas::WindowPtr window_at_cursor;
for( size_t i = 0; i < _elements.size(); ++i ) for( int i = _transform->getNumChildren() - 1; i >= 0; --i )
{ {
if( _elements[i] osg::Group *layer = _transform->getChild(i)->asGroup();
&& getWindow(i)->getRegion().contains(event.x, event.y) ) assert(layer);
if( !layer->getNumChildren() )
continue;
for( int j = layer->getNumChildren() - 1; j >= 0; --j )
{ {
window_at_cursor = i; assert(layer->getChild(j)->getUserData());
break; canvas::WindowPtr window =
static_cast<WindowUserData*>(layer->getChild(j)->getUserData())->window;
if( window->getRegion().contains(event.x, event.y) )
{
window_at_cursor = window;
break;
}
} }
if( window_at_cursor )
break;
} }
int target_window = window_at_cursor; canvas::WindowPtr target_window = window_at_cursor;
switch( ea.getEventType() ) switch( ea.getEventType() )
{ {
case osgGA::GUIEventAdapter::PUSH: case osgGA::GUIEventAdapter::PUSH:
@ -255,25 +300,23 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
break; break;
case osgGA::GUIEventAdapter::RELEASE: case osgGA::GUIEventAdapter::RELEASE:
if( _last_push < 0 ) if( !_last_push.expired() )
return false; return false;
target_window = _last_push; target_window = _last_push.lock();
_last_push = -1; _last_push.reset();
break; break;
case osgGA::GUIEventAdapter::DRAG: case osgGA::GUIEventAdapter::DRAG:
target_window = _last_push; target_window = _last_push.lock();
break; break;
default: default:
return false; return false;
} }
if( target_window >= 0 ) if( target_window )
{ {
canvas::WindowPtr window = getWindow(target_window);
event.dx = event.x - _last_x; event.dx = event.x - _last_x;
event.dy = event.y - _last_y; event.dy = event.y - _last_y;
@ -281,10 +324,10 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
_last_y = event.y; _last_y = event.y;
// Let the event position be always relative to the top left window corner // Let the event position be always relative to the top left window corner
event.x -= window->getRegion().x(); event.x -= target_window->getRegion().x();
event.y -= window->getRegion().y(); event.y -= target_window->getRegion().y();
return window->handleMouseEvent(event); return target_window->handleMouseEvent(event);
} }
else else
return false; return false;

View file

@ -55,9 +55,9 @@ class GUIMgr:
simgear::PropertyObject<int> _width, simgear::PropertyObject<int> _width,
_height; _height;
int _last_push, canvas::WindowWeakPtr _last_push;
_last_x, float _last_x,
_last_y; _last_y;
canvas::WindowPtr getWindow(size_t i); canvas::WindowPtr getWindow(size_t i);
canvas::Placements addPlacement( const SGPropertyNode*, canvas::Placements addPlacement( const SGPropertyNode*,

View file

@ -30,3 +30,15 @@ PropertyBasedElement::~PropertyBasedElement()
{ {
_node->removeChangeListener(this); _node->removeChangeListener(this);
} }
//------------------------------------------------------------------------------
SGConstPropertyNode_ptr PropertyBasedElement::getProps() const
{
return _node;
}
//------------------------------------------------------------------------------
SGPropertyNode_ptr PropertyBasedElement::getProps()
{
return _node;
}

View file

@ -34,6 +34,9 @@ class PropertyBasedElement:
virtual void update(double delta_time_sec) = 0; virtual void update(double delta_time_sec) = 0;
SGConstPropertyNode_ptr getProps() const;
SGPropertyNode_ptr getProps();
protected: protected:
friend class PropertyBasedMgr; friend class PropertyBasedMgr;

View file

@ -59,7 +59,10 @@ namespace canvas
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void Window::valueChanged(SGPropertyNode * node) void Window::valueChanged(SGPropertyNode * node)
{ {
_image.valueChanged(node); if( node->getParent() == _node && node->getNameString() == "raise-top" )
doRaise(node);
else
_image.valueChanged(node);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -95,4 +98,22 @@ namespace canvas
return false; return false;
} }
//----------------------------------------------------------------------------
void Window::doRaise(SGPropertyNode* node_raise)
{
if( !node_raise->getBoolValue() )
return;
BOOST_FOREACH(osg::Group* parent, getGroup()->getParents())
{
// Remove window...
parent->removeChild(getGroup());
// ...and add again as topmost window
parent->addChild(getGroup());
}
node_raise->setBoolValue(false);
}
} // namespace canvas } // namespace canvas

View file

@ -51,6 +51,8 @@ namespace canvas
protected: protected:
Image _image; Image _image;
void doRaise(SGPropertyNode* node_raise);
}; };
} // namespace canvas } // namespace canvas