Canvas: Basic support for window stacking
This commit is contained in:
parent
9c2d01189e
commit
948d87e561
6 changed files with 108 additions and 27 deletions
|
@ -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;
|
||||||
|
|
|
@ -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*,
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -51,6 +51,8 @@ namespace canvas
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Image _image;
|
Image _image;
|
||||||
|
|
||||||
|
void doRaise(SGPropertyNode* node_raise);
|
||||||
};
|
};
|
||||||
} // namespace canvas
|
} // namespace canvas
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue