Skip to content

Instantly share code, notes, and snippets.

@Andre-LA
Created March 2, 2023 19:25
Show Gist options
  • Save Andre-LA/672e1b44bbb56e9525dd88069f2bc3fe to your computer and use it in GitHub Desktop.
Save Andre-LA/672e1b44bbb56e9525dd88069f2bc3fe to your computer and use it in GitHub Desktop.
nelua "Handles"
local Button = @record{
text: string,
on_mouse_down: function(btn: *Button, x: integer, y: integer),
}
## Button.value.is_widget = true -- related doc: https://nelua.io/overview/#specializing-concepts-for-records
-- let's create an alias to make this easier
local OnMouseDownCallback = @function(btn: *Button, x: integer, y: integer)
-- note: we don't need the `&` operator when binding a function to a variable/field, because
-- function types and values are references already.
function Button.init(text: string, on_mouse_down: OnMouseDownCallback): Button
return Button{
=text, -- syntax sugar to `text=text`
=on_mouse_down,
}
end
-- test without handles
-- the function we want to bind
local function btn_click(btn: *Button, x: integer, y: integer)
print(btn.text, x, y)
end
local btn1 = Button.init('Btn 1', btn_click)
btn1:on_mouse_down(20, 20) -- outputs 'Btn 1 20 20'
---
-- This is the best `Handles` mimic I can think of,
-- maybe with more metaprogramming an equivalent of VB.NET's it's possible,
-- but I think it would still use the code below.
local a_function = #[concept(function(attr) return attr.type.is_function end)]#
local a_widget_ptr = #[concept(function(attr) return attr.type.is_pointer and attr.type.subtype.is_widget end)]#
-- Note: I could use var args to better mimic Handles, but for simplicity, I'm just using a single
-- parameter.
local function handles(widget: a_widget_ptr, callback: a_function)
-- search each field of Button type, find the matching type of callback
## for _, field in ipairs(Button.value.fields) do
## if field.type == callback.type then
-- matching callback found
widget.#|field.name|# = callback
## break
## end
## end
end
-- test
local btn1 = Button.init('Btn 1')
local btn2 = Button.init('Btn 2')
-- the function we want to bind
local function btn_click_clone(btn: *Button, x: integer, y: integer)
print(btn.text, x, y)
end
-- the "Handles" after the function declaration
handles(&btn1, btn_click_clone)
handles(&btn2, btn_click_clone)
btn1:on_mouse_down(50, 50) -- outputs 'Btn 1 50 50'
btn2:on_mouse_down(30, 30) -- outputs 'Btn 2 30 30'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment