From 77946585b1c9b54c4848b604eb1549e2ec55df12 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Tue, 27 Nov 2012 13:46:48 +0100 Subject: [PATCH] Canvas: Prepare for DOM Level 2 like event model. --- simgear/canvas/CMakeLists.txt | 8 ++ simgear/canvas/Canvas.cxx | 35 ++++--- simgear/canvas/Canvas.hxx | 2 +- simgear/canvas/CanvasEvent.cxx | 59 +++++++++++ simgear/canvas/CanvasEvent.hxx | 56 +++++++++++ simgear/canvas/CanvasEventListener.cxx | 66 +++++++++++++ simgear/canvas/CanvasEventListener.hxx | 48 +++++++++ simgear/canvas/CanvasEventTypes.hxx | 31 ++++++ simgear/canvas/CanvasEventVisitor.cxx | 113 ++++++++++++++++++++++ simgear/canvas/CanvasEventVisitor.hxx | 67 +++++++++++++ simgear/canvas/CanvasSystemAdapter.hxx | 9 ++ simgear/canvas/MouseEvent.hxx | 43 ++++---- simgear/canvas/canvas_fwd.hxx | 8 +- simgear/canvas/elements/CanvasElement.cxx | 59 +++++++---- simgear/canvas/elements/CanvasElement.hxx | 28 ++++-- simgear/canvas/elements/CanvasGroup.cxx | 18 ++-- simgear/canvas/elements/CanvasGroup.hxx | 7 +- simgear/canvas/elements/CanvasImage.cxx | 5 +- simgear/canvas/elements/CanvasImage.hxx | 3 +- simgear/canvas/elements/CanvasMap.cxx | 5 +- simgear/canvas/elements/CanvasMap.hxx | 3 +- simgear/canvas/elements/CanvasPath.cxx | 5 +- simgear/canvas/elements/CanvasPath.hxx | 3 +- simgear/canvas/elements/CanvasText.cxx | 5 +- simgear/canvas/elements/CanvasText.hxx | 3 +- 25 files changed, 600 insertions(+), 89 deletions(-) create mode 100644 simgear/canvas/CanvasEvent.cxx create mode 100644 simgear/canvas/CanvasEvent.hxx create mode 100644 simgear/canvas/CanvasEventListener.cxx create mode 100644 simgear/canvas/CanvasEventListener.hxx create mode 100644 simgear/canvas/CanvasEventTypes.hxx create mode 100644 simgear/canvas/CanvasEventVisitor.cxx create mode 100644 simgear/canvas/CanvasEventVisitor.hxx diff --git a/simgear/canvas/CMakeLists.txt b/simgear/canvas/CMakeLists.txt index 1fa496b6..c0e7fecd 100644 --- a/simgear/canvas/CMakeLists.txt +++ b/simgear/canvas/CMakeLists.txt @@ -3,6 +3,10 @@ include (SimGearComponent) set(HEADERS canvas_fwd.hxx Canvas.hxx + CanvasEvent.hxx + CanvasEventListener.hxx + CanvasEventTypes.hxx + CanvasEventVisitor.hxx CanvasMgr.hxx CanvasPlacement.hxx CanvasSystemAdapter.hxx @@ -13,6 +17,10 @@ set(HEADERS set(SOURCES Canvas.cxx + Canvas.cxx + CanvasEvent.cxx + CanvasEventListener.cxx + CanvasEventVisitor.cxx CanvasMgr.cxx CanvasPlacement.cxx ODGauge.cxx diff --git a/simgear/canvas/Canvas.cxx b/simgear/canvas/Canvas.cxx index 3112fcb3..d2dc2358 100644 --- a/simgear/canvas/Canvas.cxx +++ b/simgear/canvas/Canvas.cxx @@ -17,6 +17,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA #include "Canvas.hxx" +#include "CanvasEventVisitor.hxx" #include #include #include @@ -324,23 +325,31 @@ namespace canvas } //---------------------------------------------------------------------------- - bool Canvas::handleMouseEvent(const MouseEvent& event) + bool Canvas::handleMouseEvent(const MouseEventPtr& event) { - _mouse_x = event.x; - _mouse_y = event.y; - _mouse_dx = event.dx; - _mouse_dy = event.dy; - _mouse_button = event.button; - _mouse_state = event.state; - _mouse_mod = event.mod; - _mouse_scroll = event.scroll; + _mouse_x = event->pos.x(); + _mouse_y = event->pos.y(); + _mouse_dx = event->delta.x(); + _mouse_dy = event->delta.y(); + _mouse_button = event->button; + _mouse_state = event->state; + _mouse_mod = event->mod; + //_mouse_scroll = event.scroll; // Always set event type last because all listeners are attached to it - _mouse_event = event.type; + _mouse_event = event->type; - if( _root_group.get() ) - return _root_group->handleMouseEvent(event); - else + if( !_root_group.get() ) + return false; + + EventVisitor visitor( EventVisitor::TRAVERSE_DOWN, + event->getPos(), + event->getDelta() ); + if( !_root_group->accept(visitor) ) return false; + + // TODO create special events like click/dblclick etc. + + return visitor.propagateEvent(event); } //---------------------------------------------------------------------------- diff --git a/simgear/canvas/Canvas.hxx b/simgear/canvas/Canvas.hxx index 848908c3..4ad23527 100644 --- a/simgear/canvas/Canvas.hxx +++ b/simgear/canvas/Canvas.hxx @@ -112,7 +112,7 @@ namespace canvas void setViewWidth(int w); void setViewHeight(int h); - bool handleMouseEvent(const MouseEvent& event); + bool handleMouseEvent(const MouseEventPtr& event); virtual void childAdded( SGPropertyNode * parent, SGPropertyNode * child ); diff --git a/simgear/canvas/CanvasEvent.cxx b/simgear/canvas/CanvasEvent.cxx new file mode 100644 index 00000000..36b73ecf --- /dev/null +++ b/simgear/canvas/CanvasEvent.cxx @@ -0,0 +1,59 @@ +// Canvas Event for event model similar to DOM Level 2 Event Model +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#include "CanvasEvent.hxx" + +namespace simgear +{ +namespace canvas +{ + + //---------------------------------------------------------------------------- + Event::Event(): + type(UNKNOWN) + { + + } + + //---------------------------------------------------------------------------- + Event::Type Event::getType() const + { + return type; + } + + //---------------------------------------------------------------------------- + std::string Event::getTypeString() const + { + switch( type ) + { +# define ENUM_MAPPING(name, str) case name: return str; +# include "CanvasEventTypes.hxx" +# undef ENUM_MAPPING + default: + return "unknown"; + } + } + + //---------------------------------------------------------------------------- + ElementWeakPtr Event::getTarget() const + { + return target; + } + +} // namespace canvas +} // namespace simgear diff --git a/simgear/canvas/CanvasEvent.hxx b/simgear/canvas/CanvasEvent.hxx new file mode 100644 index 00000000..88cb4216 --- /dev/null +++ b/simgear/canvas/CanvasEvent.hxx @@ -0,0 +1,56 @@ +// Canvas Event for event model similar to DOM Level 2 Event Model +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef CANVAS_EVENT_HXX_ +#define CANVAS_EVENT_HXX_ + +#include "canvas_fwd.hxx" + +namespace simgear +{ +namespace canvas +{ + + struct Event + { + public: + + enum Type + { + UNKNOWN, +# define ENUM_MAPPING(name, str) name, +# include "CanvasEventTypes.hxx" +# undef ENUM_MAPPING + USER_TYPE /// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#include "CanvasEventListener.hxx" +#include "CanvasSystemAdapter.hxx" + +#include + +namespace simgear +{ +namespace canvas +{ + + //---------------------------------------------------------------------------- + EventListener::EventListener(naRef code, const SystemAdapterPtr& sys_adapter): + _code(code), + _gc_key(-1), + _sys(sys_adapter) + { + assert( sys_adapter ); + if( !naIsCode(code) + && !naIsCCode(code) + && !naIsFunc(code) ) + throw std::runtime_error + ( + "canvas::EventListener: invalid function argument" + ); + + _gc_key = sys_adapter->gcSave(_code); + } + + //---------------------------------------------------------------------------- + EventListener::~EventListener() + { + assert( !_sys.expired() ); + _sys.lock()->gcRelease(_gc_key); + } + + //------------------------------------------------------------------------------ + void EventListener::call() + { + const size_t num_args = 1; + naRef args[num_args] = { + naNil() + }; + _sys.lock()->callMethod(_code, naNil(), num_args, args, naNil()); + } + + +} // namespace canvas +} // namespace simgear diff --git a/simgear/canvas/CanvasEventListener.hxx b/simgear/canvas/CanvasEventListener.hxx new file mode 100644 index 00000000..022b76a1 --- /dev/null +++ b/simgear/canvas/CanvasEventListener.hxx @@ -0,0 +1,48 @@ +// Listener for canvas (GUI) events being passed to a Nasal function/code +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef CANVAS_EVENT_LISTENER_HXX_ +#define CANVAS_EVENT_LISTENER_HXX_ + +#include "canvas_fwd.hxx" +#include + +namespace simgear +{ +namespace canvas +{ + + class EventListener + { + public: + EventListener( naRef code, + const SystemAdapterPtr& sys_adapter ); + ~EventListener(); + + void call(); + + protected: + naRef _code; + int _gc_key; + SystemAdapterWeakPtr _sys; + }; + +} // namespace canvas +} // namespace simgear + +#endif /* CANVAS_EVENT_LISTENER_HXX_ */ diff --git a/simgear/canvas/CanvasEventTypes.hxx b/simgear/canvas/CanvasEventTypes.hxx new file mode 100644 index 00000000..6e428ee5 --- /dev/null +++ b/simgear/canvas/CanvasEventTypes.hxx @@ -0,0 +1,31 @@ +// Mapping between canvas gui Event types and their names +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef ENUM_MAPPING +# error "Don't include this file directly!" +#endif + +ENUM_MAPPING(MOUSE_DOWN, "mousedown") +ENUM_MAPPING(MOUSE_UP, "mouseup") +ENUM_MAPPING(CLICK, "click") +ENUM_MAPPING(DBL_CLICK, "dblclick") +ENUM_MAPPING(MOUSE_MOVE, "mousemove") +ENUM_MAPPING(MOUSE_OVER, "mouseover") +ENUM_MAPPING(MOUSE_OUT, "mouseout") +ENUM_MAPPING(MOUSE_ENTER, "mouseenter") +ENUM_MAPPING(MOUSE_LEAVE, "mouseleave") diff --git a/simgear/canvas/CanvasEventVisitor.cxx b/simgear/canvas/CanvasEventVisitor.cxx new file mode 100644 index 00000000..9970d8d9 --- /dev/null +++ b/simgear/canvas/CanvasEventVisitor.cxx @@ -0,0 +1,113 @@ +// Visitor for traversing a canvas element hierarchy similar to the traversal +// of the DOM Level 2 Event Model +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#include "CanvasEvent.hxx" +#include "CanvasEventVisitor.hxx" +#include +#include + +namespace simgear +{ +namespace canvas +{ + + //---------------------------------------------------------------------------- + EventVisitor::EventVisitor( TraverseMode mode, + const osg::Vec2f& pos, + const osg::Vec2f& delta ): + _traverse_mode( mode ) + { + if( mode == TRAVERSE_DOWN ) + { + EventTarget target = {0, pos, delta}; + _target_path.push_back(target); + } + } + + //---------------------------------------------------------------------------- + EventVisitor::~EventVisitor() + { + + } + + //---------------------------------------------------------------------------- + bool EventVisitor::traverse(Element& el) + { + if( _traverse_mode == TRAVERSE_UP ) + return el.ascend(*this); + else + return el.traverse(*this); + } + + //---------------------------------------------------------------------------- + bool EventVisitor::apply(Element& el) + { + // We only need to check for hits while traversing down + if( _traverse_mode == TRAVERSE_DOWN ) + { + // Transform event to local coordinates + const osg::Matrix& m = el.getMatrixTransform()->getInverseMatrix(); + const osg::Vec2f& pos = _target_path.back().local_pos; + const osg::Vec2f local_pos + ( + m(0, 0) * pos[0] + m(1, 0) * pos[1] + m(3, 0), + m(0, 1) * pos[0] + m(1, 1) * pos[1] + m(3, 1) + ); + + if( !el.hitBound(local_pos) ) + return false; + + const osg::Vec2f& delta = _target_path.back().local_delta; + const osg::Vec2f local_delta + ( + m(0, 0) * delta[0] + m(1, 0) * delta[1], + m(0, 1) * delta[0] + m(1, 1) * delta[1] + ); + + EventTarget target = {&el, local_pos, local_delta}; + _target_path.push_back(target); + + if( el.traverse(*this) ) + return true; + + _target_path.pop_back(); + return false; + } + else + return el.ascend(*this); + } + + //---------------------------------------------------------------------------- + bool EventVisitor::propagateEvent(const EventPtr& event) + { +// std::cout << "Propagate event " << event->getTypeString() << "\n"; +// 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"; +// } + + return true; + } + +} // namespace canvas +} // namespace simgear diff --git a/simgear/canvas/CanvasEventVisitor.hxx b/simgear/canvas/CanvasEventVisitor.hxx new file mode 100644 index 00000000..415641b0 --- /dev/null +++ b/simgear/canvas/CanvasEventVisitor.hxx @@ -0,0 +1,67 @@ +// Visitor for traversing a canvas element hierarchy similar to the traversal +// of the DOM Level 2 Event Model +// +// Copyright (C) 2012 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef CANVAS_EVENT_VISITOR_HXX_ +#define CANVAS_EVENT_VISITOR_HXX_ + +#include "canvas_fwd.hxx" +#include + +namespace simgear +{ +namespace canvas +{ + + class EventVisitor + { + public: + + enum TraverseMode + { + TRAVERSE_UP, + TRAVERSE_DOWN + }; + + EventVisitor( TraverseMode mode, + const osg::Vec2f& pos, + const osg::Vec2f& delta ); + virtual ~EventVisitor(); + virtual bool traverse(Element& el); + virtual bool apply(Element& el); + + bool propagateEvent(const EventPtr& event); + + protected: + struct EventTarget + { + Element* element; + osg::Vec2f local_pos, + local_delta; + }; + typedef std::deque EventTargets; + + EventTargets _target_path; + TraverseMode _traverse_mode; + }; + +} // namespace canvas +} // namespace simgear + + +#endif /* CANVAS_EVENTVISITOR_HXX_ */ diff --git a/simgear/canvas/CanvasSystemAdapter.hxx b/simgear/canvas/CanvasSystemAdapter.hxx index 5dfa8ac3..6a608d9a 100644 --- a/simgear/canvas/CanvasSystemAdapter.hxx +++ b/simgear/canvas/CanvasSystemAdapter.hxx @@ -48,6 +48,15 @@ namespace canvas * cleaned up by the garbage collector. */ virtual void gcRelease(int key) = 0; + + /** + * Call a Nasal function with the given environment and arguments. + */ + virtual naRef callMethod( naRef code, + naRef self, + int argc, + naRef* args, + naRef locals ) = 0; }; } // namespace canvas diff --git a/simgear/canvas/MouseEvent.hxx b/simgear/canvas/MouseEvent.hxx index 2e6a26dd..b5d014f2 100644 --- a/simgear/canvas/MouseEvent.hxx +++ b/simgear/canvas/MouseEvent.hxx @@ -19,6 +19,7 @@ #ifndef CANVAS_MOUSE_EVENT_HXX_ #define CANVAS_MOUSE_EVENT_HXX_ +#include "CanvasEvent.hxx" #include namespace simgear @@ -26,32 +27,24 @@ namespace simgear namespace canvas { - class MouseEvent + struct MouseEvent: + public Event { - public: - typedef osgGA::GUIEventAdapter::EventType EventType; - typedef osgGA::GUIEventAdapter::ScrollingMotion Scroll; - - MouseEvent(EventType type): - type(type), - x(-1), y(-1), - dx(0), dy(0), - button(-1), - state(-1), - mod(-1), - scroll(osgGA::GUIEventAdapter::SCROLL_NONE) - {} - - osg::Vec2f getPos() const { return osg::Vec2f(x, y); } - osg::Vec3f getPos3() const { return osg::Vec3f(x, y, 0); } - - EventType type; - float x, y, - dx, dy; - int button, // Style; typedef ElementPtr (*ElementFactory)( const CanvasWeakPtr&, const SGPropertyNode_ptr&, - const Style& ); + const Style&, + Element* ); typedef osg::ref_ptr FontPtr; diff --git a/simgear/canvas/elements/CanvasElement.cxx b/simgear/canvas/elements/CanvasElement.cxx index be0903dc..2059c658 100644 --- a/simgear/canvas/elements/CanvasElement.cxx +++ b/simgear/canvas/elements/CanvasElement.cxx @@ -17,6 +17,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA #include "CanvasElement.hxx" +#include #include #include @@ -108,6 +109,13 @@ namespace canvas } } + //---------------------------------------------------------------------------- + naRef Element::addEventListener(const nasal::CallContext& ctx) + { + std::cout << "addEventListener " << _node->getPath() << std::endl; + return naNil(); + } + //---------------------------------------------------------------------------- SGConstPropertyNode_ptr Element::getProps() const { @@ -121,28 +129,41 @@ namespace canvas } //---------------------------------------------------------------------------- - bool Element::handleMouseEvent(const MouseEvent& event) + bool Element::accept(EventVisitor& visitor) + { + return visitor.apply(*this); + } + + //---------------------------------------------------------------------------- + bool Element::ascend(EventVisitor& visitor) + { + if( _parent ) + return _parent->accept(visitor); + return true; + } + + //---------------------------------------------------------------------------- + bool Element::traverse(EventVisitor& visitor) { - // Transform event to local coordinates - const osg::Matrixd& m = _transform->getInverseMatrix(); - MouseEvent local_event = event; - local_event.x = m(0, 0) * event.x + m(1, 0) * event.y + m(3, 0); - local_event.y = m(0, 1) * event.x + m(1, 1) * event.y + m(3, 1); + return true; + } + + //---------------------------------------------------------------------------- + bool Element::hitBound(const osg::Vec2f& pos) const + { + const osg::Vec3f pos3(pos, 0); // Drawables have a bounding box... if( _drawable ) { - if( !_drawable->getBound().contains(local_event.getPos3()) ) + if( !_drawable->getBound().contains(pos3) ) return false; } // ... for other elements, i.e. groups only a bounding sphere is available - else if( !_transform->getBound().contains(local_event.getPos3()) ) + else if( !_transform->getBound().contains(pos3) ) return false; - local_event.dx = m(0, 0) * event.dx + m(1, 0) * event.dy; - local_event.dy = m(0, 1) * event.dx + m(1, 1) * event.dy; - - return handleLocalMouseEvent(local_event); + return true; } //---------------------------------------------------------------------------- @@ -253,8 +274,10 @@ namespace canvas //---------------------------------------------------------------------------- Element::Element( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ): + const Style& parent_style, + Element* parent ): _canvas( canvas ), + _parent( parent ), _transform_dirty( false ), _transform( new osg::MatrixTransform ), _node( node ), @@ -273,13 +296,11 @@ namespace canvas } //---------------------------------------------------------------------------- - bool Element::handleLocalMouseEvent(const MouseEvent& event) + void Element::callListeners(canvas::Event& event) { -// std::cout << _node->getPath() -// << " local: pos=(" << event.x << "|" << event.y << ") " -// << "d=(" << event.dx << "|" << event.dx << ")" -// << std::endl; - return true; + ListenerMap::iterator listeners = _listener.find(event.getType()); + if( listeners == _listener.end() ) + return; } //---------------------------------------------------------------------------- diff --git a/simgear/canvas/elements/CanvasElement.hxx b/simgear/canvas/elements/CanvasElement.hxx index 547b3863..bf71a4cd 100644 --- a/simgear/canvas/elements/CanvasElement.hxx +++ b/simgear/canvas/elements/CanvasElement.hxx @@ -20,8 +20,11 @@ #define CANVAS_ELEMENT_HXX_ #include +#include #include #include // for uint32_t +#include + #include #include @@ -38,7 +41,6 @@ namespace simgear namespace canvas { - class MouseEvent; class Element: public SGPropertyChangeListener { @@ -67,14 +69,17 @@ namespace canvas */ virtual void update(double dt); + naRef addEventListener(const nasal::CallContext& ctx); + SGConstPropertyNode_ptr getProps() const; SGPropertyNode_ptr getProps(); - /** - * Handle mouse event (transforms coordinates to local coordinate frame - * and forwards event to #handleLocalMouseEvent) - */ - virtual bool handleMouseEvent(const canvas::MouseEvent& event); + virtual bool accept(EventVisitor& visitor); + virtual bool ascend(EventVisitor& visitor); + virtual bool traverse(EventVisitor& visitor); + + virtual bool hitBound(const osg::Vec2f& pos) const; + osg::ref_ptr getMatrixTransform(); @@ -106,6 +111,7 @@ namespace canvas }; CanvasWeakPtr _canvas; + Element *_parent; uint32_t _attributes_dirty; bool _transform_dirty; @@ -117,9 +123,15 @@ namespace canvas StyleSetters _style_setters; std::vector _bounding_box; + typedef std::vector Listener; + typedef std::map ListenerMap; + + ListenerMap _listener; + Element( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ); + const Style& parent_style, + Element* parent ); template Element::StyleSetter @@ -156,7 +168,7 @@ namespace canvas return boost::bind(setter, instance, boost::bind(&getValue, _1)); } - virtual bool handleLocalMouseEvent(const canvas::MouseEvent& event); + void callListeners(canvas::Event& event); virtual void childAdded(SGPropertyNode * child) {} virtual void childRemoved(SGPropertyNode * child){} diff --git a/simgear/canvas/elements/CanvasGroup.cxx b/simgear/canvas/elements/CanvasGroup.cxx index f5e9ce3f..fdcc7ae2 100644 --- a/simgear/canvas/elements/CanvasGroup.cxx +++ b/simgear/canvas/elements/CanvasGroup.cxx @@ -21,6 +21,8 @@ #include "CanvasMap.hxx" #include "CanvasPath.hxx" #include "CanvasText.hxx" +#include +#include #include #include @@ -36,16 +38,18 @@ namespace canvas template ElementPtr createElement( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& style ) + const Style& style, + Element* parent ) { - return ElementPtr( new T(canvas, node, style) ); + return ElementPtr( new T(canvas, node, style, parent) ); } //---------------------------------------------------------------------------- Group::Group( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ): - Element(canvas, node, parent_style) + const Style& parent_style, + Element* parent ): + Element(canvas, node, parent_style, parent) { _child_factories["group"] = &createElement; _child_factories["image"] = &createElement; @@ -91,12 +95,12 @@ namespace canvas } //---------------------------------------------------------------------------- - bool Group::handleLocalMouseEvent(const canvas::MouseEvent& event) + bool Group::traverse(EventVisitor& visitor) { // Iterate in reverse order as last child is displayed on top BOOST_REVERSE_FOREACH( ChildList::value_type child, _children ) { - if( child.second->handleMouseEvent(event) ) + if( child.second->accept(visitor) ) return true; } return false; @@ -112,7 +116,7 @@ namespace canvas _child_factories.find( child->getNameString() ); if( child_factory != _child_factories.end() ) { - ElementPtr element = child_factory->second(_canvas, child, _style); + ElementPtr element = child_factory->second(_canvas, child, _style, this); // Add to osg scene graph... _transform->addChild( element->getMatrixTransform() ); diff --git a/simgear/canvas/elements/CanvasGroup.hxx b/simgear/canvas/elements/CanvasGroup.hxx index 0cac8a1c..55b031e8 100644 --- a/simgear/canvas/elements/CanvasGroup.hxx +++ b/simgear/canvas/elements/CanvasGroup.hxx @@ -39,7 +39,8 @@ namespace canvas Group( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style = Style() ); + const Style& parent_style = Style(), + Element* parent = 0 ); virtual ~Group(); ElementPtr createChild( const std::string& type, @@ -48,6 +49,8 @@ namespace canvas virtual void update(double dt); + virtual bool traverse(EventVisitor& visitor); + protected: typedef std::map ChildFactories; @@ -55,8 +58,6 @@ namespace canvas ChildFactories _child_factories; ChildList _children; - virtual bool handleLocalMouseEvent(const canvas::MouseEvent& event); - virtual void childAdded(SGPropertyNode * child); virtual void childRemoved(SGPropertyNode * child); virtual void childChanged(SGPropertyNode * child); diff --git a/simgear/canvas/elements/CanvasImage.cxx b/simgear/canvas/elements/CanvasImage.cxx index e97a85b3..ad538dd4 100644 --- a/simgear/canvas/elements/CanvasImage.cxx +++ b/simgear/canvas/elements/CanvasImage.cxx @@ -74,8 +74,9 @@ namespace canvas //---------------------------------------------------------------------------- Image::Image( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ): - Element(canvas, node, parent_style), + const Style& parent_style, + Element* parent ): + Element(canvas, node, parent_style, parent), _texture(new osg::Texture2D), _node_src_rect( node->getNode("source", 0, true) ) { diff --git a/simgear/canvas/elements/CanvasImage.hxx b/simgear/canvas/elements/CanvasImage.hxx index d7affec5..f72ed6f1 100644 --- a/simgear/canvas/elements/CanvasImage.hxx +++ b/simgear/canvas/elements/CanvasImage.hxx @@ -43,7 +43,8 @@ namespace canvas */ Image( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ); + const Style& parent_style, + Element* parent = 0 ); virtual ~Image(); virtual void update(double dt); diff --git a/simgear/canvas/elements/CanvasMap.cxx b/simgear/canvas/elements/CanvasMap.cxx index a2ec2cba..184ac819 100644 --- a/simgear/canvas/elements/CanvasMap.cxx +++ b/simgear/canvas/elements/CanvasMap.cxx @@ -47,8 +47,9 @@ namespace canvas //---------------------------------------------------------------------------- Map::Map( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ): - Group(canvas, node, parent_style), + const Style& parent_style, + Element* parent ): + Group(canvas, node, parent_style, parent), // TODO make projection configurable _projection(new SansonFlamsteedProjection), _projection_dirty(true) diff --git a/simgear/canvas/elements/CanvasMap.hxx b/simgear/canvas/elements/CanvasMap.hxx index bf278a6e..dda9c482 100644 --- a/simgear/canvas/elements/CanvasMap.hxx +++ b/simgear/canvas/elements/CanvasMap.hxx @@ -37,7 +37,8 @@ namespace canvas public: Map( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ); + const Style& parent_style, + Element* parent = 0 ); virtual ~Map(); virtual void update(double dt); diff --git a/simgear/canvas/elements/CanvasPath.cxx b/simgear/canvas/elements/CanvasPath.cxx index 7b5af927..ebcb45ff 100644 --- a/simgear/canvas/elements/CanvasPath.cxx +++ b/simgear/canvas/elements/CanvasPath.cxx @@ -355,8 +355,9 @@ namespace canvas //---------------------------------------------------------------------------- Path::Path( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ): - Element(canvas, node, parent_style), + const Style& parent_style, + Element* parent ): + Element(canvas, node, parent_style, parent), _path( new PathDrawable(this) ) { setDrawable(_path); diff --git a/simgear/canvas/elements/CanvasPath.hxx b/simgear/canvas/elements/CanvasPath.hxx index 3ef722a4..42854772 100644 --- a/simgear/canvas/elements/CanvasPath.hxx +++ b/simgear/canvas/elements/CanvasPath.hxx @@ -31,7 +31,8 @@ namespace canvas public: Path( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ); + const Style& parent_style, + Element* parent = 0 ); virtual ~Path(); virtual void update(double dt); diff --git a/simgear/canvas/elements/CanvasText.cxx b/simgear/canvas/elements/CanvasText.cxx index d0680c36..3e5d7853 100644 --- a/simgear/canvas/elements/CanvasText.cxx +++ b/simgear/canvas/elements/CanvasText.cxx @@ -177,8 +177,9 @@ namespace canvas //---------------------------------------------------------------------------- Text::Text( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ): - Element(canvas, node, parent_style), + const Style& parent_style, + Element* parent ): + Element(canvas, node, parent_style, parent), _text( new Text::TextOSG(this) ) { setDrawable(_text); diff --git a/simgear/canvas/elements/CanvasText.hxx b/simgear/canvas/elements/CanvasText.hxx index 0937e591..1c82fe39 100644 --- a/simgear/canvas/elements/CanvasText.hxx +++ b/simgear/canvas/elements/CanvasText.hxx @@ -35,7 +35,8 @@ namespace canvas public: Text( const CanvasWeakPtr& canvas, const SGPropertyNode_ptr& node, - const Style& parent_style ); + const Style& parent_style, + Element* parent = 0 ); ~Text(); void setText(const char* text); -- 2.39.5