From f1a50990f25e5798bb0a603e2effb6f4785daf6c Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Thu, 28 Jul 2022 10:09:34 -0400 Subject: [PATCH] #84 improved element creation process for adding children --- graphics/core.lua | 6 +- graphics/element.lua | 67 ++++++++++--------- graphics/elements/controls/push_button.lua | 4 +- graphics/elements/controls/scram_button.lua | 4 +- .../elements/controls/spinbox_numeric.lua | 4 +- graphics/elements/controls/switch_button.lua | 4 +- graphics/elements/displaybox.lua | 2 +- graphics/elements/div.lua | 4 +- graphics/elements/indicators/data.lua | 4 +- graphics/elements/indicators/hbar.lua | 5 +- graphics/elements/indicators/icon.lua | 4 +- graphics/elements/indicators/light.lua | 4 +- graphics/elements/indicators/state.lua | 4 +- graphics/elements/indicators/vbar.lua | 4 +- graphics/elements/pipenet.lua | 10 +-- graphics/elements/rectangle.lua | 4 +- graphics/elements/textbox.lua | 6 +- graphics/elements/tiling.lua | 4 +- 18 files changed, 90 insertions(+), 54 deletions(-) diff --git a/graphics/core.lua b/graphics/core.lua index 4894b3a..f4d86fd 100644 --- a/graphics/core.lua +++ b/graphics/core.lua @@ -40,6 +40,8 @@ graphics.TEXT_ALIGN = { ---@field color color ---@field even boolean +---@alias element_id string|integer + -- create a new border definition ---@param width integer border width ---@param color color border color @@ -111,7 +113,7 @@ end ---@field w integer width ---@field h integer height ---@field color color pipe color ----@field thin boolean true for 1 subpixels, false (default) for 2 +---@field thin boolean true for 1 subpixel, false (default) for 2 ---@field align_tr boolean false to align bottom left (default), true to align top right -- create a new pipe @@ -122,7 +124,7 @@ end ---@param x2 integer ending x, origin is 0 ---@param y2 integer ending y, origin is 0 ---@param color color pipe color ----@param thin? boolean true for 1 subpixels, false (default) for 2 +---@param thin? boolean true for 1 subpixel, false (default) for 2 ---@param align_tr? boolean false to align bottom left (default), true to align top right ---@return pipe function graphics.pipe(x1, y1, x2, y2, color, thin, align_tr) diff --git a/graphics/element.lua b/graphics/element.lua index ee4b633..64e1029 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -9,6 +9,7 @@ local element = {} ---@class graphics_args_generic ---@field window? table ---@field parent? graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field offset_x? integer 0 if omitted @@ -22,7 +23,9 @@ local element = {} ---@param args graphics_args_generic arguments function element.new(args) local self = { + id = -1, elem_type = debug.getinfo(2).name, + define_completed = false, p_window = nil, ---@type table position = { x = 1, y = 1 }, child_offset = { x = 0, y = 0 }, @@ -31,42 +34,16 @@ function element.new(args) mt = {} } + ---@class graphics_template local protected = { window = nil, ---@type table fg_bg = core.graphics.cpair(colors.white, colors.black), frame = core.graphics.gframe(1, 1, 1, 1) } - -- append a child element without a tag - local function add_child(child) - table.insert(self.children, child) - return #self.children - end - - -- add a child element without a tag - function self.mt.__add(_, child) return add_child(child) end - function self.mt.__lt(_, child) return add_child(child) end - function self.mt.__le(_, child) return add_child(child) end - - -- add a child element without a tag - ---@param _ table ignored (self) - ---@vararg table children - ---@return integer|table id/ids - function self.mt.__call(_, ...) - local children = { ... } - - if #children == 1 then - return add_child(children[1]) - else - local ids = {} - for _, v in ipairs(children) do table.insert(ids, add_child(v)) end - return ids - end - end - -- element as string function self.mt.__tostring() - return "graphics.element{" .. self.elem_type .. "}"-- @ " .. tostring(self) + return "graphics.element{" .. self.elem_type .. "} @ " .. tostring(self) end -- SETUP -- @@ -167,8 +144,21 @@ function element.new(args) setmetatable(public, self.mt) - -- get public interface - function protected.get() return public end + -- get public interface and wrap up element creation + ---@return graphics_element element, element_id id + function protected.complete() + if not self.define_completed then + self.define_completed = true + + if args.parent then + self.id = args.parent.__add_child(args.id, public) + end + + return public, self.id + else + assert("graphics.element{" .. self.elem_type .. "}: illegal duplicate call to complete()") + end + end -- PUBLIC FUNCTIONS -- @@ -176,9 +166,18 @@ function element.new(args) function public.window() return protected.window end -- add a child element - ---@param key string id + ---@param key string|nil id ---@param child graphics_element - function public.add_child(key, child) self.children[key] = child end + ---@return graphics_element element, integer|string key + function public.__add_child(key, child) + if key == nil then + table.insert(self.children, child) + return child, #self.children + else + self.children[key] = child + return child, key + end + end -- get a child element ---@return graphics_element @@ -188,6 +187,10 @@ function element.new(args) ---@param key string|integer function public.remove(key) self.children[key] = nil end + ---@param id element_id + function public.get_element_by_id(id) + end + -- get the foreground/background colors function public.get_fg_bg() return protected.fg_bg end diff --git a/graphics/elements/controls/push_button.lua b/graphics/elements/controls/push_button.lua index 82aa081..35e70a6 100644 --- a/graphics/elements/controls/push_button.lua +++ b/graphics/elements/controls/push_button.lua @@ -10,6 +10,7 @@ local element = require("graphics.element") ---@field min_width? integer text length + 2 if omitted ---@field active_fg_bg? cpair foreground/background colors when pressed ---@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 @@ -17,6 +18,7 @@ local element = require("graphics.element") -- new push button ---@param args push_button_args +---@return graphics_element element, element_id id local function push_button(args) assert(type(args.text) == "string", "graphics.elements.controls.push_button: text is a required field") assert(type(args.callback) == "function", "graphics.elements.controls.push_button: callback is a required field") @@ -61,7 +63,7 @@ local function push_button(args) args.callback() end - return e.get() + return e.complete() end return push_button diff --git a/graphics/elements/controls/scram_button.lua b/graphics/elements/controls/scram_button.lua index 1694969..e916fbe 100644 --- a/graphics/elements/controls/scram_button.lua +++ b/graphics/elements/controls/scram_button.lua @@ -9,12 +9,14 @@ local element = require("graphics.element") ---@class scram_button_args ---@field callback function function to call on touch ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors -- new scram button ---@param args scram_button_args +---@return graphics_element element, element_id id local function scram_button(args) assert(type(args.callback) == "function", "graphics.elements.controls.scram_button: callback is a required field") @@ -63,7 +65,7 @@ local function scram_button(args) args.callback() end - return e.get() + return e.complete() end return scram_button diff --git a/graphics/elements/controls/spinbox_numeric.lua b/graphics/elements/controls/spinbox_numeric.lua index 37a40c2..16237d6 100644 --- a/graphics/elements/controls/spinbox_numeric.lua +++ b/graphics/elements/controls/spinbox_numeric.lua @@ -9,12 +9,14 @@ local util = require("scada-common.util") ---@field fractional_precision integer number of fractional digits ---@field arrow_fg_bg cpair arrow foreground/background colors ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors -- new spinbox control (minimum value is 0) ---@param args spinbox_args +---@return graphics_element element, element_id id local function spinbox(args) -- properties local value = args.default or 0.0 @@ -110,7 +112,7 @@ local function spinbox(args) ---@return number|integer function e.get_value() return value end - return e.get() + return e.complete() end return spinbox diff --git a/graphics/elements/controls/switch_button.lua b/graphics/elements/controls/switch_button.lua index 03c25bb..aae443c 100644 --- a/graphics/elements/controls/switch_button.lua +++ b/graphics/elements/controls/switch_button.lua @@ -9,6 +9,7 @@ local element = require("graphics.element") ---@field min_width? integer text length + 2 if omitted ---@field active_fg_bg cpair foreground/background colors when pressed ---@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 @@ -16,6 +17,7 @@ local element = require("graphics.element") -- new switch button (latch high/low) ---@param args switch_button_args +---@return graphics_element element, element_id id local function switch_button(args) assert(type(args.text) == "string", "graphics.elements.controls.switch_button: text is a required field") assert(type(args.callback) == "function", "graphics.elements.controls.switch_button: callback is a required field") @@ -71,7 +73,7 @@ local function switch_button(args) args.callback(state) end - return e.get() + return e.complete() end return switch_button diff --git a/graphics/elements/displaybox.lua b/graphics/elements/displaybox.lua index 0d7fd47..218f599 100644 --- a/graphics/elements/displaybox.lua +++ b/graphics/elements/displaybox.lua @@ -15,7 +15,7 @@ local element = require("graphics.element") ---@param args displaybox_args local function displaybox(args) -- create new graphics element base object - return element.new(args).get() + return element.new(args).complete() end return displaybox diff --git a/graphics/elements/div.lua b/graphics/elements/div.lua index cb56aa0..0864b36 100644 --- a/graphics/elements/div.lua +++ b/graphics/elements/div.lua @@ -4,6 +4,7 @@ local element = require("graphics.element") ---@class div_args ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field width? integer parent width if omitted @@ -13,9 +14,10 @@ local element = require("graphics.element") -- new div element ---@param args div_args +---@return graphics_element element, element_id id local function div(args) -- create new graphics element base object - return element.new(args).get() + return element.new(args).complete() end return div diff --git a/graphics/elements/indicators/data.lua b/graphics/elements/indicators/data.lua index 07930c5..1022551 100644 --- a/graphics/elements/indicators/data.lua +++ b/graphics/elements/indicators/data.lua @@ -35,6 +35,7 @@ end ---@field lu_colors? cpair label foreground color (a), unit foreground color (b) ---@field value any default value ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field width integer length @@ -42,6 +43,7 @@ end -- new data indicator ---@param args data_indicator_args +---@return graphics_element element, element_id id local function data(args) assert(type(args.label) == "string", "graphics.elements.indicators.data: label is a required field") assert(type(args.format) == "string", "graphics.elements.indicators.data: format is a required field") @@ -91,7 +93,7 @@ local function data(args) -- initial value draw e.on_update(args.value) - return e.get() + return e.complete() end return data diff --git a/graphics/elements/indicators/hbar.lua b/graphics/elements/indicators/hbar.lua index c886a63..53862aa 100644 --- a/graphics/elements/indicators/hbar.lua +++ b/graphics/elements/indicators/hbar.lua @@ -8,6 +8,7 @@ local element = require("graphics.element") ---@field show_percent? boolean whether or not to show the percent ---@field bar_fg_bg? cpair bar foreground/background colors if showing percent ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field width? integer parent width if omitted @@ -17,6 +18,8 @@ local element = require("graphics.element") -- new horizontal bar ---@param args hbar_args +---@return graphics_element element, element_id id +---@return graphics_element element, element_id id local function hbar(args) -- properties/state local last_num_bars = -1 @@ -96,7 +99,7 @@ local function hbar(args) -- initialize to 0 e.on_update(0) - return e.get() + return e.complete() end return hbar diff --git a/graphics/elements/indicators/icon.lua b/graphics/elements/indicators/icon.lua index d116f2b..a33711a 100644 --- a/graphics/elements/indicators/icon.lua +++ b/graphics/elements/indicators/icon.lua @@ -14,12 +14,14 @@ local element = require("graphics.element") ---@field value? integer default state, defaults to 1 ---@field min_label_width? integer label length if omitted ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors -- new icon indicator ---@param args icon_indicator_args +---@return graphics_element element, element_id id local function icon(args) assert(type(args.label) == "string", "graphics.elements.indicators.icon: label is a required field") assert(type(args.states) == "table", "graphics.elements.indicators.icon: states is a required field") @@ -60,7 +62,7 @@ local function icon(args) -- initial icon draw e.on_update(args.value or 1) - return e.get() + return e.complete() end return icon diff --git a/graphics/elements/indicators/light.lua b/graphics/elements/indicators/light.lua index 3d733df..f902bfb 100644 --- a/graphics/elements/indicators/light.lua +++ b/graphics/elements/indicators/light.lua @@ -9,12 +9,14 @@ local element = require("graphics.element") ---@field colors cpair on/off colors (a/b respectively) ---@field min_label_width? integer label length if omitted ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field fg_bg? cpair foreground/background colors -- new indicator light ---@param args indicator_light_args +---@return graphics_element element, element_id id local function indicator_light(args) assert(type(args.label) == "string", "graphics.elements.indicators.light: label is a required field") assert(type(args.colors) == "table", "graphics.elements.indicators.light: colors is a required field") @@ -43,7 +45,7 @@ local function indicator_light(args) e.on_update(false) e.window.write(args.label) - return e.get() + return e.complete() end return indicator_light diff --git a/graphics/elements/indicators/state.lua b/graphics/elements/indicators/state.lua index 0383fd8..2311d3d 100644 --- a/graphics/elements/indicators/state.lua +++ b/graphics/elements/indicators/state.lua @@ -13,6 +13,7 @@ local element = require("graphics.element") ---@field value? integer default state, defaults to 1 ---@field min_width? integer max state text length if omitted ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field height? integer 1 if omitted, must be an odd number @@ -20,6 +21,7 @@ local element = require("graphics.element") -- new state indicator ---@param args state_indicator_args +---@return graphics_element element, element_id id local function state_indicator(args) assert(type(args.states) == "table", "graphics.elements.indicators.state: states is a required field") @@ -70,7 +72,7 @@ local function state_indicator(args) -- initial draw e.on_update(args.value or 1) - return e.get() + return e.complete() end return state_indicator diff --git a/graphics/elements/indicators/vbar.lua b/graphics/elements/indicators/vbar.lua index e1016aa..8b3d9ba 100644 --- a/graphics/elements/indicators/vbar.lua +++ b/graphics/elements/indicators/vbar.lua @@ -6,6 +6,7 @@ local element = require("graphics.element") ---@class vbar_args ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field width? integer parent width if omitted @@ -15,6 +16,7 @@ local element = require("graphics.element") -- new vertical bar ---@param args vbar_args +---@return graphics_element element, element_id id local function vbar(args) -- properties/state local last_num_bars = -1 @@ -76,7 +78,7 @@ local function vbar(args) end end - return e.get() + return e.complete() end return vbar diff --git a/graphics/elements/pipenet.lua b/graphics/elements/pipenet.lua index b9436c3..81e7b0a 100644 --- a/graphics/elements/pipenet.lua +++ b/graphics/elements/pipenet.lua @@ -6,14 +6,16 @@ local core = require("graphics.core") local element = require("graphics.element") ---@class pipenet_args ----@field parent graphics_element ----@field x? integer 1 if omitted ----@field y? integer 1 if omitted ---@field pipes table pipe list ---@field bg? color background color +---@field parent graphics_element +---@field id? string element id +---@field x? integer 1 if omitted +---@field y? integer 1 if omitted -- new pipe network ---@param args pipenet_args +---@return graphics_element element, element_id id local function pipenet(args) assert(type(args.pipes) == "table", "graphics.elements.indicators.pipenet: pipes is a required field") @@ -139,7 +141,7 @@ local function pipenet(args) end - return e.get() + return e.complete() end return pipenet diff --git a/graphics/elements/rectangle.lua b/graphics/elements/rectangle.lua index 933bcd3..12dacac 100644 --- a/graphics/elements/rectangle.lua +++ b/graphics/elements/rectangle.lua @@ -7,6 +7,7 @@ local element = require("graphics.element") ---@class rectangle_args ---@field border? graphics_border ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field width? integer parent width if omitted @@ -16,6 +17,7 @@ local element = require("graphics.element") -- new rectangle ---@param args rectangle_args +---@return graphics_element element, element_id id local function rectangle(args) -- offset children if args.border ~= nil then @@ -108,7 +110,7 @@ local function rectangle(args) end end - return e.get() + return e.complete() end return rectangle diff --git a/graphics/elements/textbox.lua b/graphics/elements/textbox.lua index d5694a4..1d76f4e 100644 --- a/graphics/elements/textbox.lua +++ b/graphics/elements/textbox.lua @@ -9,8 +9,9 @@ local TEXT_ALIGN = core.graphics.TEXT_ALIGN ---@class textbox_args ---@field text string text to show ----@field parent graphics_element ---@field alignment? TEXT_ALIGN text alignment, left by default +---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field width? integer parent width if omitted @@ -20,6 +21,7 @@ local TEXT_ALIGN = core.graphics.TEXT_ALIGN -- new text box ---@param args textbox_args +---@return graphics_element element, element_id id local function textbox(args) assert(type(args.text) == "string", "graphics.elements.textbox: text is a required field") @@ -50,7 +52,7 @@ local function textbox(args) e.window.write(lines[i]) end - return e.get() + return e.complete() end return textbox diff --git a/graphics/elements/tiling.lua b/graphics/elements/tiling.lua index 47367b4..9f94d97 100644 --- a/graphics/elements/tiling.lua +++ b/graphics/elements/tiling.lua @@ -9,6 +9,7 @@ local element = require("graphics.element") ---@field even? boolean whether to account for rectangular pixels ---@field border_c? color optional frame color ---@field parent graphics_element +---@field id? string element id ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted ---@field width? integer parent width if omitted @@ -18,6 +19,7 @@ local element = require("graphics.element") -- new tiling box ---@param args tiling_args +---@return graphics_element element, element_id id local function tiling(args) assert(type(args.fill_c) == "table", "graphics.elements.tiling: fill_c is a required field") @@ -77,7 +79,7 @@ local function tiling(args) end end - return e.get() + return e.complete() end return tiling