From 6deb77dd4db931d8dfc8cc612dd492ddfe18df44 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Sat, 12 Oct 2013 00:27:52 +0200 Subject: [PATCH] Canvas: allow also C++ callable entities as event callbacks. --- simgear/canvas/Canvas.cxx | 16 ++++++++-- simgear/canvas/Canvas.hxx | 3 +- simgear/canvas/CanvasEventListener.cxx | 16 +++++----- simgear/canvas/CanvasEventListener.hxx | 11 ++++--- simgear/canvas/canvas_fwd.hxx | 3 +- simgear/canvas/elements/CanvasElement.cxx | 38 ++++++++++++++--------- simgear/canvas/elements/CanvasElement.hxx | 6 ++-- 7 files changed, 60 insertions(+), 33 deletions(-) diff --git a/simgear/canvas/Canvas.cxx b/simgear/canvas/Canvas.cxx index 99fc08cd..390c3ea0 100644 --- a/simgear/canvas/Canvas.cxx +++ b/simgear/canvas/Canvas.cxx @@ -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); } //---------------------------------------------------------------------------- diff --git a/simgear/canvas/Canvas.hxx b/simgear/canvas/Canvas.hxx index 08fbe40d..481179b1 100644 --- a/simgear/canvas/Canvas.hxx +++ b/simgear/canvas/Canvas.hxx @@ -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); diff --git a/simgear/canvas/CanvasEventListener.cxx b/simgear/canvas/CanvasEventListener.cxx index 78feb64d..03675ff7 100644 --- a/simgear/canvas/CanvasEventListener.cxx +++ b/simgear/canvas/CanvasEventListener.cxx @@ -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::create(sys->getNasalContext(), event) @@ -65,6 +68,5 @@ namespace canvas sys->callMethod(_code, naNil(), num_args, args, naNil()); } - } // namespace canvas } // namespace simgear diff --git a/simgear/canvas/CanvasEventListener.hxx b/simgear/canvas/CanvasEventListener.hxx index b8e39c50..6879345a 100644 --- a/simgear/canvas/CanvasEventListener.hxx +++ b/simgear/canvas/CanvasEventListener.hxx @@ -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; diff --git a/simgear/canvas/canvas_fwd.hxx b/simgear/canvas/canvas_fwd.hxx index 8694d86e..e90f5907 100644 --- a/simgear/canvas/canvas_fwd.hxx +++ b/simgear/canvas/canvas_fwd.hxx @@ -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 PlacementFactory; + typedef boost::function EventListener; + } // namespace canvas } // namespace simgear diff --git a/simgear/canvas/elements/CanvasElement.cxx b/simgear/canvas/elements/CanvasElement.cxx index c4612659..5ffde2a2 100644 --- a/simgear/canvas/elements/CanvasElement.cxx +++ b/simgear/canvas/elements/CanvasElement.cxx @@ -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(0); - naRef code = ctx.requireArg(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 listener = + new NasalEventListener(code, _canvas.lock()->getSystemAdapter()); - _listener[ type ].push_back + return addEventListener ( - boost::make_shared( 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; } diff --git a/simgear/canvas/elements/CanvasElement.hxx b/simgear/canvas/elements/CanvasElement.hxx index 3487f868..c7191984 100644 --- a/simgear/canvas/elements/CanvasElement.hxx +++ b/simgear/canvas/elements/CanvasElement.hxx @@ -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 _bounding_box; - typedef std::vector Listener; + typedef std::vector Listener; typedef std::map ListenerMap; ListenerMap _listener; -- 2.39.5