diff --git a/test_ui.lua b/test_ui.lua new file mode 100644 index 0000000..64dd99b --- /dev/null +++ b/test_ui.lua @@ -0,0 +1,33 @@ +require("oct_utils") +require("termbox_defs") +require("ui") + +--textbox = oct_tb_sprite_new() +textbox = {} + +function oct_init() + -- textbox["x"] = 50 + -- textbox["y"] = 20 + -- textbox["shape"] = "___________" + -- textbox["fg"] = TB_RED + textbox1 = create_textbox("textbox1", 50, 20, 20) + textbox2 = create_textbox("textbox2", 50, 22, 20) + textbox3 = create_textbox("textbox3", 50, 24, 20) + register_textbox(textbox1) + register_textbox(textbox1) + register_textbox(textbox2) + register_textbox(textbox3) + unregister_textbox(textbox2) + unregister_textbox(textbox2) + + return OCT_NOT_NEEDS_NETWORKING, OCT_NEEDS_TERMBOX +end + +function oct_loop(key, ch) + textbox_contents = handle_textbox(key, ch) + if (textbox_contents) + then + OCT_LOG_DEBUG("Received string from textbox: " .. table_to_string(textbox_contents)) + end + +end diff --git a/ui.lua b/ui.lua new file mode 100644 index 0000000..577314e --- /dev/null +++ b/ui.lua @@ -0,0 +1,129 @@ +-- Contains user interface elements +require("oct_utils") +require("termbox_defs") + + +-- visible_textboxes is a global list of all textboxes we can cycle through +-- it is, in principle, a circular list +-- the top of the list is the currently selected textbox +-- upon a switch (i.e. TAB key), the list is rotated +registered_textboxes = {} + +function create_textbox(id, pos_x, pos_y, max_length) + t = oct_tb_sprite_new() + t["x"] = pos_x + t["y"] = pos_y + t["shape"] = string.rep("_", max_length) -- what is displayed to user + t["fg"] = TB_WHITE + + local textbox = {} + textbox["sprite"] = t + textbox["contents"] = "" -- what is returned when box is submitted + textbox["max_length"] = max_length + textbox["id"] = id + return textbox +end + +function update_registered_textboxes_appearance() + -- textbox at front is focused, set to green + registered_textboxes[1]["sprite"]["fg"] = TB_GREEN + -- set all other textboxes to unfocused (white colored) + for i=2,#registered_textboxes + do + registered_textboxes[i]["sprite"]["fg"] = TB_WHITE + end +end + +function register_textbox(textbox) + already_registered = false; + for i=1,#registered_textboxes + do + if (registered_textboxes[i] == textbox) + then + already_registered = true + end + end + + if (already_registered) + then + OCT_LOG_WARNING("Attempted to register an already-registered textbox") + else + table.insert(registered_textboxes, 1, textbox) + end + + update_registered_textboxes_appearance() +end + +function unregister_textbox(textbox) + removed = false + for i=1,#registered_textboxes + do + if (registered_textboxes[i] == textbox) + then + table.remove(registered_textboxes, i) + textbox["sprite"]["fg"] = TB_WHITE + removed = true + end + end + if not removed + then + OCT_LOG_WARNING("Attempted to unregister an unregistered textbox") + end + update_registered_textboxes_appearance() +end + +function textbox_contents_to_shape(contents, max_length) + l = string.len(contents) + ret_str = "" + if (l < max_length+1) + then + ret_str = contents + n_underscores = max_length - l + ret_str = ret_str .. string.rep("_", n_underscores) + else -- show only the last max_length characters + ret_str = string.sub(contents, -max_length) + end + return ret_str +end + + +function handle_textbox(key, ch) + local to_return = nil + -- Convert ch from a character code to a character + ch = string.char(ch) + + -- if nothing was pressed, ch is '\0' (null byte) + if (ch ~= '\0') + then + -- Update the contents of the textbox, this isn't displayed by default + registered_textboxes[1]["contents"] = registered_textboxes[1]["contents"] .. ch + end + + if (key == TB_KEY_BACKSPACE2 or key == TB_KEY_BACKSPACE) + then + registered_textboxes[1]["contents"] = string.sub(registered_textboxes[1]["contents"], 1, string.len(registered_textboxes[1]["contents"])-1) + end + + -- Update the user-visible sprite + registered_textboxes[1]["sprite"]["shape"] = textbox_contents_to_shape(registered_textboxes[1]["contents"], registered_textboxes[1]["max_length"]) + + -- Submit our registered textboxes + if (key == TB_KEY_ENTER) + then + to_return = {} + for i=1,#registered_textboxes + do + curr = registered_textboxes[i] + to_return[curr["id"]] = curr["contents"] + end + end + + -- Rotate the registered textboxes + if (key == TB_KEY_TAB) + then + table.insert(registered_textboxes, 1, table.remove(registered_textboxes)) + update_registered_textboxes_appearance() + end + + return to_return +end