diff --git a/graphics/element.lua b/graphics/element.lua index 40b3f66..bad2a80 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -11,7 +11,7 @@ local element = {} ---@field parent? graphics_element ---@field id? string element id ---@field x? integer 1 if omitted ----@field y? integer 1 if omitted +---@field y? integer next line if omitted ---@field offset_x? integer 0 if omitted ---@field offset_y? integer 0 if omitted ---@field width? integer parent width if omitted @@ -30,6 +30,7 @@ function element.new(args) position = { x = 1, y = 1 }, child_offset = { x = 0, y = 0 }, bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1}, + next_y = 1, children = {}, mt = {} } @@ -46,84 +47,85 @@ function element.new(args) return "graphics.element{" .. self.elem_type .. "} @ " .. tostring(self) end - -- SETUP -- + ---@class graphics_element + local public = {} - -- get the parent window - self.p_window = args.window - if self.p_window == nil and args.parent ~= nil then - self.p_window = args.parent.window() - end - - -- check window - assert(self.p_window, "graphics.element{" .. self.elem_type .. "}: no parent window provided") - - -- get frame coordinates/size - if args.gframe ~= nil then - protected.frame.x = args.gframe.x - protected.frame.y = args.gframe.y - protected.frame.w = args.gframe.w - protected.frame.h = args.gframe.h - else - local w, h = self.p_window.getSize() - protected.frame.x = args.x or 1 - protected.frame.y = args.y or 1 - protected.frame.w = args.width or w - protected.frame.h = args.height or h - end - - -- inner offsets - if args.offset_x ~= nil then self.child_offset.x = args.offset_x end - if args.offset_y ~= nil then self.child_offset.y = args.offset_y end - - -- adjust window frame if applicable - local f = protected.frame - local x = f.x - local y = f.y - - -- apply offsets - if args.parent ~= nil then - -- offset x/y - local offset_x, offset_y = args.parent.get_offset() - x = x + offset_x - y = y + offset_y - - -- constrain to parent inner width/height - local w, h = self.p_window.getSize() - f.w = math.min(f.w, w - ((2 * offset_x) + (f.x - 1))) - f.h = math.min(f.h, h - ((2 * offset_y) + (f.y - 1))) - end - - -- check frame - assert(f.x >= 1, "graphics.element{" .. self.elem_type .. "}: frame x not >= 1") - assert(f.y >= 1, "graphics.element{" .. self.elem_type .. "}: frame y not >= 1") - assert(f.w >= 1, "graphics.element{" .. self.elem_type .. "}: frame width not >= 1") - assert(f.h >= 1, "graphics.element{" .. self.elem_type .. "}: frame height not >= 1") - - -- create window - protected.window = window.create(self.p_window, x, y, f.w, f.h, true) - - -- init colors - if args.fg_bg ~= nil then - protected.fg_bg = args.fg_bg - elseif args.parent ~= nil then - protected.fg_bg = args.parent.get_fg_bg() - end - - -- set colors - protected.window.setBackgroundColor(protected.fg_bg.bkg) - protected.window.setTextColor(protected.fg_bg.fgd) - protected.window.clear() - - -- record position - self.position.x, self.position.y = protected.window.getPosition() - - -- calculate bounds - self.bounds.x1 = self.position.x - self.bounds.x2 = self.position.x + f.w - 1 - self.bounds.y1 = self.position.y - self.bounds.y2 = self.position.y + f.h - 1 + setmetatable(public, self.mt) + ------------------------- -- PROTECTED FUNCTIONS -- + ------------------------- + + -- prepare the template + ---@param offset_x integer x offset + ---@param offset_y integer y offset + ---@param next_y integer next line if no y was provided + function protected.prepare_template(offset_x, offset_y, next_y) + -- get frame coordinates/size + if args.gframe ~= nil then + protected.frame.x = args.gframe.x + protected.frame.y = args.gframe.y + protected.frame.w = args.gframe.w + protected.frame.h = args.gframe.h + else + local w, h = self.p_window.getSize() + protected.frame.x = args.x or 1 + protected.frame.y = args.y or next_y + protected.frame.w = args.width or w + protected.frame.h = args.height or h + end + + -- inner offsets + if args.offset_x ~= nil then self.child_offset.x = args.offset_x end + if args.offset_y ~= nil then self.child_offset.y = args.offset_y end + + -- adjust window frame if applicable + local f = protected.frame + local x = f.x + local y = f.y + + -- apply offsets + if args.parent ~= nil then + -- constrain to parent inner width/height + local w, h = self.p_window.getSize() + f.w = math.min(f.w, w - ((2 * offset_x) + (f.x - 1))) + f.h = math.min(f.h, h - ((2 * offset_y) + (f.y - 1))) + + -- offset x/y + f.x = x + offset_x + f.y = y + offset_y + end + + -- check frame + assert(f.x >= 1, "graphics.element{" .. self.elem_type .. "}: frame x not >= 1") + assert(f.y >= 1, "graphics.element{" .. self.elem_type .. "}: frame y not >= 1") + assert(f.w >= 1, "graphics.element{" .. self.elem_type .. "}: frame width not >= 1") + assert(f.h >= 1, "graphics.element{" .. self.elem_type .. "}: frame height not >= 1") + + -- create window + protected.window = window.create(self.p_window, f.x, f.y, f.w, f.h, true) + + -- init colors + if args.fg_bg ~= nil then + protected.fg_bg = args.fg_bg + elseif args.parent ~= nil then + protected.fg_bg = args.parent.get_fg_bg() + end + + -- set colors + protected.window.setBackgroundColor(protected.fg_bg.bkg) + protected.window.setTextColor(protected.fg_bg.fgd) + protected.window.clear() + + -- record position + self.position.x, self.position.y = protected.window.getPosition() + + -- calculate bounds + self.bounds.x1 = self.position.x + self.bounds.x2 = self.position.x + f.w - 1 + self.bounds.y1 = self.position.y + self.bounds.y2 = self.position.y + f.h - 1 + end -- handle a touch event ---@param event table monitor_touch event @@ -139,43 +141,56 @@ function element.new(args) return nil end - ---@class graphics_element - local public = {} - - setmetatable(public, self.mt) - - -- get public interface and wrap up element creation + -- get public interface ---@return graphics_element element, element_id id - function protected.complete() - if not self.define_completed then - self.define_completed = true + function protected.get() return public, self.id end - if args.parent then - self.id = args.parent.__add_child(args.id, public) - end + ----------- + -- SETUP -- + ----------- - return public, self.id - else - assert("graphics.element{" .. self.elem_type .. "}: illegal duplicate call to complete()") - end + -- get the parent window + self.p_window = args.window + if self.p_window == nil and args.parent ~= nil then + self.p_window = args.parent.window() end + -- check window + assert(self.p_window, "graphics.element{" .. self.elem_type .. "}: no parent window provided") + + -- prepare the template + if args.parent == nil then + protected.prepare_template(0, 0, 1) + else + self.id = args.parent.__add_child(args.id, protected) + end + + ---------------------- -- PUBLIC FUNCTIONS -- + ---------------------- -- get the window object function public.window() return protected.window end + -- CHILD ELEMENTS -- + -- add a child element ---@param key string|nil id - ---@param child graphics_element - ---@return graphics_element element, integer|string key + ---@param child graphics_template + ---@return integer|string key function public.__add_child(key, child) + child.prepare_template(self.child_offset.x, self.child_offset.y, self.next_y) + + self.next_y = child.frame.y + child.frame.h + + local child_element = child.get() + if key == nil then - table.insert(self.children, child) - return child, #self.children + table.insert(self.children, child_element) + return #self.children else - self.children[key] = child - return child, key + self.children[key] = child_element + return key end end @@ -203,15 +218,16 @@ function element.new(args) return nil end + -- AUTO-PLACEMENT -- + + -- skip a line for automatically placed elements + function public.line_break() self.next_y = self.next_y + 1 end + + -- PROPERTIES -- + -- get the foreground/background colors function public.get_fg_bg() return protected.fg_bg end - -- get offset from this element's frame - ---@return integer x, integer y - function public.get_offset() - return self.child_offset.x, self.child_offset.y - end - -- get element width function public.width() return protected.frame.w @@ -222,6 +238,13 @@ function element.new(args) return protected.frame.h end + -- get the control value reading + function public.get_value() + return protected.get_value() + end + + -- FUNCTION CALLBACKS -- + -- handle a monitor touch ---@param event monitor_touch monitor touch event function public.handle_touch(event) @@ -244,10 +267,7 @@ function element.new(args) protected.on_update(...) end - -- get the control value reading - function public.get_value() - return protected.get_value() - end + -- VISIBILITY -- -- show the element function public.show() diff --git a/graphics/elements/controls/push_button.lua b/graphics/elements/controls/push_button.lua index 35e70a6..5e2bf4d 100644 --- a/graphics/elements/controls/push_button.lua +++ b/graphics/elements/controls/push_button.lua @@ -63,7 +63,7 @@ local function push_button(args) args.callback() end - return e.complete() + return e.get() end return push_button diff --git a/graphics/elements/controls/scram_button.lua b/graphics/elements/controls/scram_button.lua index e916fbe..bac3045 100644 --- a/graphics/elements/controls/scram_button.lua +++ b/graphics/elements/controls/scram_button.lua @@ -65,7 +65,7 @@ local function scram_button(args) args.callback() end - return e.complete() + return e.get() end return scram_button diff --git a/graphics/elements/controls/spinbox_numeric.lua b/graphics/elements/controls/spinbox_numeric.lua index 16237d6..55b80ce 100644 --- a/graphics/elements/controls/spinbox_numeric.lua +++ b/graphics/elements/controls/spinbox_numeric.lua @@ -112,7 +112,7 @@ local function spinbox(args) ---@return number|integer function e.get_value() return value end - return e.complete() + return e.get() end return spinbox diff --git a/graphics/elements/controls/switch_button.lua b/graphics/elements/controls/switch_button.lua index aae443c..964eada 100644 --- a/graphics/elements/controls/switch_button.lua +++ b/graphics/elements/controls/switch_button.lua @@ -73,7 +73,7 @@ local function switch_button(args) args.callback(state) end - return e.complete() + return e.get() end return switch_button diff --git a/graphics/elements/displaybox.lua b/graphics/elements/displaybox.lua index 218f599..0d7fd47 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).complete() + return element.new(args).get() end return displaybox diff --git a/graphics/elements/div.lua b/graphics/elements/div.lua index 0864b36..59e3a1e 100644 --- a/graphics/elements/div.lua +++ b/graphics/elements/div.lua @@ -17,7 +17,7 @@ local element = require("graphics.element") ---@return graphics_element element, element_id id local function div(args) -- create new graphics element base object - return element.new(args).complete() + return element.new(args).get() end return div diff --git a/graphics/elements/indicators/data.lua b/graphics/elements/indicators/data.lua index 1022551..86e248b 100644 --- a/graphics/elements/indicators/data.lua +++ b/graphics/elements/indicators/data.lua @@ -93,7 +93,7 @@ local function data(args) -- initial value draw e.on_update(args.value) - return e.complete() + return e.get() end return data diff --git a/graphics/elements/indicators/hbar.lua b/graphics/elements/indicators/hbar.lua index 53862aa..a45eb91 100644 --- a/graphics/elements/indicators/hbar.lua +++ b/graphics/elements/indicators/hbar.lua @@ -99,7 +99,7 @@ local function hbar(args) -- initialize to 0 e.on_update(0) - return e.complete() + return e.get() end return hbar diff --git a/graphics/elements/indicators/icon.lua b/graphics/elements/indicators/icon.lua index a33711a..cdbcf9e 100644 --- a/graphics/elements/indicators/icon.lua +++ b/graphics/elements/indicators/icon.lua @@ -62,7 +62,7 @@ local function icon(args) -- initial icon draw e.on_update(args.value or 1) - return e.complete() + return e.get() end return icon diff --git a/graphics/elements/indicators/light.lua b/graphics/elements/indicators/light.lua index f902bfb..e16a68a 100644 --- a/graphics/elements/indicators/light.lua +++ b/graphics/elements/indicators/light.lua @@ -45,7 +45,7 @@ local function indicator_light(args) e.on_update(false) e.window.write(args.label) - return e.complete() + return e.get() end return indicator_light diff --git a/graphics/elements/indicators/state.lua b/graphics/elements/indicators/state.lua index 2311d3d..a3d5854 100644 --- a/graphics/elements/indicators/state.lua +++ b/graphics/elements/indicators/state.lua @@ -72,7 +72,7 @@ local function state_indicator(args) -- initial draw e.on_update(args.value or 1) - return e.complete() + return e.get() end return state_indicator diff --git a/graphics/elements/indicators/vbar.lua b/graphics/elements/indicators/vbar.lua index 8b3d9ba..114fb77 100644 --- a/graphics/elements/indicators/vbar.lua +++ b/graphics/elements/indicators/vbar.lua @@ -78,7 +78,7 @@ local function vbar(args) end end - return e.complete() + return e.get() end return vbar diff --git a/graphics/elements/pipenet.lua b/graphics/elements/pipenet.lua index 81e7b0a..71ee9fd 100644 --- a/graphics/elements/pipenet.lua +++ b/graphics/elements/pipenet.lua @@ -141,7 +141,7 @@ local function pipenet(args) end - return e.complete() + return e.get() end return pipenet diff --git a/graphics/elements/rectangle.lua b/graphics/elements/rectangle.lua index 12dacac..b7ece93 100644 --- a/graphics/elements/rectangle.lua +++ b/graphics/elements/rectangle.lua @@ -110,7 +110,7 @@ local function rectangle(args) end end - return e.complete() + return e.get() end return rectangle diff --git a/graphics/elements/textbox.lua b/graphics/elements/textbox.lua index 1d76f4e..14b5591 100644 --- a/graphics/elements/textbox.lua +++ b/graphics/elements/textbox.lua @@ -52,7 +52,7 @@ local function textbox(args) e.window.write(lines[i]) end - return e.complete() + return e.get() end return textbox diff --git a/graphics/elements/tiling.lua b/graphics/elements/tiling.lua index 9f94d97..4d20025 100644 --- a/graphics/elements/tiling.lua +++ b/graphics/elements/tiling.lua @@ -79,7 +79,7 @@ local function tiling(args) end end - return e.complete() + return e.get() end return tiling