Canvas: allow also C++ callable entities as event callbacks.

This commit is contained in:
Thomas Geymayer 2013-10-12 00:27:52 +02:00
parent 9e3172cb04
commit 6deb77dd4d
7 changed files with 60 additions and 33 deletions

View 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);
}
//----------------------------------------------------------------------------

View 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);

View 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

View 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;

View 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

View 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
_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());
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;
}

View 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;