Re: Implementing event handler for objects

Daniel Wallin <[email protected]>
Newsgroups gmane.comp.lang.lua.bind.user
Message-ID <[email protected]>
On Wed, Apr 6, 2011 at 6:05 PM, Jonatan Magnusson <[email protected]> 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.