cc-mek-scada/graphics/elements/controls/sidebar.lua
2023-04-12 12:40:13 -04:00

105 lines
3.1 KiB
Lua

-- Sidebar Graphics Element
local tcd = require("scada-common.tcallbackdsp")
local element = require("graphics.element")
---@class sidebar_tab
---@field char string character identifier
---@field color cpair tab colors (fg/bg)
---@class sidebar_args
---@field tabs table sidebar tab options
---@field callback function function to call on tab change
---@field parent graphics_element
---@field id? string element id
---@field x? integer 1 if omitted
---@field y? integer 1 if omitted
---@field height? integer parent height if omitted
---@field fg_bg? cpair foreground/background colors
-- new sidebar tab selector
---@param args sidebar_args
---@return graphics_element element, element_id id
local function sidebar(args)
assert(type(args.tabs) == "table", "graphics.elements.controls.sidebar: tabs is a required field")
assert(#args.tabs > 0, "graphics.elements.controls.sidebar: at least one tab is required")
assert(type(args.callback) == "function", "graphics.elements.controls.sidebar: callback is a required field")
-- always 3 wide
args.width = 3
-- create new graphics element base object
local e = element.new(args)
assert(e.frame.h >= (#args.tabs * 3), "graphics.elements.controls.sidebar: height insufficent to display all tabs")
-- default to 1st tab
e.value = 1
-- show the button state
---@param pressed boolean if the currently selected tab should appear as actively pressed
local function draw(pressed)
for i = 1, #args.tabs do
local tab = args.tabs[i] ---@type sidebar_tab
local y = ((i - 1) * 3) + 1
e.window.setCursorPos(1, y)
if pressed and e.value == i then
e.window.setTextColor(e.fg_bg.fgd)
e.window.setBackgroundColor(e.fg_bg.bkg)
else
e.window.setTextColor(tab.color.fgd)
e.window.setBackgroundColor(tab.color.bkg)
end
e.window.write(" ")
e.window.setCursorPos(1, y + 1)
if e.value == i then
-- show as selected
e.window.write(" " .. tab.char .. "\x10")
else
-- show as unselected
e.window.write(" " .. tab.char .. " ")
end
e.window.setCursorPos(1, y + 2)
e.window.write(" ")
end
end
-- handle mouse interaction
---@param event mouse_interaction mouse event
function e.handle_mouse(event)
-- determine what was pressed
if e.enabled then
local idx = math.ceil(event.y / 3)
if args.tabs[idx] ~= nil then
e.value = idx
draw(true)
-- show as unpressed in 0.25 seconds
tcd.dispatch(0.25, function () draw(false) end)
args.callback(e.value)
end
end
end
-- set the value
---@param val integer new value
function e.set_value(val)
e.value = val
draw(false)
end
-- initial draw
draw(false)
return e.get()
end
return sidebar