Created
March 2, 2023 19:25
-
-
Save Andre-LA/672e1b44bbb56e9525dd88069f2bc3fe to your computer and use it in GitHub Desktop.
nelua "Handles"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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