forked from your-land-mirror/minetest-flow
Add on_key_enter callback and close_on_enter
Closes https://gitlab.com/luk3yx/minetest-flow/-/issues/4
This commit is contained in:
parent
7bad88cdcd
commit
e3dc6d6750
38
README.md
38
README.md
@ -622,4 +622,42 @@ end)
|
||||
If multiple `on_quit` callbacks are specified in different elements, they will
|
||||
all get called.
|
||||
|
||||
</details><details>
|
||||
<summary><b>Handling enter keypresses in fields</b></summary>
|
||||
|
||||
`gui.Field` and `gui.Pwdfield` support an `on_key_enter` callback that gets
|
||||
called if enter is pressed:
|
||||
|
||||
```lua
|
||||
local form = flow.make_gui(function(player, ctx)
|
||||
return gui.VBox{
|
||||
gui.Field{
|
||||
label = "Press enter!",
|
||||
name = "field",
|
||||
on_key_enter = function(player, ctx)
|
||||
core.chat_send_player(player:get_player_name(),
|
||||
"Field value: " .. dump(ctx.form.field))
|
||||
end,
|
||||
|
||||
-- You can also specify close_on_enter to close the form when enter
|
||||
-- is pressed.
|
||||
close_on_enter = true,
|
||||
},
|
||||
}
|
||||
end)
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- If you're using this callback, please make sure there's some other way to
|
||||
trigger the enter action (like a button) to support older flow versions and
|
||||
in case I replace this API with a better one in the future.
|
||||
- If you want recent mobile clients to call this callback when editing text,
|
||||
add `enter_after_edit = true` to the field definition.
|
||||
- The similarly named `on_event` gets called whenever the client submits the
|
||||
field to the server, which could be at any time, and is not very useful, but
|
||||
is still supported for compatibility (and there may be uses for it, such as
|
||||
sanitising field values). Be careful not to accidentally use the wrong
|
||||
callback.
|
||||
|
||||
</details>
|
||||
|
29
init.lua
29
init.lua
@ -200,11 +200,13 @@ local function insert_shorthand_elements(tree)
|
||||
if node.type == "container" or node.type == "scroll_container" then
|
||||
insert_shorthand_elements(node)
|
||||
elseif node.type == "field" then
|
||||
table.insert(tree, i, {
|
||||
type = 'field_close_on_enter',
|
||||
name = node.name,
|
||||
close_on_enter = false,
|
||||
})
|
||||
if not node.close_on_enter then
|
||||
table.insert(tree, i, {
|
||||
type = 'field_close_on_enter',
|
||||
name = node.name,
|
||||
close_on_enter = false,
|
||||
})
|
||||
end
|
||||
|
||||
if node.enter_after_edit then
|
||||
table.insert(tree, i, {
|
||||
@ -250,9 +252,8 @@ function Form:_render(player, ctx, formspec_version, id1, embedded, lang_code)
|
||||
if not id1 or id1 > 1e6 then id1 = 0 end
|
||||
|
||||
local tree = render_ast(box, embedded)
|
||||
local callbacks, btn_callbacks, saved_fields, id2 = parse_callbacks(
|
||||
tree, orig_form, id1, embedded, formspec_version
|
||||
)
|
||||
local callbacks, btn_callbacks, saved_fields, id2, on_key_enters =
|
||||
parse_callbacks(tree, orig_form, id1, embedded, formspec_version)
|
||||
|
||||
-- This should be after parse_callbacks so it can take advantage of
|
||||
-- automatic field naming
|
||||
@ -274,6 +275,7 @@ function Form:_render(player, ctx, formspec_version, id1, embedded, lang_code)
|
||||
callbacks = callbacks,
|
||||
btn_callbacks = btn_callbacks,
|
||||
saved_fields = saved_fields,
|
||||
on_key_enters = on_key_enters,
|
||||
redraw_if_changed = redraw_if_changed,
|
||||
ctx = ctx,
|
||||
auto_name_id = id2,
|
||||
@ -496,6 +498,17 @@ function fs_process_events(player, form_info, fields)
|
||||
end
|
||||
end
|
||||
|
||||
-- Run on_key_enter callbacks
|
||||
if fields.key_enter and form_info.on_key_enters then
|
||||
local callback = form_info.on_key_enters[fields.key_enter_field]
|
||||
if callback then
|
||||
-- Enter callbacks and button fields can't be sent at the same
|
||||
-- time (except from a hacked client), so make sure they aren't
|
||||
-- both processed at once by returning now.
|
||||
return callback(player, ctx) or redraw_fs
|
||||
end
|
||||
end
|
||||
|
||||
-- Run button callbacks after all other callbacks as that seems to be the
|
||||
-- most intuitive thing to do
|
||||
-- Note: Try not to rely on the order of on_event callbacks, I may change
|
||||
|
23
input.lua
23
input.lua
@ -155,7 +155,7 @@ local button_types = {
|
||||
-- Removes on_event from a formspec_ast tree and returns a callbacks table
|
||||
local function parse_callbacks(tree, ctx_form, auto_name_id,
|
||||
replace_backgrounds, formspec_version)
|
||||
local callbacks
|
||||
local callbacks, on_key_enters
|
||||
local btn_callbacks = {}
|
||||
local saved_fields = {}
|
||||
local tablecolumn_count = 1
|
||||
@ -297,13 +297,32 @@ local function parse_callbacks(tree, ctx_form, auto_name_id,
|
||||
node.on_event = nil
|
||||
end
|
||||
|
||||
local is_field = node.type == "field" or node.type == "pwdfield"
|
||||
if node.on_key_enter and node_name then
|
||||
if is_field then
|
||||
on_key_enters = on_key_enters or {}
|
||||
if on_key_enters[node_name] then
|
||||
error(("Multiple on_key_enter callbacks registered for " ..
|
||||
"elements with the same name (%q)"):format(node_name))
|
||||
end
|
||||
on_key_enters[node_name] = node.on_key_enter
|
||||
else
|
||||
core.log("warning",
|
||||
"[flow] on_key_enter only works with Field and Pwdfield")
|
||||
end
|
||||
node.on_key_enter = nil
|
||||
elseif is_field and node.close_on_enter then
|
||||
core.log("warning", ("[flow] Field %q has close_on_enter " ..
|
||||
"enabled but no on_key_enter callback."):format(node_name))
|
||||
end
|
||||
|
||||
-- Call _after_positioned (used internally for ScrollableVBox)
|
||||
if node._after_positioned then
|
||||
node:_after_positioned()
|
||||
node._after_positioned = nil
|
||||
end
|
||||
end
|
||||
return callbacks, btn_callbacks, saved_fields, auto_name_id
|
||||
return callbacks, btn_callbacks, saved_fields, auto_name_id, on_key_enters
|
||||
end
|
||||
|
||||
return parse_callbacks
|
||||
|
Loading…
Reference in New Issue
Block a user