//----------------------------------------------------------------------------
EventVisitor::EventVisitor( TraverseMode mode,
const osg::Vec2f& pos,
- const osg::Vec2f& delta ):
- _traverse_mode( mode )
+ const osg::Vec2f& delta,
+ const ElementPtr& root ):
+ _traverse_mode( mode ),
+ _root(root)
{
if( mode == TRAVERSE_DOWN )
{
- EventTarget target = {0, pos, delta};
+ EventTarget target = {ElementWeakPtr(), pos, delta};
_target_path.push_back(target);
}
}
m(0, 1) * pos[0] + m(1, 1) * pos[1] + m(3, 1)
);
- // 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(local_pos) )
+ // Don't check specified root element for collision, as its purpose is to
+ // catch all events which have no target. This allows for example calling
+ // event listeners attached to the canvas itself (its root group) even if
+ // no element has been hit.
+ if( _root.get() != &el && !el.hitBound(pos, local_pos) )
return false;
const osg::Vec2f& delta = _target_path.back().local_delta;
m(0, 1) * delta[0] + m(1, 1) * delta[1]
);
- EventTarget target = {&el, local_pos, local_delta};
+ EventTarget target = {el.getWeakPtr(), local_pos, local_delta};
_target_path.push_back(target);
- if( el.traverse(*this) || _target_path.size() <= 2 )
+ if( el.traverse(*this) || &el == _root.get() )
return true;
_target_path.pop_back();
}
//----------------------------------------------------------------------------
- bool EventVisitor::propagateEvent(const EventPtr& event)
+ const EventPropagationPath& EventVisitor::getPropagationPath() const
{
- // Event propagation similar to DOM Level 3 event flow:
- // 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 )
-// {
-// if( it->element )
-// std::cout << it->element->getProps()->getPath() << " "
-// << "(" << it->local_pos.x() << "|" << it->local_pos.y() << ")\n";
-// }
-
- // Bubbling phase
- for( EventTargets::reverse_iterator it = _target_path.rbegin();
- it != _target_path.rend();
- ++it )
- {
- if( !it->element )
- continue;
-
- it->element->callListeners(event);
-
- if( event->propagation_stopped )
- return true;
- }
-
- return true;
+ return _target_path;
}
} // namespace canvas