]> git.mxchange.org Git - simgear.git/commitdiff
Canvas: Prepare for DOM Level 2 like event model.
authorThomas Geymayer <tomgey@gmail.com>
Tue, 27 Nov 2012 12:46:48 +0000 (13:46 +0100)
committerThomas Geymayer <tomgey@gmail.com>
Tue, 27 Nov 2012 12:51:00 +0000 (13:51 +0100)
25 files changed:
simgear/canvas/CMakeLists.txt
simgear/canvas/Canvas.cxx
simgear/canvas/Canvas.hxx
simgear/canvas/CanvasEvent.cxx [new file with mode: 0644]
simgear/canvas/CanvasEvent.hxx [new file with mode: 0644]
simgear/canvas/CanvasEventListener.cxx [new file with mode: 0644]
simgear/canvas/CanvasEventListener.hxx [new file with mode: 0644]
simgear/canvas/CanvasEventTypes.hxx [new file with mode: 0644]
simgear/canvas/CanvasEventVisitor.cxx [new file with mode: 0644]
simgear/canvas/CanvasEventVisitor.hxx [new file with mode: 0644]
simgear/canvas/CanvasSystemAdapter.hxx
simgear/canvas/MouseEvent.hxx
simgear/canvas/canvas_fwd.hxx
simgear/canvas/elements/CanvasElement.cxx
simgear/canvas/elements/CanvasElement.hxx
simgear/canvas/elements/CanvasGroup.cxx
simgear/canvas/elements/CanvasGroup.hxx
simgear/canvas/elements/CanvasImage.cxx
simgear/canvas/elements/CanvasImage.hxx
simgear/canvas/elements/CanvasMap.cxx
simgear/canvas/elements/CanvasMap.hxx
simgear/canvas/elements/CanvasPath.cxx
simgear/canvas/elements/CanvasPath.hxx
simgear/canvas/elements/CanvasText.cxx
simgear/canvas/elements/CanvasText.hxx

index 1fa496b6613b84e38d4f2dd523e32370d593b9cf..c0e7fecd20c576171cdf1dc45ed95ee789c18092 100644 (file)
@@ -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
index 3112fcb3b9133eb7f5628c4b10adbdf9e8b1f61c..d2dc2358174a0408f8597033807ca7209651205e 100644 (file)
@@ -17,6 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
 
 #include "Canvas.hxx"
+#include "CanvasEventVisitor.hxx"
 #include <simgear/canvas/MouseEvent.hxx>
 #include <simgear/canvas/CanvasPlacement.hxx>
 #include <simgear/scene/util/parse_color.hxx>
@@ -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);
   }
 
   //----------------------------------------------------------------------------
index 848908c36bbd7067242efe65f2e71f6d44a4b506..4ad23527d7ff0b62f5c00a7a1b0ca8f6831a17e0 100644 (file)
@@ -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 (file)
index 0000000..36b73ec
--- /dev/null
@@ -0,0 +1,59 @@
+// Canvas Event for event model similar to DOM Level 2 Event Model
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 (file)
index 0000000..88cb421
--- /dev/null
@@ -0,0 +1,56 @@
+// Canvas Event for event model similar to DOM Level 2 Event Model
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 ///<! first unused id to be used for user defined types (not
+                  ///   implemented yet)
+      };
+
+      Type              type;
+      ElementWeakPtr    target;
+
+      Event();
+      Type getType() const;
+      std::string getTypeString() const;
+      ElementWeakPtr getTarget() const;
+
+  };
+
+} // namespace canvas
+} // namespace simgear
+
+#endif /* CANVAS_EVENT_HXX_ */
diff --git a/simgear/canvas/CanvasEventListener.cxx b/simgear/canvas/CanvasEventListener.cxx
new file mode 100644 (file)
index 0000000..b94928b
--- /dev/null
@@ -0,0 +1,66 @@
+// Listener for canvas (GUI) events being passed to a Nasal function/code
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 <simgear/nasal/nasal.h>
+
+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 (file)
index 0000000..022b76a
--- /dev/null
@@ -0,0 +1,48 @@
+// Listener for canvas (GUI) events being passed to a Nasal function/code
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 <simgear/nasal/naref.h>
+
+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 (file)
index 0000000..6e428ee
--- /dev/null
@@ -0,0 +1,31 @@
+// Mapping between canvas gui Event types and their names
+//
+// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
+//
+// 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 (file)
index 0000000..9970d8d
--- /dev/null
@@ -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 <tomgey@gmail.com>
+//
+// 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 <simgear/canvas/elements/CanvasElement.hxx>
+#include <iostream>
+
+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 (file)
index 0000000..415641b
--- /dev/null
@@ -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 <tomgey@gmail.com>
+//
+// 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 <deque>
+
+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<EventTarget> EventTargets;
+
+      EventTargets  _target_path;
+      TraverseMode  _traverse_mode;
+  };
+
+} // namespace canvas
+} // namespace simgear
+
+
+#endif /* CANVAS_EVENTVISITOR_HXX_ */
index 5dfa8ac3d5bc2bc0a3a8c3e3e5fe388510adbfd6..6a608d9a2497fe6a360ff9a89ea35e1b999f77ec 100644 (file)
@@ -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
index 2e6a26dd6173bcc5ef912ae7aba2e32965aeb020..b5d014f2d02d21c80eb7810f20ac17e693a9ac75 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef CANVAS_MOUSE_EVENT_HXX_
 #define CANVAS_MOUSE_EVENT_HXX_
 
+#include "CanvasEvent.hxx"
 #include <osgGA/GUIEventAdapter>
 
 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, //<! Button for this event
-                  state,  //<! Current button state
-                  mod;    //<! Keyboard modifier state
-      Scroll      scroll;
+    MouseEvent():
+      button(-1),
+      state(-1),
+      mod(-1)
+    {}
+
+    osg::Vec2f getPos() const { return pos; }
+    osg::Vec3f getPos3() const { return osg::Vec3f(pos, 0); }
+    osg::Vec2f getDelta() const { return delta; }
+
+    osg::Vec2f  pos,
+                delta;
+    int         button, //<! Button for this event
+                state,  //<! Current button state
+                mod;    //<! Keyboard modifier state
   };
 
 } // namespace canvas
index a72baf62e4bbec4b3c29916b019514b2b1b21e86..4b0e41e10ccc2acca7011550fe0a992e817da118 100644 (file)
@@ -50,15 +50,21 @@ namespace canvas
   SG_FWD_DECL(Path)
   SG_FWD_DECL(Text)
 
+  SG_FWD_DECL(Event)
+  SG_FWD_DECL(EventListener)
+  SG_FWD_DECL(MouseEvent)
   SG_FWD_DECL(Placement)
   SG_FWD_DECL(SystemAdapter)
 
 #undef SG_FWD_DECL
 
+  class EventVisitor;
+
   typedef std::map<std::string, const SGPropertyNode*> Style;
   typedef ElementPtr (*ElementFactory)( const CanvasWeakPtr&,
                                         const SGPropertyNode_ptr&,
-                                        const Style& );
+                                        const Style&,
+                                        Element* );
 
   typedef osg::ref_ptr<osgText::Font> FontPtr;
 
index be0903dc3a2355ef018e848c24c9b33532a7fb96..2059c6586b083f4b669de33ceca729a294959b78 100644 (file)
@@ -17,6 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
 
 #include "CanvasElement.hxx"
+#include <simgear/canvas/CanvasEventVisitor.hxx>
 #include <simgear/canvas/MouseEvent.hxx>
 
 #include <osg/Drawable>
@@ -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;
   }
 
   //----------------------------------------------------------------------------
index 547b3863d17b8c53359e582744c7c82362489a27..bf71a4cd52b0a98727837231e0dcfd1c46f99776 100644 (file)
 #define CANVAS_ELEMENT_HXX_
 
 #include <simgear/canvas/canvas_fwd.hxx>
+#include <simgear/canvas/CanvasEvent.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/misc/stdint.hxx> // for uint32_t
+#include <simgear/nasal/cppbind/Ghost.hxx>
+
 #include <osg/BoundingBox>
 #include <osg/MatrixTransform>
 
@@ -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<osg::MatrixTransform> 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<SGPropertyNode_ptr>   _bounding_box;
 
+      typedef std::vector<EventListenerPtr> Listener;
+      typedef std::map<Event::Type, Listener> ListenerMap;
+
+      ListenerMap _listener;
+
       Element( const CanvasWeakPtr& canvas,
                const SGPropertyNode_ptr& node,
-               const Style& parent_style );
+               const Style& parent_style,
+               Element* parent );
 
       template<typename T, class C1, class C2>
       Element::StyleSetter
@@ -156,7 +168,7 @@ namespace canvas
         return boost::bind(setter, instance, boost::bind(&getValue<T1>, _1));
       }
 
-      virtual bool handleLocalMouseEvent(const canvas::MouseEvent& event);
+      void callListeners(canvas::Event& event);
 
       virtual void childAdded(SGPropertyNode * child)  {}
       virtual void childRemoved(SGPropertyNode * child){}
index f5e9ce3ff61bd301bbeea2dcb240fddaf42e1fac..fdcc7ae244454b882a3bc1934f99e73f51629c5c 100644 (file)
@@ -21,6 +21,8 @@
 #include "CanvasMap.hxx"
 #include "CanvasPath.hxx"
 #include "CanvasText.hxx"
+#include <simgear/canvas/CanvasEventVisitor.hxx>
+#include <simgear/canvas/MouseEvent.hxx>
 
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
@@ -36,16 +38,18 @@ namespace canvas
   template<typename T>
   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<Group>;
     _child_factories["image"] = &createElement<Image>;
@@ -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() );
index 0cac8a1c9b9344e803485b62dcc2324fb8d9e0e6..55b031e82ccea8eefd51e2da9d24d135e3698df3 100644 (file)
@@ -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<std::string, ElementFactory> 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);
index e97a85b31c45e9c80e2e901fa42fb5f0eb433c06..ad538dd40f56f426366ae7e827759eb5dbd19549 100644 (file)
@@ -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) )
   {
index d7affec5c181393cc2b6fcdb06a3f2dd6a157e0f..f72ed6f1794458f5240c34f420db834fe10c5f4f 100644 (file)
@@ -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);
index a2ec2cba8a2cfacc683e579ade76b2361809fcca..184ac8193bc30d3863333b8e953354819c48ea15 100644 (file)
@@ -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)
index bf278a6e135e5ce24d7ddf55e3c14d9e99a60df3..dda9c4828a61b39e2192f36e5f4f32ce5db927fa 100644 (file)
@@ -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);
index 7b5af9272a4a267f22fb7a04d820d00b1082412e..ebcb45ff7445db89e3297c8df64d6bf7c5260a3a 100644 (file)
@@ -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);
index 3ef722a4ca02b31f15cd895dc9b3733dd299a552..42854772aef3f06e7e63e3f49a604ad209e41e85 100644 (file)
@@ -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);
index d0680c365b35d33fc9336debad1f4e815d3942d5..3e5d78531cf71c3bfff0124c032894cd8b3b756c 100644 (file)
@@ -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);
index 0937e5910d5640a95f24696acc5e259f3b6cb055..1c82fe3963d38db66949fdbb0a3e4a986f6d11e5 100644 (file)
@@ -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);