[solved] GUI: textbox.state_focussed

Discussion of Lua and LuaWML support, development, and ideas.

Moderator: Forum Moderators

Post Reply
white_haired_uncle
Posts: 1204
Joined: August 26th, 2018, 11:46 pm
Location: A country place, far outside the Wire

[solved] GUI: textbox.state_focussed

Post by white_haired_uncle »

This is a stupid little example, just for learning. I have a slider and a textbox, and I want each to update the other when they are changed. The slider works (text box updates when slider moves), but I have some issues with the textbox.

Code: Select all

function wesnoth.wml_actions.current_test_gui()
        local dialogDefinition = {
                wml.tag.tooltip { id = "tooltip_large" },
                wml.tag.helptip { id = "helptip_large" },
                wml.tag.grid {
                        wml.tag.row {
                                wml.tag.column {
                                        wml.tag.label { label = _"How much gold will you pay for this old rusty sword?" }
                                }
                        },
                        wml.tag.row {
                                wml.tag.column {
                                        horizontal_grow = true,
                                        grow_factor = 1,
                                        wml.tag.slider {
                                                id = "gold_sl",
                                                right_offset = 120,
                                                minimum_value = 0,
                                                maximum_value = wesnoth.sides[wesnoth.current.side].gold,
                                                value = math.floor(wesnoth.sides[wesnoth.current.side].gold/2)
                                        }
                                }
                        },
                        wml.tag.row {
                                wml.tag.column {
                                        wml.tag.text_box {
                                                id = "gold_tb",
                                                label = tostring(math.floor(wesnoth.sides[wesnoth.current.side].gold/2))
                                        }
                                }
                        },
                        wml.tag.row {
                                wml.tag.column {
                                        wml.tag.text_box {
                                                id = "gold_tb",
                                                label = tostring(math.floor(wesnoth.sides[wesnoth.current.side].gold/2))
                                        }
                                }
                        },

                        wml.tag.row {
                                wml.tag.column {
                                        wml.tag.button {
                                                id = "ok",
                                                label = _"OK"
                                        }
                                }
                        }
                }
        }
        local function preshow(dialog)
                local function show_input()
                        wesnoth.interface.add_chat_message(_"You chose " .. dialog.gold_sl.value .. _" with the slider")
                        wesnoth.interface.add_chat_message(_"You entered " .. tostring(dialog.gold_tb.text) .. _" in the text_box")
                end
                dialog.ok.on_button_click = show_input

                dialog.gold_sl.on_modified=function()dialog.gold_tb.text = tostring(dialog.gold_sl.value)end

                local function text2string()
                        --if dialog.gold_tb.state_focussed then return nil end
                        local input = tonumber(dialog.gold_tb.text)
                        if type(input) ~= "number" then
                                wesnoth.message("NO!!!")
                        else
                                if input > 0 and input <= wesnoth.sides[wesnoth.current.side].gold then
                                        dialog.gold_sl.value=input
                                end
                        end
                end
                --dialog.gold_tb.on_modified = text2string()   -- core dumps bfw
                --dialog.gold_tb.on_modified = text2string     -- works, but kludgy
                
                
                

                if wesnoth.current_version() >= wesnoth.version "1.17.0" then
                        wesnoth.print_attributes(dialog.gold_sl)
                        gui.show_lua_console()
                end
        end

        gui.show_dialog(dialogDefinition,preshow)
end
At first, I just used

Code: Select all

 dialog.gold_tb.on_modified = text2string 
that worked more or less, but it moved the slider every time I made ANY change to the text box. For instance, if I typed in 9999, the slider would move to 9, then 99, and then do nothing because 999>gold.

What I want is to let the user finish typing in the text_box, then evaluate the input, then move the slider (or popup an error) as necessary. The only thing I could find that looked like it might work was to check for focus. In hindsight, this may not make any sense, as you may not be able to fire on_modified unless the tb is focused (or focussed, never seen that spelling before). Anyway, devdocs says state_focussed is valid for text_box, but "error scripting/lua: invalid property of 'N4gui28text_boxE' widget :state_focussed"

1) Is text_box.state_focussed valid?
2) Does this approach make any sense, and/or is there a better way to do this (wait to update the slider until user is finished with input and input is validated).
3) I'm not sure about my approach to checking if input is a number (tonumber, then check the result???). Minimal testing seems to look okay, but I'm suspicious. assert(type(dialog.gold_tb.text) == "number") perhaps? Never used assert, but it looks promising.
4) Any comments on my attempt to use short circuit evaluation like this?

Code: Select all

dialog.gold_tb.on_modified = function()return not dialog.gold_tb.state_focussed and text2string() end
Last edited by white_haired_uncle on January 19th, 2024, 10:35 am, edited 1 time in total.
Speak softly, and carry Doombringer.
gfgtdf
Developer
Posts: 1432
Joined: February 10th, 2013, 2:25 pm

Re: GUI: textbox.state_focussed

Post by gfgtdf »

white_haired_uncle wrote: January 18th, 2024, 7:25 pm
that worked more or less, but it moved the slider every time I made ANY change to the text box. For instance, if I typed in 9999, the slider would move to 9, then 99, and then do nothing because 999>gold.

What I want is to let the user finish typing in the text_box, then evaluate the input, then move the slider (or popup an error) as necessary. The only thing I could find that looked like it might work was to check for focus. In hindsight, this may not make any sense, as you may not be able to fire on_modified unless the tb is focused (or focussed, never seen that spelling before). Anyway, devdocs says state_focussed is valid for text_box, but "error scripting/lua: invalid property of 'N4gui28text_boxE' widget :state_focussed"

1) Is text_box.state_focussed valid?
No the only attributes you can set/set via the lua widget objects are described in https://wiki.wesnoth.org/LuaAPI/types/widget
white_haired_uncle wrote: January 18th, 2024, 7:25 pm 2) Does this approach make any sense, and/or is there a better way to do this (wait to update the slider until user is finished with input and input is validated).
I don't think that is possible currently. could file a feature request for more callbacks, but you'd need to know what exactly do you want, meaning when exactly do you want the slider to update, also since we are more or less in a feature freeze for 1.17 it probably won't happen soon.
white_haired_uncle wrote: January 18th, 2024, 7:25 pm 3) I'm not sure about my approach to checking if input is a number (tonumber, then check the result???). Minimal testing seems to look okay, but I'm suspicious. assert(type(dialog.gold_tb.text) == "number") perhaps? Never used assert, but it looks promising.
assert looks even more wrong for this, assert only gives an error when the condition is wrong, its a debug tool not something for control progam flow.
Scenario with Robots SP scenario (1.11/1.12), allows you to build your units with components, PYR No preperation turn 1.12 mp-mod that allows you to select your units immideately after the game begins.
User avatar
Celtic_Minstrel
Developer
Posts: 2235
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: GUI: textbox.state_focussed

Post by Celtic_Minstrel »

white_haired_uncle wrote: January 18th, 2024, 7:25 pm Anyway, devdocs says state_focussed is valid for text_box, but "error scripting/lua: invalid property of 'N4gui28text_boxE' widget :state_focussed"
The properties documented in the devdocs mainly describe the WML format for defining a widget. It means that you can put a [state_focused] tag in your textbox definition, but doesn't mean anything with respect to the Lua API.
white_haired_uncle wrote: January 18th, 2024, 7:25 pm 3) I'm not sure about my approach to checking if input is a number (tonumber, then check the result???). Minimal testing seems to look okay, but I'm suspicious. assert(type(dialog.gold_tb.text) == "number") perhaps? Never used assert, but it looks promising.
There's no reason to use assert, as that raises an error that terminates the script entirely, (or if pcall was used, winding back to that point in the script). Your description of the approach is fine, however. The tonumber function returns nil if the input is not a number, so one approach would be:

Code: Select all

local n = tonumber(dialog.gold_tb.text)
if n then
	dialog.gold_sl.value = n
end
The type function however will not work, as dialog.gold_tb.text is always a string even if it happens to be numerical.
white_haired_uncle wrote: January 18th, 2024, 7:25 pm 4) Any comments on my attempt to use short circuit evaluation like this?

Code: Select all

dialog.gold_tb.on_modified = function()return not dialog.gold_tb.state_focussed and text2string() end
Even ignoring the fact that state_focussed is not a valid attribute, what you're doing here makes no sense. I'm not 100% certain, as the documentation could be missing something, but I don't think on_modified has a return value in the first place. So it would make more sense to write that as an if statement: if not dialog.whatever then text2string() end
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
Post Reply