XuNeo / luavgl

lua + lvgl = luavgl An optimized lvgl Lua binding
MIT License
70 stars 14 forks source link

Adding properties to LVGL objects #32

Closed jonsmirl closed 8 months ago

jonsmirl commented 8 months ago

Introduce the problem

How do I add my own properties to the LVGL objects? I want to do something like this, but this doesn't work quite right.

local function createBtn(parent, x, y, w, h, name, index)
    local root = parent:Object {
        x = x,
        y = y,
        w = w,
        h = h,
    }

    getmetatable(root).__index = {
         index = index
    }

    root:add_style(style_default, lvgl.STATE.DEFAULT)
    root:add_style(style_pressed, lvgl.STATE.PRESSED)

    root:onevent(lvgl.EVENT.CLICKED, function (obj, code)
        print(obj.index_, " clicked")
    end)

Proposal

No response

jonsmirl commented 8 months ago

I don't understand why this prints add_style, add_style is defined so why is it calling __index?

local function createBtn(parent, x, y, w, h, name, index)
    local root = parent:Object {
        x = x,
        y = y,
        w = w,
        h = h,
    }
    local meta = getmetatable(root)
    meta.index = index
    meta.__index = function(t, _k)
        print("JDS1", _k)
        return 13
      end

    root:add_style(style_default, lvgl.STATE.DEFAULT)

prints

JDS1    add_style
/init.lua:47: attempt to call a number value (method 'add_style')
stack traceback:
    /init.lua:47: in function </init.lua:33>
    /init.lua:98: in main chunk
    [C]: in ?
jonsmirl commented 8 months ago

How do I change the group.lua example to print 1,2,3,4,5 when you click on the object instead of just the object address? From the group example:

    for _ = 1, 5 do
        local obj = root:Object({
                w = lvgl.PCT(50),
                h = lvgl.PCT(50),
                bg_color = "#555",
            })

        obj:add_style(style, lvgl.STATE.FOCUSED)

        obj:onClicked(function(obj, code)
            print("clicked: ", obj)
        end)

        obj:onevent(lvgl.EVENT.FOCUSED, function(obj, code)
            print("focused: ", obj)
            obj:scroll_to_view(true)
        end)

        obj:onevent(lvgl.EVENT.DEFOCUSED, function(obj, code)
            print("defocused: ", obj)
        end)

        g:add_obj(obj)
    end
XuNeo commented 8 months ago

Simpler issue first.

How do I change the group.lua example to print 1,2,3,4,5

You can print the value _ directly. Lua will store this var in upvalue I think.

        obj:onClicked(function(obj, code)
            print("clicked: ", obj, "index: ", _) -- better name var _ to `index` etc.
        end)
jonsmirl commented 8 months ago

Thanks, this worked which is enough to get me started. I had to be able to identify which button was being clicked.

local function createBtn(parent, x, y, w, h, name, index)
    local root = parent:Object {
        x = x,
        y = y,
        w = w,
        h = h,
    }

    root:add_style(style_default, lvgl.STATE.DEFAULT)
    root:add_style(style_pressed, lvgl.STATE.PRESSED)

    root:onevent(lvgl.EVENT.CLICKED, function (obj, code)
        print(obj, " clicked", index)
    end)
lv_obj: 0x3fcf1f40   pressed    4
lv_obj: 0x3fcf1f40   released   4
lv_obj: 0x3fcf1f40   short clicked  4
lv_obj: 0x3fcf1f40   clicked    4
lv_obj: 0x3fccb0bc   pressed    1
lv_obj: 0x3fccb0bc   released   1
lv_obj: 0x3fccb0bc   short clicked  1
lv_obj: 0x3fccb0bc   clicked    1
lv_obj: 0x3fce3658   pressed    5
lv_obj: 0x3fce3658   released   5
lv_obj: 0x3fce3658   short clicked  5
lv_obj: 0x3fce3658   clicked    5
XuNeo commented 8 months ago

I don't understand why this prints add_style, add_style is defined so why is it calling __index?

This is lua's behavior. So you have replaced userdata root's metatable which originaly includes a table __index that include key add_style. Now the metatable.__index is changed to your custom function, thus it cannot find original add_style.

I guess you want to play with obj's metatable, but be aware that the obj is a userdata which is different than table.

The easier way to add your own property and the obj to a table. For example:

local my_root = {}
my_root.widget = lvgl.Object(nil, {})
my_root.name = "root"

Or you can use table's metatable.

local root = lvgl.Object(nil, {})

local obj = {}

local meta = getmetatable(root)
setmetatable(obj, meta)

obj.add_flag(root, lvgl.FLAG.CLICKABLE) -- manually pass the first argument as obj
obj.a = "hello"
print("Access", obj.a)
jonsmirl commented 8 months ago

Most recently I have been programming in Kotlin. In Kotlin you can do things like this:

for (i in 1..5) {
    makebutton(onclick={print(i)})
}

I was trying to figure out how to make something similar to those lambdas in Lua. The info I was missing was the up variable, which you pointed out above.

jonsmirl commented 8 months ago

I have this working now, upvalue was the clue I needed.