#544 #545 work on graphics

This commit is contained in:
Mikayla Fischler 2024-09-21 18:38:25 -04:00
parent 2047794173
commit 1d53241b82
13 changed files with 126 additions and 161 deletions

View File

@ -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,

View File

@ -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<br>
---@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<br>
---@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<br>
---@see Window.setTextColor
---@param c color
function protected.w_set_fgd(c) protected.window.setTextColor(c) end
-- write text
-- write text<br>
---@see Window.write
---@param str string
function protected.w_write(str) protected.window.write(str) end
-- blit text
-- blit text<br>
---@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<br>
@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<br>