#344 added focus navigation to checkboxes and radio buttons, refactor of enable handlers

This commit is contained in:
Mikayla Fischler 2023-09-23 14:31:37 -04:00
parent 1f9743efd0
commit 645a5f5137
8 changed files with 100 additions and 31 deletions

View File

@ -321,6 +321,12 @@ function element.new(args, child_offset_x, child_offset_y)
---@param id element_id element identifier ---@param id element_id element identifier
function protected.on_removed(id) end function protected.on_removed(id) end
-- handle enabled
function protected.on_enabled() end
-- handle disabled
function protected.on_disabled() end
-- handle this element having been focused -- handle this element having been focused
function protected.on_focused() end function protected.on_focused() end
@ -369,12 +375,6 @@ function element.new(args, child_offset_x, child_offset_y)
---@param max integer maximum allowed value ---@param max integer maximum allowed value
function protected.set_max(max) end function protected.set_max(max) end
-- enable the control
function protected.enable() end
-- disable the control
function protected.disable() end
-- custom recolor command, varies by element if implemented -- custom recolor command, varies by element if implemented
---@vararg cpair|color color(s) ---@vararg cpair|color color(s)
function protected.recolor(...) end function protected.recolor(...) end
@ -599,7 +599,7 @@ function element.new(args, child_offset_x, child_offset_y)
function public.enable() function public.enable()
if not protected.enabled then if not protected.enabled then
protected.enabled = true protected.enabled = true
protected.enable() protected.on_enabled()
end end
end end
@ -607,7 +607,7 @@ function element.new(args, child_offset_x, child_offset_y)
function public.disable() function public.disable()
if protected.enabled then if protected.enabled then
protected.enabled = false protected.enabled = false
protected.disable() protected.on_disabled()
public.unfocus_all() public.unfocus_all()
end end
end end

View File

@ -22,6 +22,7 @@ local function checkbox(args)
assert(type(args.box_fg_bg) == "table", "graphics.elements.controls.checkbox: box_fg_bg is a required field") assert(type(args.box_fg_bg) == "table", "graphics.elements.controls.checkbox: box_fg_bg is a required field")
assert(type(args.callback) == "function", "graphics.elements.controls.checkbox: callback is a required field") assert(type(args.callback) == "function", "graphics.elements.controls.checkbox: callback is a required field")
args.can_focus = true
args.height = 1 args.height = 1
args.width = 3 + string.len(args.label) args.width = 3 + string.len(args.label)
@ -53,6 +54,21 @@ local function checkbox(args)
end end
end end
-- write label text
local function draw_label()
if e.enabled and e.is_focused() then
e.w_set_cur(3, 1)
e.w_set_fgd(e.fg_bg.bkg)
e.w_set_bkg(e.fg_bg.fgd)
e.w_write(args.label)
else
e.w_set_cur(3, 1)
e.w_set_fgd(e.fg_bg.fgd)
e.w_set_bkg(e.fg_bg.bkg)
e.w_write(args.label)
end
end
-- handle mouse interaction -- handle mouse interaction
---@param event mouse_interaction mouse event ---@param event mouse_interaction mouse event
function e.handle_mouse(event) function e.handle_mouse(event)
@ -63,6 +79,18 @@ local function checkbox(args)
end end
end end
-- handle keyboard interaction
---@param event key_interaction key event
function e.handle_key(event)
if event.type == core.events.KEY_CLICK.DOWN then
if event.key == keys.space or event.key == keys.enter or event.key == keys.numPadEnter then
e.value = not e.value
draw()
args.callback(e.value)
end
end
end
-- set the value -- set the value
---@param val integer new value ---@param val integer new value
function e.set_value(val) function e.set_value(val)
@ -70,14 +98,17 @@ local function checkbox(args)
draw() draw()
end end
-- write label text -- handle focus
e.w_set_cur(3, 1) e.on_focused = draw_label
e.w_set_fgd(e.fg_bg.fgd) e.on_unfocused = draw_label
e.w_set_bkg(e.fg_bg.bkg)
e.w_write(args.label) -- handle enable
e.on_enabled = draw_label
e.on_disabled = draw_label
-- initial draw -- initial draw
draw() draw()
draw_label()
return e.complete() return e.complete()
end end

View File

@ -178,7 +178,7 @@ local function hazard_button(args)
end end
-- show the button as disabled -- show the button as disabled
function e.disable() function e.on_disabled()
if args.dis_colors then if args.dis_colors then
draw_border(args.dis_colors.color_a) draw_border(args.dis_colors.color_a)
e.w_set_fgd(args.dis_colors.color_b) e.w_set_fgd(args.dis_colors.color_b)
@ -188,7 +188,7 @@ local function hazard_button(args)
end end
-- show the button as enabled -- show the button as enabled
function e.enable() function e.on_enabled()
draw_border(args.accent) draw_border(args.accent)
e.w_set_fgd(args.fg_bg.fgd) e.w_set_fgd(args.fg_bg.fgd)
e.w_set_cur(3, 2) e.w_set_cur(3, 2)

View File

@ -112,7 +112,7 @@ local function push_button(args)
end end
-- show butten as enabled -- show butten as enabled
function e.enable() function e.on_enabled()
if args.dis_fg_bg ~= nil then if args.dis_fg_bg ~= nil then
e.value = false e.value = false
e.w_set_fgd(e.fg_bg.fgd) e.w_set_fgd(e.fg_bg.fgd)
@ -122,7 +122,7 @@ local function push_button(args)
end end
-- show button as disabled -- show button as disabled
function e.disable() function e.on_disabled()
if args.dis_fg_bg ~= nil then if args.dis_fg_bg ~= nil then
e.value = false e.value = false
e.w_set_fgd(args.dis_fg_bg.fgd) e.w_set_fgd(args.dis_fg_bg.fgd)
@ -131,7 +131,7 @@ local function push_button(args)
end end
end end
-- handle focus change -- handle focus
e.on_focused = show_pressed e.on_focused = show_pressed
e.on_unfocused = show_unpressed e.on_unfocused = show_unpressed

View File

@ -33,9 +33,6 @@ local function radio_button(args)
assert(type(args.min_width) == "nil" or (type(args.min_width) == "number" and args.min_width > 0), assert(type(args.min_width) == "nil" or (type(args.min_width) == "number" and args.min_width > 0),
"graphics.elements.controls.radio_button: min_width must be nil or a number > 0") "graphics.elements.controls.radio_button: min_width must be nil or a number > 0")
-- one line per option
args.height = #args.options
-- determine widths -- determine widths
local max_width = 1 local max_width = 1
for i = 1, #args.options do for i = 1, #args.options do
@ -47,11 +44,16 @@ local function radio_button(args)
local button_text_width = math.max(max_width, args.min_width or 0) local button_text_width = math.max(max_width, args.min_width or 0)
-- set automatic args
args.can_focus = true
args.width = button_text_width + 2 args.width = button_text_width + 2
args.height = #args.options -- one line per option
-- create new graphics element base object -- create new graphics element base object
local e = element.new(args) local e = element.new(args)
local focused_opt = 1
-- button state (convert nil to 1 if missing) -- button state (convert nil to 1 if missing)
e.value = args.default or 1 e.value = args.default or 1
@ -74,8 +76,14 @@ local function radio_button(args)
e.w_write("\x95") e.w_write("\x95")
-- write button text -- write button text
if i == focused_opt and e.is_focused() and e.enabled then
e.w_set_fgd(e.fg_bg.bkg)
e.w_set_bkg(e.fg_bg.fgd)
else
e.w_set_fgd(e.fg_bg.fgd) e.w_set_fgd(e.fg_bg.fgd)
e.w_set_bkg(e.fg_bg.bkg) e.w_set_bkg(e.fg_bg.bkg)
end
e.w_write(opt) e.w_write(opt)
end end
end end
@ -93,6 +101,28 @@ local function radio_button(args)
end end
end end
-- handle keyboard interaction
---@param event key_interaction key event
function e.handle_key(event)
if event.type == core.events.KEY_CLICK.DOWN then
if event.key == keys.space or event.key == keys.enter or event.key == keys.numPadEnter then
e.value = focused_opt
draw()
args.callback(e.value)
elseif event.key == keys.down then
if focused_opt < #args.options then
focused_opt = focused_opt + 1
draw()
end
elseif event.key == keys.up then
if focused_opt > 1 then
focused_opt = focused_opt - 1
draw()
end
end
end
end
-- set the value -- set the value
---@param val integer new value ---@param val integer new value
function e.set_value(val) function e.set_value(val)
@ -100,6 +130,14 @@ local function radio_button(args)
draw() draw()
end end
-- handle focus
e.on_focused = draw
e.on_unfocused = draw
-- handle enable
e.on_enabled = draw
e.on_disabled = draw
-- initial draw -- initial draw
draw() draw()

View File

@ -176,12 +176,12 @@ local function spinbox(args)
end end
-- enable this input -- enable this input
function e.enable() function e.on_enabled()
draw_arrows(args.arrow_fg_bg.fgd) draw_arrows(args.arrow_fg_bg.fgd)
end end
-- disable this input -- disable this input
function e.disable() function e.on_disabled()
draw_arrows(args.arrow_disable or colors.lightGray) draw_arrows(args.arrow_disable or colors.lightGray)
end end

View File

@ -158,9 +158,9 @@ local function number_field(args)
ifield.show() ifield.show()
end end
-- on enable/disable -- handle enable
e.enable = ifield.show e.on_enabled = ifield.show
e.disable = ifield.show e.on_disabled = ifield.show
-- initial draw -- initial draw
ifield.show() ifield.show()

View File

@ -85,9 +85,9 @@ local function text_field(args)
e.on_focused = ifield.show e.on_focused = ifield.show
e.on_unfocused = ifield.show e.on_unfocused = ifield.show
-- on enable/disable -- handle enable
e.enable = ifield.show e.on_enabled = ifield.show
e.disable = ifield.show e.on_disabled = ifield.show
-- initial draw -- initial draw
ifield.show() ifield.show()