Canvas: clear event listeners on destroy
Removing all event listeneres on destroying a canvas prevents circular references due to Nasal event listeners keeping a reference to the canvas in their closure. Also fix event handling with direct children of the root group and add some more helpers to the Canvas.
This commit is contained in:
parent
c3af88dfc1
commit
7fe16d99be
@ -114,6 +114,9 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
void Canvas::destroy()
|
||||
{
|
||||
if( _root_group )
|
||||
_root_group->clearEventListener();
|
||||
|
||||
// TODO check if really not in use anymore
|
||||
getProps()->getParent()
|
||||
->removeChild( getProps()->getName(),
|
||||
@ -185,6 +188,16 @@ namespace canvas
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
GroupPtr Canvas::getOrCreateGroup(const std::string& name)
|
||||
{
|
||||
GroupPtr group = getGroup(name);
|
||||
if( group )
|
||||
return group;
|
||||
|
||||
return createGroup(name);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
GroupPtr Canvas::getRootGroup()
|
||||
{
|
||||
|
@ -102,8 +102,25 @@ namespace canvas
|
||||
void removeParentCanvas(const CanvasWeakPtr& canvas);
|
||||
void removeChildCanvas(const CanvasWeakPtr& canvas);
|
||||
|
||||
/**
|
||||
* Create a new group
|
||||
*/
|
||||
GroupPtr createGroup(const std::string& name = "");
|
||||
|
||||
/**
|
||||
* Get an existing group with the given name
|
||||
*/
|
||||
GroupPtr getGroup(const std::string& name);
|
||||
|
||||
/**
|
||||
* Get an existing group with the given name or otherwise create a new
|
||||
* group
|
||||
*/
|
||||
GroupPtr getOrCreateGroup(const std::string& name);
|
||||
|
||||
/**
|
||||
* Get the root group of the canvas
|
||||
*/
|
||||
GroupPtr getRootGroup();
|
||||
|
||||
/**
|
||||
|
@ -188,13 +188,12 @@ namespace canvas
|
||||
// http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
|
||||
|
||||
// Capturing phase
|
||||
// for( EventTargets::iterator it = _target_path.begin();
|
||||
// it != _target_path.end();
|
||||
// ++it )
|
||||
// for( EventPropagationPath::const_iterator it = path.begin();
|
||||
// it != path.end();
|
||||
// ++it )
|
||||
// {
|
||||
// if( it->element )
|
||||
// std::cout << it->element->getProps()->getPath() << " "
|
||||
// << "(" << it->local_pos.x() << "|" << it->local_pos.y() << ")\n";
|
||||
// if( !it->element.expired() )
|
||||
// std::cout << it->element.lock()->getProps()->getPath() << std::endl;
|
||||
// }
|
||||
|
||||
// Bubbling phase
|
||||
|
@ -73,7 +73,7 @@ namespace canvas
|
||||
// Don't check collision with root element (2nd element in _target_path)
|
||||
// do event listeners attached to the canvas itself (its root group)
|
||||
// always get called even if no element has been hit.
|
||||
if( _target_path.size() > 2 && !el.hitBound(pos, local_pos) )
|
||||
if( _target_path.size() > 1 && !el.hitBound(pos, local_pos) )
|
||||
return false;
|
||||
|
||||
const osg::Vec2f& delta = _target_path.back().local_delta;
|
||||
|
@ -179,6 +179,12 @@ namespace canvas
|
||||
return naNil();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::clearEventListener()
|
||||
{
|
||||
_listener.clear();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Element::accept(EventVisitor& visitor)
|
||||
{
|
||||
@ -220,15 +226,10 @@ namespace canvas
|
||||
|
||||
// Drawables have a bounding box...
|
||||
if( _drawable )
|
||||
{
|
||||
if( !_drawable->getBound().contains(osg::Vec3f(local_pos, 0)) )
|
||||
return false;
|
||||
}
|
||||
return _drawable->getBound().contains(osg::Vec3f(local_pos, 0));
|
||||
// ... for other elements, i.e. groups only a bounding sphere is available
|
||||
else if( !_transform->getBound().contains(osg::Vec3f(pos, 0)) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
else
|
||||
return _transform->getBound().contains(osg::Vec3f(pos, 0));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -85,6 +85,7 @@ namespace canvas
|
||||
virtual void update(double dt);
|
||||
|
||||
naRef addEventListener(const nasal::CallContext& ctx);
|
||||
virtual void clearEventListener();
|
||||
|
||||
virtual bool accept(EventVisitor& visitor);
|
||||
virtual bool ascend(EventVisitor& visitor);
|
||||
|
@ -133,6 +133,15 @@ namespace canvas
|
||||
return ElementPtr();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Group::clearEventListener()
|
||||
{
|
||||
BOOST_FOREACH( ChildList::value_type child, _children )
|
||||
child.second->clearEventListener();
|
||||
|
||||
Element::clearEventListener();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Group::update(double dt)
|
||||
{
|
||||
|
@ -57,6 +57,8 @@ namespace canvas
|
||||
*/
|
||||
ElementPtr getElementById(const std::string& id);
|
||||
|
||||
virtual void clearEventListener();
|
||||
|
||||
virtual void update(double dt);
|
||||
|
||||
virtual bool traverse(EventVisitor& visitor);
|
||||
|
Loading…
Reference in New Issue
Block a user