]> git.mxchange.org Git - simgear.git/commitdiff
Canvas: allow also C++ callable entities as event callbacks.
authorThomas Geymayer <tomgey@gmail.com>
Fri, 11 Oct 2013 22:27:52 +0000 (00:27 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Fri, 11 Oct 2013 22:29:37 +0000 (00:29 +0200)
simgear/canvas/Canvas.cxx
simgear/canvas/Canvas.hxx
simgear/canvas/CanvasEventListener.cxx
simgear/canvas/CanvasEventListener.hxx
simgear/canvas/canvas_fwd.hxx
simgear/canvas/elements/CanvasElement.cxx
simgear/canvas/elements/CanvasElement.hxx

index 99fc08cdad1261047c593a2943fa39153ec77f36..390c3ea0d1ab2dd7d762958f43c460bd05d453b4 100644 (file)
@@ -320,12 +320,22 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  naRef Canvas::addEventListener(const nasal::CallContext& ctx)
+  bool Canvas::addEventListener( const std::string& type,
+                                 const EventListener& cb )
   {
     if( !_root_group.get() )
-      naRuntimeError(ctx.c, "Canvas: No root group!");
+      throw std::runtime_error("Canvas::AddEventListener: no root group!");
 
-    return _root_group->addEventListener(ctx);
+    return _root_group->addEventListener(type, cb);
+  }
+
+  //----------------------------------------------------------------------------
+  bool Canvas::addNasalEventListener(const std::string& type, naRef code)
+  {
+    if( !_root_group.get() )
+      throw std::runtime_error("Canvas::AddNasalEventListener: no root group!");
+
+    return _root_group->addNasalEventListener(type, code);
   }
 
   //----------------------------------------------------------------------------
index 08fbe40dc3a9f363596cf8fced67799f45fd45db..481179b1940be71cb1e70e15bc21cc8c51449446 100644 (file)
@@ -132,7 +132,8 @@ namespace canvas
 
       void update(double delta_time_sec);
 
-      naRef addEventListener(const nasal::CallContext& ctx);
+      bool addEventListener(const std::string& type, const EventListener& cb);
+      bool addNasalEventListener(const std::string& type, naRef code);
 
       void setSizeX(int sx);
       void setSizeY(int sy);
index 78feb64da0a288dfb59c6fd53b5e92c59f158811..03675ff78ba33fad8bb03872d418007dc7cee862 100644 (file)
@@ -28,7 +28,8 @@ namespace canvas
 {
 
   //----------------------------------------------------------------------------
-  EventListener::EventListener(naRef code, const SystemAdapterPtr& sys_adapter):
+  NasalEventListener::NasalEventListener( naRef code,
+                                          const SystemAdapterPtr& sys_adapter ):
     _code(code),
     _gc_key(-1),
     _sys(sys_adapter)
@@ -39,23 +40,25 @@ namespace canvas
         && !naIsFunc(code) )
       throw std::runtime_error
       (
-        "canvas::EventListener: invalid function argument"
+        "canvas::NasalEventListener: invalid function argument"
       );
 
     _gc_key = sys_adapter->gcSave(_code);
   }
 
   //----------------------------------------------------------------------------
-  EventListener::~EventListener()
+  NasalEventListener::~NasalEventListener()
   {
-    assert( !_sys.expired() );
-    _sys.lock()->gcRelease(_gc_key);
+    if( !_sys.expired() )
+      _sys.lock()->gcRelease(_gc_key);
   }
 
   //----------------------------------------------------------------------------
-  void EventListener::call(const canvas::EventPtr& event)
+  void NasalEventListener::operator()(const canvas::EventPtr& event) const
   {
     SystemAdapterPtr sys = _sys.lock();
+    if( !sys )
+      return;
 
     naRef args[] = {
       nasal::Ghost<EventPtr>::create(sys->getNasalContext(), event)
@@ -65,6 +68,5 @@ namespace canvas
     sys->callMethod(_code, naNil(), num_args, args, naNil());
   }
 
-
 } // namespace canvas
 } // namespace simgear
index b8e39c5021d239904a5f8d42e58c4d4825eac17e..6879345a859830606db1d02eddf882482e7337d2 100644 (file)
@@ -27,14 +27,15 @@ namespace simgear
 namespace canvas
 {
 
-  class EventListener
+  class NasalEventListener:
+    public SGReferenced
   {
     public:
-      EventListener( naRef code,
-                     const SystemAdapterPtr& sys_adapter );
-      ~EventListener();
+      NasalEventListener( naRef code,
+                          const SystemAdapterPtr& sys_adapter );
+      ~NasalEventListener();
 
-      void call(const canvas::EventPtr& event);
+      void operator()(const canvas::EventPtr& event) const;
 
     protected:
       naRef _code;
index 8694d86e929b70c127077e8821e86a815d7b7d47..e90f590786d73582263fb48a1e7e434b5797e399 100644 (file)
@@ -51,7 +51,6 @@ namespace canvas
   SG_FWD_DECL(Text)
 
   SG_FWD_DECL(Event)
-  SG_FWD_DECL(EventListener)
   SG_FWD_DECL(MouseEvent)
   SG_FWD_DECL(Placement)
   SG_FWD_DECL(SystemAdapter)
@@ -73,6 +72,8 @@ namespace canvas
   typedef boost::function<Placements( SGPropertyNode*,
                                       CanvasPtr )> PlacementFactory;
 
+  typedef boost::function<void(const EventPtr&)> EventListener;
+
 } // namespace canvas
 } // namespace simgear
 
index c4612659dfb80fcf231acea6469784a5aa8dcd9a..5ffde2a293e63c86c330a820c249c6633a46e31e 100644 (file)
@@ -173,11 +173,9 @@ namespace canvas
   }
 
   //----------------------------------------------------------------------------
-  naRef Element::addEventListener(const nasal::CallContext& ctx)
+  bool Element::addEventListener( const std::string& type_str,
+                                  const EventListener& cb )
   {
-    const std::string type_str = ctx.requireArg<std::string>(0);
-    naRef code = ctx.requireArg<naRef>(1);
-
     SG_LOG
     (
       SG_NASAL,
@@ -187,17 +185,29 @@ namespace canvas
 
     Event::Type type = Event::strToType(type_str);
     if( type == Event::UNKNOWN )
-      naRuntimeError( ctx.c,
-                      "addEventListener: Unknown event type %s",
-                      type_str.c_str() );
+    {
+      SG_LOG( SG_NASAL,
+              SG_WARN,
+              "addEventListener: Unknown event type " << type_str );
+      return false;
+    }
+
+    _listener[ type ].push_back(cb);
+
+    return true;
+  }
+
+  //----------------------------------------------------------------------------
+  bool Element::addNasalEventListener(const std::string& type, naRef code)
+  {
+    SGSharedPtr<NasalEventListener> listener =
+      new NasalEventListener(code, _canvas.lock()->getSystemAdapter());
 
-    _listener[ type ].push_back
+    return addEventListener
     (
-      boost::make_shared<EventListener>( code,
-                                         _canvas.lock()->getSystemAdapter() )
+      type,
+      boost::bind(&NasalEventListener::operator(), listener, _1)
     );
-
-    return naNil();
   }
 
   //----------------------------------------------------------------------------
@@ -236,8 +246,8 @@ namespace canvas
     if( listeners == _listener.end() )
       return false;
 
-    BOOST_FOREACH(EventListenerPtr listener, listeners->second)
-      listener->call(event);
+    BOOST_FOREACH(EventListener const& listener, listeners->second)
+      listener(event);
 
     return true;
   }
index 3487f868135ec07dae2a5d242919c8b114e9065c..c7191984681378124f622cea54b6fe41e72de264 100644 (file)
@@ -92,7 +92,9 @@ namespace canvas
        */
       virtual void update(double dt);
 
-      naRef addEventListener(const nasal::CallContext& ctx);
+      bool addEventListener(const std::string& type, const EventListener& cb);
+      bool addNasalEventListener(const std::string& type, naRef code);
+
       virtual void clearEventListener();
 
       virtual bool accept(EventVisitor& visitor);
@@ -189,7 +191,7 @@ namespace canvas
       Style                             _style;
       std::vector<SGPropertyNode_ptr>   _bounding_box;
 
-      typedef std::vector<EventListenerPtr> Listener;
+      typedef std::vector<EventListener> Listener;
       typedef std::map<Event::Type, Listener> ListenerMap;
 
       ListenerMap _listener;