diff --git a/graphics/element.lua b/graphics/element.lua index cfaba05..9e78faf 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -3,6 +3,8 @@ -- local core = require("graphics.core") +local log = require("scada-common.log") +local util = require("scada-common.util") local element = {} @@ -20,11 +22,15 @@ local element = {} ---@param args graphics_args_generic arguments function element.new(args) local self = { + elem_type = debug.getinfo(2).name, p_window = nil, ---@type table position = { x = 1, y = 1 }, bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1} } + ---@fixme remove debug + log.dmesg("new " .. self.elem_type) + local protected = { window = nil, ---@type table fg_bg = core.graphics.cpair(colors.white, colors.black), @@ -34,7 +40,10 @@ function element.new(args) -- SETUP -- -- get the parent window - self.p_window = args.window or args.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: no parent window provided") @@ -63,14 +72,18 @@ function element.new(args) local f = protected.frame protected.window = window.create(self.p_window, f.x, f.y, f.w, f.h, true) - -- init display box + -- init colors if args.fg_bg ~= nil then - protected.window.setBackgroundColor(args.fg_bg.bkg) - protected.window.setTextColor(args.fg_bg.fgd) - protected.window.clear() 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() @@ -107,6 +120,9 @@ function element.new(args) -- get the window object function public.window() return protected.window end + -- get the foreground/background colors + function public.get_fg_bg() return protected.fg_bg end + -- handle a monitor touch ---@param event monitor_touch monitor touch event function public.handle_touch(event) diff --git a/graphics/elements/button_push.lua b/graphics/elements/controls/push_button.lua similarity index 90% rename from graphics/elements/button_push.lua rename to graphics/elements/controls/push_button.lua index 321e5a6..9968240 100644 --- a/graphics/elements/button_push.lua +++ b/graphics/elements/controls/push_button.lua @@ -18,8 +18,11 @@ local element = require("graphics.element") -- new push button ---@param args push_button_args local function push_button(args) - assert(type(args.text) == "string", "graphics.elements.button_push: text is a required field") - assert(type(args.callback) == "function", "graphics.elements.button_push: callback is a required field") + 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") + + -- single line + args.height = 1 local text_width = string.len(args.text) args.width = math.max(text_width + 2, args.min_width) diff --git a/graphics/elements/spinbox_numeric.lua b/graphics/elements/controls/spinbox_numeric.lua similarity index 92% rename from graphics/elements/spinbox_numeric.lua rename to graphics/elements/controls/spinbox_numeric.lua index 841bf1f..92946d8 100644 --- a/graphics/elements/spinbox_numeric.lua +++ b/graphics/elements/controls/spinbox_numeric.lua @@ -23,8 +23,8 @@ local function spinbox(args) local fr_prec = args.fractional_precision local dec_point_x = args.whole_num_precision + 1 - assert(util.is_int(wn_prec), "graphics.element.spinbox_numeric: whole number precision must be an integer") - assert(util.is_int(fr_prec), "graphics.element.spinbox_numeric: fractional precision must be an integer") + assert(util.is_int(wn_prec), "graphics.element.controls.spinbox_numeric: whole number precision must be an integer") + assert(util.is_int(fr_prec), "graphics.element.controls.spinbox_numeric: fractional precision must be an integer") assert(type(args.arrow_fg_bg) == "table", "graphics.element.spinbox_numeric: arrow_fg_bg is a required field") diff --git a/graphics/elements/button_switch.lua b/graphics/elements/controls/switch_button.lua similarity index 88% rename from graphics/elements/button_switch.lua rename to graphics/elements/controls/switch_button.lua index 6a06348..03c25bb 100644 --- a/graphics/elements/button_switch.lua +++ b/graphics/elements/controls/switch_button.lua @@ -17,9 +17,12 @@ local element = require("graphics.element") -- new switch button (latch high/low) ---@param args switch_button_args local function switch_button(args) - assert(type(args.text) == "string", "graphics.elements.button_switch: text is a required field") - assert(type(args.callback) == "function", "graphics.elements.button_switch: callback is a required field") - assert(type(args.active_fg_bg) == "table", "graphics.elements.button_switch: active_fg_bg is a required field") + 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") + assert(type(args.active_fg_bg) == "table", "graphics.elements.controls.switch_button: active_fg_bg is a required field") + + -- single line + args.height = 1 -- button state (convert nil to false if missing) local state = args.default or false diff --git a/graphics/elements/indicator_data.lua b/graphics/elements/indicators/data.lua similarity index 68% rename from graphics/elements/indicator_data.lua rename to graphics/elements/indicators/data.lua index 97e2667..d33cb69 100644 --- a/graphics/elements/indicator_data.lua +++ b/graphics/elements/indicators/data.lua @@ -8,8 +8,8 @@ local element = require("graphics.element") ---@field label string indicator label ---@field unit? string indicator unit ---@field format string data format (lua string format) ----@field label_unit_colors? cpair label foreground color (a), unit foreground color (b) ----@field initial_value any default value +---@field lu_colors? cpair label foreground color (a), unit foreground color (b) +---@field value any default value ---@field parent graphics_element ---@field x? integer 1 if omitted ---@field y? integer 1 if omitted @@ -18,18 +18,21 @@ local element = require("graphics.element") -- new data indicator ---@param args data_indicator_args -local function data_indicator(args) - assert(type(args.label) == "string", "graphics.elements.indicator_data: label is a required field") - assert(type(args.format) == "string", "graphics.elements.indicator_data: format is a required field") - assert(args.initial_value ~= nil, "graphics.elements.indicator_data: initial_value is a required field") - assert(util.is_int(args.width), "graphics.elements.indicator_data: width is a required field") +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") + assert(args.value ~= nil, "graphics.elements.indicators.data: value is a required field") + assert(util.is_int(args.width), "graphics.elements.indicators.data: width is a required field") + + -- single line + args.height = 1 -- create new graphics element base object local e = element.new(args) -- label color - if args.label_unit_colors ~= nil then - e.window.setTextColor(args.label_unit_colors.color_a) + if args.lu_colors ~= nil then + e.window.setTextColor(args.lu_colors.color_a) end -- write label @@ -50,17 +53,17 @@ local function data_indicator(args) -- write label if args.unit ~= nil then - if args.label_unit_colors ~= nil then - e.window.setTextColor(args.label_unit_colors.color_b) + if args.lu_colors ~= nil then + e.window.setTextColor(args.lu_colors.color_b) end e.window.write(" " .. args.unit) end end -- initial value draw - e.on_update(args.initial_value) + e.on_update(args.value) return e.get() end -return data_indicator +return data diff --git a/graphics/elements/hbar.lua b/graphics/elements/indicators/hbar.lua similarity index 82% rename from graphics/elements/hbar.lua rename to graphics/elements/indicators/hbar.lua index fad6a50..d620df0 100644 --- a/graphics/elements/hbar.lua +++ b/graphics/elements/indicators/hbar.lua @@ -19,7 +19,6 @@ local element = require("graphics.element") ---@param args hbar_args local function hbar(args) -- properties/state - local bkg = "" local last_num_bars = -1 -- create new graphics element base object @@ -31,12 +30,10 @@ local function hbar(args) assert(bar_width > 0, "graphics.elements.hbar: too small for bar") -- determine bar colors + ---@fixme this doesnt work as intended local bar_bkg = util.trinary(args.bar_fg_bg == nil, e.fg_bg.blit_bkg, args.bar_fg_bg.blit_bkg) local bar_fgd = util.trinary(args.bar_fg_bg == nil, e.fg_bg.blit_fgd, args.bar_fg_bg.blit_fgd) - -- set background blit string - bkg = util.strrep(args.bar_fg_bg.blit_bkg, bar_width) - -- handle data changes function e.on_update(fraction) -- enforce minimum and maximum @@ -47,37 +44,43 @@ local function hbar(args) end -- compute number of bars - local num_bars = util.round((fraction * 100) / (bar_width * 2)) + local num_bars = util.round(fraction * (bar_width * 2)) + util.print(num_bars) -- redraw bar if changed if num_bars ~= last_num_bars then last_num_bars = num_bars local fgd = "" + local bkg = "" local spaces = "" -- fill percentage for _ = 1, num_bars / 2 do spaces = spaces .. " " fgd = fgd .. bar_fgd + bkg = bkg .. bar_bkg end -- add fractional bar if needed if num_bars % 2 == 1 then spaces = spaces .. "\x95" - fgd = fgd .. bar_fgd + fgd = fgd .. bar_bkg + bkg = bkg .. bar_fgd end -- pad background - for _ = 1, bar_width - ((num_bars / 2) + num_bars % 2) do + for _ = 1, ((bar_width * 2) - num_bars) / 2 do spaces = spaces .. " " fgd = fgd .. bar_bkg + bkg = bkg .. bar_bkg end -- draw bar for y = 1, e.frame.h do e.window.setCursorPos(1, y) - e.window.blit(spaces, fgd, bkg) + -- intentionally swapped fgd/bkg since we use spaces as fill, but they are the opposite + e.window.blit(spaces, bkg, fgd) end end diff --git a/graphics/elements/indicator_icon.lua b/graphics/elements/indicators/icon.lua similarity index 87% rename from graphics/elements/indicator_icon.lua rename to graphics/elements/indicators/icon.lua index 6bcf326..d116f2b 100644 --- a/graphics/elements/indicator_icon.lua +++ b/graphics/elements/indicators/icon.lua @@ -11,7 +11,7 @@ local element = require("graphics.element") ---@class icon_indicator_args ---@field label string indicator label ---@field states table state color and symbol table ----@field default? integer default state, defaults to 1 +---@field value? integer default state, defaults to 1 ---@field min_label_width? integer label length if omitted ---@field parent graphics_element ---@field x? integer 1 if omitted @@ -20,9 +20,12 @@ local element = require("graphics.element") -- new icon indicator ---@param args icon_indicator_args -local function icon_indicator(args) - assert(type(args.label) == "string", "graphics.elements.indicator_icon: label is a required field") - assert(type(args.states) == "table", "graphics.elements.indicator_icon: states is a required field") +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") + + -- single line + args.height = 1 -- determine width args.width = math.max(args.min_label_width or 1, string.len(args.label)) + 4 @@ -55,9 +58,9 @@ local function icon_indicator(args) end -- initial icon draw - e.on_update(args.default or 1) + e.on_update(args.value or 1) return e.get() end -return icon_indicator +return icon diff --git a/graphics/elements/indicator_light.lua b/graphics/elements/indicators/light.lua similarity index 92% rename from graphics/elements/indicator_light.lua rename to graphics/elements/indicators/light.lua index 8cf7d14..6db28db 100644 --- a/graphics/elements/indicator_light.lua +++ b/graphics/elements/indicators/light.lua @@ -16,8 +16,11 @@ local element = require("graphics.element") -- new indicator light ---@param args indicator_light_args local function indicator_light(args) - assert(type(args.label) == "string", "graphics.elements.indicator_light: label is a required field") - assert(type(args.colors) == "table", "graphics.elements.indicator_light: colors is a required field") + 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") + + -- single line + args.height = 1 -- determine width args.width = math.max(args.min_label_width or 1, string.len(args.label)) + 3 diff --git a/graphics/elements/indicator_state.lua b/graphics/elements/indicators/state.lua similarity index 79% rename from graphics/elements/indicator_state.lua rename to graphics/elements/indicators/state.lua index 722f633..0383fd8 100644 --- a/graphics/elements/indicator_state.lua +++ b/graphics/elements/indicators/state.lua @@ -10,7 +10,7 @@ local element = require("graphics.element") ---@class state_indicator_args ---@field states table state color and text table ----@field default? integer default state, defaults to 1 +---@field value? integer default state, defaults to 1 ---@field min_width? integer max state text length if omitted ---@field parent graphics_element ---@field x? integer 1 if omitted @@ -21,11 +21,11 @@ local element = require("graphics.element") -- new state indicator ---@param args state_indicator_args local function state_indicator(args) - assert(type(args.states) == "table", "graphics.elements.indicator_state: states is a required field") + assert(type(args.states) == "table", "graphics.elements.indicators.state: states is a required field") -- determine height if util.is_int(args.height) then - assert(args.height % 2 == 1, "graphics.elements.indicator_state: height should be an odd number") + assert(args.height % 2 == 1, "graphics.elements.indicators.state: height should be an odd number") else args.height = 1 end @@ -45,12 +45,14 @@ local function state_indicator(args) local len = string.len(state_def.text) local lpad = math.floor((args.width - len) / 2) - local rpad = len - lpad + local rpad = args.width - lpad + + local text = util.spaces(lpad) .. state_def.text .. util.spaces(rpad) table.insert(state_blit_cmds, { - text = util.spaces(lpad) .. state_def.text .. util.spaces(rpad), - fgd = util.strrep(state_def.color.blit_fgd, 3), - bkg = util.strrep(state_def.color.blit_bkg, 3) + text = text, + fgd = util.strrep(state_def.color.blit_fgd, string.len(text)), + bkg = util.strrep(state_def.color.blit_bkg, string.len(text)) }) end @@ -66,7 +68,7 @@ local function state_indicator(args) end -- initial draw - e.on_update(args.default or 1) + e.on_update(args.value or 1) return e.get() end diff --git a/graphics/elements/vbar.lua b/graphics/elements/indicators/vbar.lua similarity index 100% rename from graphics/elements/vbar.lua rename to graphics/elements/indicators/vbar.lua