Implementing event handler for objects

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Implementing event handler for objects

Jonatan Magnusson-2
Hi

I'm wrapping a GUI toolkit using Luabind, and i've struck upon a problem
with handling events.

The GUI-toolkit I'm wrapping is wxWidgets. Every widget inherits
wxEvtHandler and that
class has a method called Bind() that is used to connect events to an
event handler. A stupid example:

class MyClass {
     void init ()
     {
         b = wxButton (frm, -1, "Some button");
         b->Bind (wxEVT_COMMAND_BUTTON_CLICKED,
&MyClass::HandleButtonClick, this);
     }

     void HandleButtonClick (wxCommandEvent& ev)
     {
         printf ("Button clicked.\n");
     }
}

My dream API for this in Lua would be:

     b = wx.Button (frm, -1, "Some button")
     b.on_click = function ()
         print ("Button clicked.\n")
     end

Or, even better:

     b.on_click:add (function ()
         print ("Button clicked, with multiple event handlers.\n")
     end

I guess I could live with something like this, which is more like the
C++ API:

     b.bind (wx.EVT_COMMAND_BUTTON_CLICKED, function (ev)
         print ("Button clicked again...\n")
     end)

But I have no idea how to implement this using Luabind, without creating
a wrapper class
for every class in the wxWidgets-library that I want to use.

I guess it would help if Luabind could automatically create a helper
class for each class (say "wxLuaEventHandler"),
but I don't think that's possible? Kind of like a nested class, but not
associated with any nested class in the base class.

Any suggestions?

Best regards,
Jonatan Magnusson



------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: Implementing event handler for objects

Tony Kostanjsek
hi jonatan,

you'll probably need some kind of callback proxy object that holds the Lua
target information that needs to be kept alive during the lifetime of the
widget/target. Something like:

struct LuaCallbackProxy
{
  luabind::object targetObject;
  luabind::object targetFunc;
 
  LuaCallbackProxy(luabind::object inTO, luabind::object inTF) :
inTargetObject(inTO),inTargetFunc(inTF) {}
 
  void eventHandler(wxCommandEvent& ev)
  {
    luabind::call_function<void>(targetFunc,targetObject,ev);
  }
};

typedef shared_ptr<LuaCallbackProxy> ProxyPtr;

ProxyPtr connect(wxButton* button, evtype , luabind::object targetObject,
luabind::object targetFunc)
{
  ProxyPtr result(new LuaCallbackProxy(targetObject, targetFunc));
  button->Bind(evtype, &LuaCallbackProxy::eventHandler, result.get());
  return result;
}

bind all this and the wx Widget stuff and then from Lua:

t={}
function t:handler(event)
  print("click")
end

local connection = connect(button, wxEVT_COMMAND_BUTTON_CLICKED,t,t.handler)


Just an idea, hope this makes sense,
best,
Tony

----- Ursprüngliche Mail ----
Von: Jonatan Magnusson <[hidden email]>
An: [hidden email]
Gesendet: Mittwoch, den 6. April 2011, 18:05:15 Uhr
Betreff: [luabind] Implementing event handler for objects

Hi

I'm wrapping a GUI toolkit using Luabind, and i've struck upon a problem
with handling events.

The GUI-toolkit I'm wrapping is wxWidgets. Every widget inherits
wxEvtHandler and that
class has a method called Bind() that is used to connect events to an
event handler. A stupid example:

class MyClass {
     void init ()
     {
         b = wxButton (frm, -1, "Some button");
         b->Bind (wxEVT_COMMAND_BUTTON_CLICKED,
&MyClass::HandleButtonClick, this);
     }

     void HandleButtonClick (wxCommandEvent& ev)
     {
         printf ("Button clicked.\n");
     }
}

My dream API for this in Lua would be:

     b = wx.Button (frm, -1, "Some button")
     b.on_click = function ()
         print ("Button clicked.\n")
     end

Or, even better:

     b.on_click:add (function ()
         print ("Button clicked, with multiple event handlers.\n")
     end

I guess I could live with something like this, which is more like the
C++ API:

     b.bind (wx.EVT_COMMAND_BUTTON_CLICKED, function (ev)
         print ("Button clicked again...\n")
     end)

But I have no idea how to implement this using Luabind, without creating
a wrapper class
for every class in the wxWidgets-library that I want to use.

I guess it would help if Luabind could automatically create a helper
class for each class (say "wxLuaEventHandler"),
but I don't think that's possible? Kind of like a nested class, but not
associated with any nested class in the base class.

Any suggestions?

Best regards,
Jonatan Magnusson



------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user


------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: Implementing event handler for objects

Jason McKesson
In reply to this post by Jonatan Magnusson-2
On 4/6/2011 9:05 AM, Jonatan Magnusson wrote:

> Hi
>
> I'm wrapping a GUI toolkit using Luabind, and i've struck upon a problem
> with handling events.
>
> The GUI-toolkit I'm wrapping is wxWidgets. Every widget inherits
> wxEvtHandler and that
> class has a method called Bind() that is used to connect events to an
> event handler. A stupid example:
>
> class MyClass {
>       void init ()
>       {
>           b = wxButton (frm, -1, "Some button");
>           b->Bind (wxEVT_COMMAND_BUTTON_CLICKED,
> &MyClass::HandleButtonClick, this);
>       }
>
>       void HandleButtonClick (wxCommandEvent&  ev)
>       {
>           printf ("Button clicked.\n");
>       }
> }
>
> My dream API for this in Lua would be:
>
>       b = wx.Button (frm, -1, "Some button")
>       b.on_click = function ()
>           print ("Button clicked.\n")
>       end
>
> Or, even better:
>
>       b.on_click:add (function ()
>           print ("Button clicked, with multiple event handlers.\n")
>       end
>
> I guess I could live with something like this, which is more like the
> C++ API:
>
>       b.bind (wx.EVT_COMMAND_BUTTON_CLICKED, function (ev)
>           print ("Button clicked again...\n")
>       end)
>
> But I have no idea how to implement this using Luabind, without creating
> a wrapper class
> for every class in the wxWidgets-library that I want to use.
>
> I guess it would help if Luabind could automatically create a helper
> class for each class (say "wxLuaEventHandler"),
> but I don't think that's possible? Kind of like a nested class, but not
> associated with any nested class in the base class.
>
> Any suggestions?
>
> Best regards,
> Jonatan Magnusson

I love Luabind. Really, I do. But it's simply not the best tool for
every Lua association task.

If you forced me to create a binding between wxWidgets and Lua, well,
I'd just download wxLua. But if you forced *me* to do it myself? I'd use
SWIG.

The type mapping feature of SWIG makes it so much easier to have this
kind of thing, where you can insert small bits of wrapper code
automatically in functions based on parameters and return values. It
makes adapting certain kinds of interfaces much easier.

SWIG works best when you have no control over the C/C++ API you're
using. Luabind is for when you have complete control over both the Lua
API and the C/C++ equivalent.

What Luabind really needs is a way to attach certain C++ objects to
Luabind, such that whenever they appear in a function's parameter list
or signature, Luabind will automatically call a given function that will
generate this parameter and/or return the value to Lua after the fact.
Rather than having to apply policies to each and every use of a
particular parameter.

------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: Implementing event handler for objects

Daniel Wallin
In reply to this post by Jonatan Magnusson-2
On Wed, Apr 6, 2011 at 6:05 PM, Jonatan Magnusson <[hidden email]> wrote:

> Hi
>
> I'm wrapping a GUI toolkit using Luabind, and i've struck upon a problem
> with handling events.
>
> The GUI-toolkit I'm wrapping is wxWidgets. Every widget inherits
> wxEvtHandler and that
> class has a method called Bind() that is used to connect events to an
> event handler. A stupid example:
>
> class MyClass {
>     void init ()
>     {
>         b = wxButton (frm, -1, "Some button");
>         b->Bind (wxEVT_COMMAND_BUTTON_CLICKED,
> &MyClass::HandleButtonClick, this);
>     }
>
>     void HandleButtonClick (wxCommandEvent& ev)
>     {
>         printf ("Button clicked.\n");
>     }
> }
>
> My dream API for this in Lua would be:
>
>     b = wx.Button (frm, -1, "Some button")
>     b.on_click = function ()
>         print ("Button clicked.\n")
>     end

This should be possible by doing something like:

  template <unsigned Event>
  void bind_wx_event(
    luabind::object const& self,
    luabind::object const& handler)
  {
    luabind::object_cast<wxEvtHandler*>(self)->Bind(handler, self);
  }

  void no_read(wxEvtHandler&)
  {
    throw std::runtime_error("can't read");
  }

  ...

  class_<wxEvtHandler>("wxEvtHandler");
  class_<wxButton, wxEvtHandler>(wxButton)
    .property("on_click", no_read, bind_wx_event<wxEVT_COMMAND_BUTTON_CLICKED>);

The easiest way to make that less repetitive would be to just use a
macro for it:

  #define EVT_PROPERTY(name, id) property(#name, no_read, bind_wx_event<id>)

> Or, even better:
>
>     b.on_click:add (function ()
>         print ("Button clicked, with multiple event handlers.\n")
>     end

That would be possible in the same way, but you'd need to return a
proxy object from the property accessor.

> I guess I could live with something like this, which is more like the
> C++ API:
>
>     b.bind (wx.EVT_COMMAND_BUTTON_CLICKED, function (ev)
>         print ("Button clicked again...\n")
>     end)

I'm not sure if it helps any in this case, but it is also possible to
extend the exported classes from Lua. So for instance, if you have the
above API and want to make it better, you should be able to do
something like:

  function no_read()
     error("can't read")
  end

  wxButton.on_read = property(no_read, function(self, handler)
       self:Bind(wx.EVT_COMMAND_BUTTON_CLICKED, handler)
     end)

this can be helpful since it's easier to automate these kinds of things in Lua.

Does any of this help?

--
Daniel Wallin
BoostPro Computing
http://www.boostpro.com

------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user
Reply | Threaded
Open this post in threaded view
|

Re: Implementing event handler for objects

Jonatan Magnusson-2
In reply to this post by Jason McKesson

Hi,


>
> I love Luabind. Really, I do. But it's simply not the best tool for
> every Lua association task.
>

I really liked Luabind as well, but I decided to try out SWIG anyway and
I think you're right. The flexibility of SWIG is really handy and
writing the interfaces are very simple, since they are in most cases
just stripped down header files.

I might choose Luabind in the future for other, smaller projects, but
for this project where I must handle several event mechanisms and 3rd
party libraries, I will use SWIG.

> If you forced me to create a binding between wxWidgets and Lua, well,
> I'd just download wxLua. But if you forced *me* to do it myself? I'd use
> SWIG.

I'm just wrapping parts of the wxWidgets library and I also need to wrap
other similar libraries, so choosing wxLua would not solve my problem
anyway.


Regards,
Jonatan Magnusson

------------------------------------------------------------------------------
Benefiting from Server Virtualization: Beyond Initial Workload
Consolidation -- Increasing the use of server virtualization is a top
priority.Virtualization can reduce costs, simplify management, and improve
application availability and disaster protection. Learn more about boosting
the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev
_______________________________________________
luabind-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/luabind-user