Jonatan
Jonatan

Reputation: 3992

Handle event callbacks with Luabind

I'm adding scripting with Lua to an application of ours, and I need to implement bindings for the GUI-toolkit. The toolkit we use is wxWidgets.

I'm using Lua 5.1 and luabind 0.9.1, and it has worked very well so far. However, I'm not sure how to best handle events. For example, if you want to create a button and print a string when it is clicked, you write something like this in C++

class MyClass : public wxFrame
{
    MyClass (...)
    {
        b = new wxButton (this, -1, "Click me");
        b->Bind (wxEVT_COMMAND_BUTTON_CLICKED, &MyClass::HandleButtonClick, this);
    }

    void HandleButtonClick (wxCommandEvent& ev)
    {
        wxMessageBox ("You clicked me");
    }
}

My dream-API for doing the same thing in Lua would look something like this:

b = wx.Button (frm, -1, "Click me")
b.on_click = function (ev)
    print ("Button clicked")
end

Or, allowing multiple event handlers:

b.on_click:add (function (ev)
    print ("Button clicked again ...")
end)

If not possible, something like this which more resembles the C++ API:

b.bind (wx.EVT_COMMAND_BUTTON_CLICKED, function (ev)
    print ("Yet again")
end)

However, I'm not sure how to implement this using Luabind without writing a wrapper class for every class in the wxWidgets-library that I want to use.

Any suggestions?

Could perhaps Luabind create helper classes (say "wxLuaEventPropagator") automatically in some way? So that the wxButton class has a nested wxLuaEventPropagator-class for each event ("on_click", and so on). Once again, i do not want to create wrapper classes for every class in wxWidgets that I use, since there is a ton.

(Yes, I'm aware of wxLua)

Upvotes: 27

Views: 2201

Answers (1)

Congelli501
Congelli501

Reputation: 2593

You can use luabind::object to do that.

An exemple class : class MyClass { public: void OnMouseMoved(int x, int y); void SetEventFunction(const luabind::object &fn);

private:
    luabind::object m_eventFunction;
};


void MyClass::SetEventFunction(const luabind::object &fn)
{
    if(luabind::type(fn) == LUA_TFUNCTION)
    {
        cout << "A function" << endl;
        m_eventFunction = fn;
    }
    else
    {
        cout << "Not a function" << endl;
    }
}

void MyClass::OnMouseMoved(int x, int y)
{
    if(m_eventFunction.is_valid())
    {
        luabind::call_function<void>(m_eventFunction, x, y);
    }
}

In lua code, it would be :

myClass = MyClass()

myClass:SetEventFunction( function (x, y)
    print ("The new mouse position is", x, y)
end)

To had more than one function to an event, you can use std::vector of luabind::object

Upvotes: 2

Related Questions