diff --git a/graphics/core.lua b/graphics/core.lua
index fe3b291..d42af53 100644
--- a/graphics/core.lua
+++ b/graphics/core.lua
@@ -124,10 +124,10 @@ end
-- Interactive Field Manager
---@param e graphics_base element
----@param max_len any max value length
----@param fg_bg any enabled fg/bg
----@param dis_fg_bg any disabled fg/bg
----@param align_right any true to align content right while unfocused
+---@param max_len integer max value length
+---@param fg_bg cpair enabled fg/bg
+---@param dis_fg_bg? cpair disabled fg/bg
+---@param align_right? boolean true to align content right while unfocused
function core.new_ifield(e, max_len, fg_bg, dis_fg_bg, align_right)
local self = {
frame_start = 1,
diff --git a/graphics/element.lua b/graphics/element.lua
index 1e94edd..402387b 100644
--- a/graphics/element.lua
+++ b/graphics/element.lua
@@ -11,8 +11,8 @@ local events = core.events
local element = {}
----@class graphics_args_generic
----@field window? table
+---@class graphics_args
+---@field window? Window
---@field parent? graphics_element
---@field id? string element id
---@field x? integer 1 if omitted
@@ -24,47 +24,6 @@ local element = {}
---@field hidden? boolean true to hide on initial draw
---@field can_focus? boolean true if this element can be focused, false by default
----@alias graphics_args graphics_args_generic
----|waiting_args
----|app_button_args
----|checkbox_args
----|hazard_button_args
----|multi_button_args
----|push_button_args
----|radio_2d_args
----|radio_button_args
----|sidebar_args
----|spinbox_args
----|switch_button_args
----|tabbar_args
----|number_field_args
----|text_field_args
----|alarm_indicator_light
----|core_map_args
----|data_indicator_args
----|hbar_args
----|icon_indicator_args
----|indicator_led_args
----|indicator_led_pair_args
----|indicator_led_rgb_args
----|indicator_light_args
----|power_indicator_args
----|rad_indicator_args
----|signal_bar_args
----|state_indicator_args
----|tristate_indicator_light_args
----|vbar_args
----|app_multipane_args
----|colormap_args
----|displaybox_args
----|div_args
----|listbox_args
----|multipane_args
----|pipenet_args
----|rectangle_args
----|textbox_args
----|tiling_args
-
---@class element_subscription
---@field ps psil ps used
---@field key string data key
@@ -92,14 +51,14 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
is_root = args.parent == nil,
elem_type = debug.getinfo(2).name,
define_completed = false,
- p_window = nil, ---@type table
+ p_window = nil, ---@type Window
position = events.new_coord_2d(1, 1),
bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1 }, ---@class element_bounds
offset_x = 0,
offset_y = 0,
next_y = 1, -- next child y coordinate
- next_id = 0, -- next child ID
- subscriptions = {},
+ next_id = 0, -- next child ID[
+ subscriptions = {}, ---@type { ps: psil, key: string, func: function }[]
button_down = { events.new_coord_2d(-1, -1), events.new_coord_2d(-1, -1), events.new_coord_2d(-1, -1) },
focused = false,
mt = {}
@@ -109,13 +68,13 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
local protected = {
enabled = true,
value = nil, ---@type any
- window = nil, ---@type table
- content_window = nil, ---@type table|nil
+ window = nil, ---@type Window
+ content_window = nil, ---@type Window|nil
mouse_window_shift = { x = 0, y = 0 },
fg_bg = core.cpair(colors.white, colors.black),
frame = core.gframe(1, 1, 1, 1),
- children = {},
- child_id_map = {}
+ children = {}, ---@type graphics_base[]
+ child_id_map = {} ---@type { [element_id]: integer }
}
-- element as string
@@ -168,10 +127,10 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
end
- ---@param children table
+ ---@param children graphics_base[]
local function traverse(children)
for i = 1, #children do
- local child = children[i] ---@type graphics_base
+ local child = children[i]
handle_element(child.get())
if child.get().is_visible() then traverse(child.children) end
end
@@ -286,24 +245,29 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- alias functions
- -- window set cursor position
+ -- window set cursor position
+ ---@see Window.setCursorPos
---@param x integer
---@param y integer
function protected.w_set_cur(x, y) protected.window.setCursorPos(x, y) end
- -- set background color
+ -- set background color
+ ---@see Window.setBackgroundColor
---@param c color
function protected.w_set_bkg(c) protected.window.setBackgroundColor(c) end
- -- set foreground (text) color
+ -- set foreground (text) color
+ ---@see Window.setTextColor
---@param c color
function protected.w_set_fgd(c) protected.window.setTextColor(c) end
- -- write text
+ -- write text
+ ---@see Window.write
---@param str string
function protected.w_write(str) protected.window.write(str) end
- -- blit text
+ -- blit text
+ ---@see Window.blit
---@param str string
---@param fg string
---@param bg string
@@ -335,8 +299,10 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- report completion of element instantiation and get the public interface
---@nodiscard
+ ---@param redraw? boolean true to call redraw as part of completing this element
---@return graphics_element element, element_id id
- function protected.complete()
+ function protected.complete(redraw)
+ if redraw then protected.redraw() end
if args.parent ~= nil then args.parent.__child_ready(self.id, public) end
return public, self.id
end
@@ -352,7 +318,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- focus this element and take away focus from all other elements
function protected.take_focus() args.parent.__focus_child(public) end
- -- action handlers --
+ --#region Action Handlers
-- luacheck: push ignore
---@diagnostic disable: unused-local, unused-vararg
@@ -401,14 +367,15 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
function protected.handle_paste(text) end
-- handle data value changes
- ---@vararg any value(s)
+ ---@param ... any value(s)
function protected.on_update(...) end
-- callback on control press responses
---@param result any
function protected.response_callback(result) end
- -- accessors and control --
+ --#endregion
+ --#region Accessors and Control --
-- get value
---@nodiscard
@@ -427,11 +394,11 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
function protected.set_max(max) end
-- custom recolor command, varies by element if implemented
- ---@vararg cpair|color color(s)
+ ---@param ... cpair|color color(s)
function protected.recolor(...) end
-- custom resize command, varies by element if implemented
- ---@vararg integer sizing
+ ---@param ... integer sizing
function protected.resize(...) end
-- luacheck: pop
@@ -514,6 +481,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- ELEMENT TREE --
-- add a child element
+ ---@package
---@nodiscard
---@param key string|nil id
---@param child graphics_base
@@ -523,7 +491,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
self.next_y = child.frame.y + child.frame.h
- local id = key ---@type string|integer|nil
+ local id = key ---@type element_id|nil
if id == nil then
id = self.next_id
self.next_id = self.next_id + 1
@@ -537,6 +505,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- remove a child element
+ ---@package
---@param id element_id id
function public.__remove_child(id)
local index = protected.child_id_map[id]
@@ -548,11 +517,13 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- actions to take upon a child element becoming ready (initial draw/construction completed)
+ ---@package
---@param key element_id id
---@param child graphics_element
function public.__child_ready(key, child) protected.on_added(key, child) end
-- focus solely on this child
+ ---@package
---@param child graphics_element
function public.__focus_child(child)
if self.is_root then
@@ -562,6 +533,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- a child was focused, used to make sure it is actually visible to the user in the content frame
+ ---@package
---@param child graphics_element
function public.__child_focused(child)
protected.on_child_focused(child)
@@ -571,8 +543,8 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- get a child element
---@nodiscard
---@param id element_id
- ---@return graphics_element
- function public.get_child(id) return protected.children[protected.child_id_map[id]].get() end
+ ---@return graphics_element element
+ function public.get_child(id) return ({ protected.children[protected.child_id_map[id]].get() })[1] end
-- get all children
---@nodiscard
@@ -619,7 +591,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
local elem = child.get().get_element_by_id(id)
if elem ~= nil then return elem end
end
- else return protected.children[index].get() end
+ else return ({ protected.children[index].get() })[1] end
end
-- AUTO-PLACEMENT --
@@ -631,17 +603,17 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
-- PROPERTIES --
- -- get element id
+ -- get element ID
---@nodiscard
---@return element_id
function public.get_id() return self.id end
- -- get element x
+ -- get element relative x position
---@nodiscard
---@return integer x
function public.get_x() return protected.frame.x end
- -- get element y
+ -- get element relative y position
---@nodiscard
---@return integer y
function public.get_y() return protected.frame.y end
@@ -661,12 +633,12 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
---@return cpair fg_bg
function public.get_fg_bg() return protected.fg_bg end
- -- get the element value
+ -- get the element's value
---@nodiscard
---@return any value
function public.get_value() return protected.get_value() end
- -- set the element value
+ -- set the element's value
---@param value any new value
function public.set_value(value) protected.set_value(value) end
@@ -728,11 +700,11 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- custom recolor command, varies by element if implemented
- ---@vararg cpair|color color(s)
+ ---@param ... cpair|color color(s)
function public.recolor(...) protected.recolor(...) end
-- resize attributes of the element value if supported
- ---@vararg number dimensions (element specific)
+ ---@param ... number dimensions (element specific)
function public.resize(...) protected.resize(...) end
-- reposition the element window
@@ -818,7 +790,7 @@ function element.new(args, constraint, child_offset_x, child_offset_y)
end
-- draw the element given new data
- ---@vararg any new data
+ ---@param ... any new data
function public.update(...) protected.on_update(...) end
-- on a control request response
diff --git a/graphics/elements/appmultipane.lua b/graphics/elements/appmultipane.lua
index 5973182..948cb32 100644
--- a/graphics/elements/appmultipane.lua
+++ b/graphics/elements/appmultipane.lua
@@ -24,15 +24,15 @@ local MOUSE_CLICK = core.events.MOUSE_CLICK
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new app multipane element
+-- Create a new app multipane container element.
---@nodiscard
---@param args app_multipane_args
----@return graphics_element element, element_id id
-local function multipane(args)
+---@return AppMultiPane element, element_id id
+return function (args)
element.assert(type(args.panes) == "table", "panes is a required field")
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 1
@@ -100,10 +100,8 @@ local function multipane(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class AppMultiPane:graphics_element
+ local AppMultiPane, id = e.complete(true)
- return e.complete()
+ return AppMultiPane, id
end
-
-return multipane
diff --git a/graphics/elements/colormap.lua b/graphics/elements/colormap.lua
index 7e3554f..1a4b0a7 100644
--- a/graphics/elements/colormap.lua
+++ b/graphics/elements/colormap.lua
@@ -9,10 +9,10 @@ local element = require("graphics.element")
---@field y? integer auto incremented if omitted
---@field hidden? boolean true to hide on initial draw
--- new color map
+-- Create a horizontal reference color map. Primarily used for tuning custom colors.
---@param args colormap_args
----@return graphics_element element, element_id id
-local function colormap(args)
+---@return ColorMap element, element_id id
+return function (args)
local bkg = "008877FFCCEE114455DD9933BBAA2266"
local spaces = string.rep(" ", 32)
@@ -20,7 +20,7 @@ local function colormap(args)
args.height = 1
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- draw color map
function e.redraw()
@@ -28,10 +28,8 @@ local function colormap(args)
e.w_blit(spaces, bkg, bkg)
end
- -- initial draw
- e.redraw()
+ ---@class ColorMap:graphics_element
+ local ColorMap, id = e.complete(true)
- return e.complete()
+ return ColorMap, id
end
-
-return colormap
diff --git a/graphics/elements/displaybox.lua b/graphics/elements/displaybox.lua
index 3578a63..ecfe03a 100644
--- a/graphics/elements/displaybox.lua
+++ b/graphics/elements/displaybox.lua
@@ -13,13 +13,16 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new root display box
+-- Create a root display box.
---@nodiscard
---@param args displaybox_args
----@return graphics_element element, element_id id
-local function displaybox(args)
+---@return DisplayBox element, element_id id
+return function (args)
-- create new graphics element base object
- return element.new(args).complete()
-end
+ local e = element.new(args --[[@as graphics_args]])
-return displaybox
+ ---@class DisplayBox:graphics_element
+ local DisplayBox, id = e.complete()
+
+ return DisplayBox, id
+end
diff --git a/graphics/elements/div.lua b/graphics/elements/div.lua
index 0af3259..2be440b 100644
--- a/graphics/elements/div.lua
+++ b/graphics/elements/div.lua
@@ -13,13 +13,16 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new div element
+-- Create a new div container element.
---@nodiscard
---@param args div_args
----@return graphics_element element, element_id id
-local function div(args)
+---@return Div element, element_id id
+return function (args)
-- create new graphics element base object
- return element.new(args).complete()
-end
+ local e = element.new(args --[[@as graphics_args]])
-return div
+ ---@class Div:graphics_element
+ local Div, id = e.complete()
+
+ return Div, id
+end
diff --git a/graphics/elements/listbox.lua b/graphics/elements/listbox.lua
index 86cacd4..e1c8dec 100644
--- a/graphics/elements/listbox.lua
+++ b/graphics/elements/listbox.lua
@@ -30,15 +30,15 @@ local MOUSE_CLICK = core.events.MOUSE_CLICK
---@field y integer y position
---@field h integer element height
--- new listbox element
+-- Create a new scrollable listbox container element.
---@nodiscard
---@param args listbox_args
----@return graphics_element element, element_id id
-local function listbox(args)
+---@return ListBox element, element_id id
+return function (args)
args.can_focus = true
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- create content window for child elements
local scroll_frame = window.create(e.window, 1, 1, e.frame.w - 1, args.scroll_height, false)
@@ -339,10 +339,8 @@ local function listbox(args)
draw_bar()
end
- -- initial draw
- e.redraw()
+ ---@class ListBox:graphics_element
+ local ListBox, id = e.complete(true)
- return e.complete()
+ return ListBox, id
end
-
-return listbox
diff --git a/graphics/elements/multipane.lua b/graphics/elements/multipane.lua
index a283ed8..aae22ac 100644
--- a/graphics/elements/multipane.lua
+++ b/graphics/elements/multipane.lua
@@ -14,15 +14,15 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new multipane element
+-- Create a new multipane container element.
---@nodiscard
---@param args multipane_args
----@return graphics_element element, element_id id
-local function multipane(args)
+---@return MultiPane element, element_id id
+return function (args)
element.assert(type(args.panes) == "table", "panes is a required field")
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
e.value = 1
@@ -41,10 +41,8 @@ local function multipane(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class MultiPane:graphics_element
+ local MultiPane, id = e.complete(true)
- return e.complete()
+ return MultiPane, id
end
-
-return multipane
diff --git a/graphics/elements/pipenet.lua b/graphics/elements/pipenet.lua
index 625a70d..7045bd0 100644
--- a/graphics/elements/pipenet.lua
+++ b/graphics/elements/pipenet.lua
@@ -20,10 +20,10 @@ local element = require("graphics.element")
---@field fg string foreground blit
---@field bg string background blit
--- new pipe network
+-- Create a pipe network diagram.
---@param args pipenet_args
----@return graphics_element element, element_id id
-local function pipenet(args)
+---@return PipeNetwork element, element_id id
+return function (args)
element.assert(type(args.pipes) == "table", "pipes is a required field")
args.width = 0
@@ -47,7 +47,7 @@ local function pipenet(args)
end
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
-- determine if there are any thin pipes involved
local any_thin = false
@@ -322,10 +322,8 @@ local function pipenet(args)
if any_thin then map_draw() else vector_draw() end
end
- -- initial draw
- e.redraw()
+ ---@class PipeNetwork:graphics_element
+ local PipeNetwork, id = e.complete(true)
- return e.complete()
+ return PipeNetwork, id
end
-
-return pipenet
diff --git a/graphics/elements/rectangle.lua b/graphics/elements/rectangle.lua
index eceb9bd..ce5fbba 100644
--- a/graphics/elements/rectangle.lua
+++ b/graphics/elements/rectangle.lua
@@ -18,10 +18,10 @@ local element = require("graphics.element")
---@field fg_bg? cpair foreground/background colors
---@field hidden? boolean true to hide on initial draw
--- new rectangle
+-- Create a new rectangle container element.
---@param args rectangle_args
----@return graphics_element element, element_id id
-local function rectangle(args)
+---@return Rectangle element, element_id id
+return function (args)
element.assert(args.border ~= nil or args.thin ~= true, "thin requires border to be provided")
-- if thin, then width will always need to be 1
@@ -45,7 +45,7 @@ local function rectangle(args)
end
-- create new graphics element base object
- local e = element.new(args, nil, offset_x, offset_y)
+ local e = element.new(args --[[@as graphics_args]], nil, offset_x, offset_y)
-- create content window for child elements
e.content_window = window.create(e.window, 1 + offset_x, 1 + offset_y, e.frame.w - (2 * offset_x), e.frame.h - (2 * offset_y))
@@ -191,7 +191,8 @@ local function rectangle(args)
e.redraw()
end
- return e.complete()
-end
+ ---@class Rectangle:graphics_element
+ local Rectangle, id = e.complete()
-return rectangle
+ return Rectangle, id
+end
diff --git a/graphics/elements/textbox.lua b/graphics/elements/textbox.lua
index a52d528..00ea3f3 100644
--- a/graphics/elements/textbox.lua
+++ b/graphics/elements/textbox.lua
@@ -23,8 +23,8 @@ local ALIGN = core.ALIGN
-- new text box
---@param args textbox_args
----@return graphics_element element, element_id id
-local function textbox(args)
+---@return TextBox element, element_id id
+return function (args)
element.assert(type(args.text) == "string", "text is a required field")
if args.anchor == true then args.can_focus = true end
@@ -42,7 +42,7 @@ local function textbox(args)
end
-- create new graphics element base object
- local e = element.new(args, constrain)
+ local e = element.new(args --[[@as graphics_args]], constrain)
e.value = args.text
@@ -82,10 +82,8 @@ local function textbox(args)
e.redraw()
end
- -- initial draw
- e.redraw()
+ ---@class TextBox:graphics_element
+ local TextBox, id = e.complete(true)
- return e.complete()
+ return TextBox, id
end
-
-return textbox
diff --git a/graphics/elements/tiling.lua b/graphics/elements/tiling.lua
index 02e2605..cd9a31e 100644
--- a/graphics/elements/tiling.lua
+++ b/graphics/elements/tiling.lua
@@ -20,12 +20,12 @@ local element = require("graphics.element")
-- new tiling box
---@param args tiling_args
----@return graphics_element element, element_id id
-local function tiling(args)
+---@return Tiling element, element_id id
+return function (args)
element.assert(type(args.fill_c) == "table", "fill_c is a required field")
-- create new graphics element base object
- local e = element.new(args)
+ local e = element.new(args --[[@as graphics_args]])
local fill_a = args.fill_c.blit_a
local fill_b = args.fill_c.blit_b
@@ -52,7 +52,7 @@ local function tiling(args)
element.assert(start_x <= inner_width, "start_x > inner_width")
element.assert(start_y <= inner_height, "start_y > inner_height")
- -- draw tiling box
+ -- draw the tiling box
function e.redraw()
local alternator = true
@@ -86,10 +86,8 @@ local function tiling(args)
end
end
- -- initial draw
- e.redraw()
+ ---@class Tiling:graphics_element
+ local Tiling, id = e.complete(true)
- return e.complete()
+ return Tiling, id
end
-
-return tiling
diff --git a/graphics/flasher.lua b/graphics/flasher.lua
index 9412ac7..624822b 100644
--- a/graphics/flasher.lua
+++ b/graphics/flasher.lua
@@ -18,7 +18,7 @@ local PERIOD = {
flasher.PERIOD = PERIOD
local active = false
-local registry = { {}, {}, {} } -- one registry table per period
+local registry = { {}, {}, {} } ---@type [ function[], function[], function [] ] one registry table per period
local callback_counter = 0
-- blink registered indicators