mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
parent
285026c1fa
commit
8ea75b9501
@ -1,36 +1,58 @@
|
||||
local log = require("scada-common.log")
|
||||
local log = require("scada-common.log")
|
||||
local util = require("scada-common.util")
|
||||
|
||||
local displaybox = require("graphics.elements.displaybox")
|
||||
local structs = require("graphics.structs")
|
||||
|
||||
local renderer = {}
|
||||
|
||||
local gconf = {
|
||||
-- root boxes
|
||||
root = {
|
||||
fgd = colors.black,
|
||||
bkg = colors.lightGray
|
||||
}
|
||||
}
|
||||
|
||||
-- render engine
|
||||
local engine = {
|
||||
monitors = nil,
|
||||
dmesg_window = nil
|
||||
}
|
||||
|
||||
-- UI elements
|
||||
local ui = {
|
||||
main_box = nil,
|
||||
unit_boxes = {}
|
||||
}
|
||||
|
||||
-- reset a display to the "default", but set text scale to 0.5
|
||||
local function _reset_display(monitor)
|
||||
monitor.setTextScale(0.5)
|
||||
monitor.setTextColor(colors.white)
|
||||
monitor.setBackgroundColor(colors.black)
|
||||
monitor.clear()
|
||||
monitor.setCursorPos(1, 1)
|
||||
end
|
||||
|
||||
-- link to the monitor peripherals
|
||||
---@param monitors monitors_struct
|
||||
function renderer.set_displays(monitors)
|
||||
engine.monitors = monitors
|
||||
end
|
||||
|
||||
-- reset all displays in use by the renderer
|
||||
function renderer.reset()
|
||||
-- reset primary monitor
|
||||
engine.monitors.primary.setTextScale(0.5)
|
||||
engine.monitors.primary.setTextColor(colors.white)
|
||||
engine.monitors.primary.setBackgroundColor(colors.black)
|
||||
engine.monitors.primary.clear()
|
||||
engine.monitors.primary.setCursorPos(1, 1)
|
||||
_reset_display(engine.monitors.primary)
|
||||
|
||||
-- reset unit displays
|
||||
for _, monitor in pairs(engine.monitors.unit_displays) do
|
||||
monitor.setTextScale(0.5)
|
||||
monitor.setTextColor(colors.white)
|
||||
monitor.setBackgroundColor(colors.black)
|
||||
monitor.clear()
|
||||
monitor.setCursorPos(1, 1)
|
||||
_reset_display(monitor)
|
||||
end
|
||||
end
|
||||
|
||||
-- initialize the dmesg output window
|
||||
function renderer.init_dmesg()
|
||||
local disp_x, disp_y = engine.monitors.primary.getSize()
|
||||
engine.dmesg_window = window.create(engine.monitors.primary, 1, 1, disp_x, disp_y)
|
||||
@ -38,4 +60,22 @@ function renderer.init_dmesg()
|
||||
log.direct_dmesg(engine.dmesg_window)
|
||||
end
|
||||
|
||||
-- start the coordinator GUI
|
||||
function renderer.start_ui()
|
||||
local palette = structs.graphics.cpair(gconf.root.fgd, gconf.root.bkg)
|
||||
|
||||
ui.main_box = displaybox{window = engine.monitors.primary, fg_bg = palette}
|
||||
|
||||
for _, monitor in pairs(engine.monitors.unit_displays) do
|
||||
table.insert(ui.unit_boxes, displaybox{window = engine.monitors.primary, fg_bg = palette})
|
||||
end
|
||||
end
|
||||
|
||||
-- close out the UI
|
||||
function renderer.close_ui()
|
||||
-- clear root UI elements
|
||||
ui.main_box = nil
|
||||
ui.unit_boxes = {}
|
||||
end
|
||||
|
||||
return renderer
|
||||
|
@ -12,7 +12,7 @@ local config = require("coordinator.config")
|
||||
local coordinator = require("coordinator.coordinator")
|
||||
local renderer = require("coordinator.renderer")
|
||||
|
||||
local COORDINATOR_VERSION = "alpha-v0.1.4"
|
||||
local COORDINATOR_VERSION = "alpha-v0.1.5"
|
||||
|
||||
local print = util.print
|
||||
local println = util.println
|
||||
@ -81,3 +81,12 @@ if modem == nil then
|
||||
end
|
||||
|
||||
log.dmesg("wireless modem connected", "COMMS", colors.purple)
|
||||
|
||||
log.dmesg("starting UI...", "GRAPHICS", colors.green)
|
||||
util.psleep(3)
|
||||
|
||||
local ui_ok = pcall(renderer.start_ui)
|
||||
if not ui_ok then
|
||||
renderer.close_ui()
|
||||
log.dmesg("UI draw failed", "GRAPHICS", colors.green)
|
||||
end
|
||||
|
73
graphics/core.lua
Normal file
73
graphics/core.lua
Normal file
@ -0,0 +1,73 @@
|
||||
local core = {}
|
||||
|
||||
local events = {}
|
||||
|
||||
---@class monitor_touch
|
||||
---@field monitor string
|
||||
---@field x integer
|
||||
---@field y integer
|
||||
|
||||
---@param monitor string
|
||||
---@param x integer
|
||||
---@param y integer
|
||||
---@return monitor_touch
|
||||
function events.touch(monitor, x, y)
|
||||
return {
|
||||
monitor = monitor,
|
||||
x = x,
|
||||
y = y
|
||||
}
|
||||
end
|
||||
|
||||
core.events = events
|
||||
|
||||
local graphics = {}
|
||||
|
||||
---@alias TEXT_ALIGN integer
|
||||
graphics.TEXT_ALIGN = {
|
||||
LEFT = 1,
|
||||
CENTER = 2,
|
||||
RIGHT = 3
|
||||
}
|
||||
|
||||
---@class graphics_frame
|
||||
---@field x integer
|
||||
---@field y integer
|
||||
---@field w integer
|
||||
---@field h integer
|
||||
|
||||
---@param x integer
|
||||
---@param y integer
|
||||
---@param w integer
|
||||
---@param h integer
|
||||
---@return graphics_frame
|
||||
function graphics.gframe(x, y, w, h)
|
||||
return {
|
||||
x = x,
|
||||
y = y,
|
||||
w = w,
|
||||
h = h
|
||||
}
|
||||
end
|
||||
|
||||
---@class cpair
|
||||
---@field fgd color
|
||||
---@field bkg color
|
||||
---@field blit_fgd string
|
||||
---@field blit_bkg string
|
||||
|
||||
---@param foreground color
|
||||
---@param background color
|
||||
---@return cpair
|
||||
function graphics.cpair(foreground, background)
|
||||
return {
|
||||
fgd = foreground,
|
||||
bkg = background,
|
||||
blit_fgd = colors.toBlit(foreground),
|
||||
blit_bkg = colors.toBlit(background)
|
||||
}
|
||||
end
|
||||
|
||||
core.graphics = graphics
|
||||
|
||||
return core
|
124
graphics/element.lua
Normal file
124
graphics/element.lua
Normal file
@ -0,0 +1,124 @@
|
||||
local core = require("graphics.core")
|
||||
|
||||
local element = {}
|
||||
|
||||
---@class graphics_args_generic
|
||||
---@field window? table
|
||||
---@field parent? graphics_element
|
||||
---@field x? integer 1 if omitted
|
||||
---@field y? integer 1 if omitted
|
||||
---@field width? integer parent width if omitted
|
||||
---@field height? integer parent height if omitted
|
||||
---@field gframe? graphics_frame frame instead of x/y/width/height
|
||||
---@field fg_bg? cpair foreground/background colors
|
||||
|
||||
-- a base graphics element, should not be created on its own
|
||||
---@param args graphics_args_generic arguments
|
||||
function element.new(args)
|
||||
local self = {
|
||||
p_window = nil, ---@type table
|
||||
position = { x = 1, y = 1 },
|
||||
bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1}
|
||||
}
|
||||
|
||||
local protected = {
|
||||
window = nil, ---@type table
|
||||
frame = core.graphics.gframe(1, 1, 1, 1)
|
||||
}
|
||||
|
||||
-- SETUP --
|
||||
|
||||
-- get the parent window
|
||||
self.p_window = args.window or args.parent.window()
|
||||
|
||||
assert(self.p_window, "graphics.element: 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
|
||||
|
||||
-- create window
|
||||
local f = protected.frame
|
||||
protected.window = window.create(self.p_window, f.x, f.y, f.w, f.h, true)
|
||||
|
||||
-- init display box
|
||||
if args.fg_bg ~= nil then
|
||||
protected.window.setBackgroundColor(args.fg_bg.bkg)
|
||||
protected.window.setTextColor(args.fg_bg.fgd)
|
||||
protected.window.clear()
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
-- PROTECTED FUNCTIONS --
|
||||
|
||||
-- handle a touch event
|
||||
---@param event table monitor_touch event
|
||||
function protected.handle_touch(event)
|
||||
end
|
||||
|
||||
-- handle data value changes
|
||||
function protected.on_update(...)
|
||||
end
|
||||
|
||||
---@class graphics_element
|
||||
local public = {}
|
||||
|
||||
-- get public interface
|
||||
function protected.get() return public end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
|
||||
-- get the window object
|
||||
function public.window() return protected.window end
|
||||
|
||||
-- handle a monitor touch
|
||||
---@param event monitor_touch monitor touch event
|
||||
function public.handle_touch(event)
|
||||
local in_x = event.x >= self.bounds.x1 and event.x <= self.bounds.x2
|
||||
local in_y = event.y >= self.bounds.y1 and event.y <= self.bounds.y2
|
||||
|
||||
if in_x and in_y then
|
||||
-- handle the touch event, transformed into the window frame
|
||||
protected.handle_touch(core.events.touch(event.monitor,
|
||||
(event.x - self.position.x) + 1,
|
||||
(event.y - self.position.y) + 1))
|
||||
end
|
||||
end
|
||||
|
||||
-- draw the element given new data
|
||||
function public.draw(...)
|
||||
protected.on_update(...)
|
||||
end
|
||||
|
||||
-- show the element
|
||||
function public.show()
|
||||
protected.window.setVisible(true)
|
||||
end
|
||||
|
||||
-- hide the element
|
||||
function public.hide()
|
||||
protected.window.setVisible(false)
|
||||
end
|
||||
|
||||
return protected
|
||||
end
|
||||
|
||||
return element
|
21
graphics/elements/displaybox.lua
Normal file
21
graphics/elements/displaybox.lua
Normal file
@ -0,0 +1,21 @@
|
||||
-- Root Display Box Graphics Element
|
||||
|
||||
local element = require("graphics.element")
|
||||
|
||||
---@class displaybox_args
|
||||
---@field window table
|
||||
---@field x? integer 1 if omitted
|
||||
---@field y? integer 1 if omitted
|
||||
---@field width? integer parent width if omitted
|
||||
---@field height? integer parent height if omitted
|
||||
---@field gframe? graphics_frame frame instead of x/y/width/height
|
||||
---@field fg_bg? cpair foreground/background colors
|
||||
|
||||
-- new root display box
|
||||
---@param args displaybox_args
|
||||
local function displaybox(args)
|
||||
-- create new graphics element base object
|
||||
return element.new(args).get()
|
||||
end
|
||||
|
||||
return displaybox
|
74
graphics/elements/textbox.lua
Normal file
74
graphics/elements/textbox.lua
Normal file
@ -0,0 +1,74 @@
|
||||
-- Text Box Graphics Element
|
||||
|
||||
local element = require("graphics.element")
|
||||
|
||||
---@class textbox_args
|
||||
---@field text string text to show
|
||||
---@field parent graphics_element
|
||||
---@field x? integer 1 if omitted
|
||||
---@field y? integer 1 if omitted
|
||||
---@field width? integer parent width if omitted
|
||||
---@field height? integer parent height if omitted
|
||||
---@field gframe? graphics_frame frame instead of x/y/width/height
|
||||
---@field fg_bg? cpair foreground/background colors
|
||||
|
||||
-- new text box
|
||||
---@param args textbox_args
|
||||
local function textbox(args)
|
||||
assert(args.text ~= nil, "graphics.elements.textbox: empty text box")
|
||||
|
||||
-- create new graphics element base object
|
||||
local e = element.new(args)
|
||||
|
||||
-- write text
|
||||
|
||||
local text = args.text
|
||||
local lines = { text }
|
||||
|
||||
local w = e.frame.w
|
||||
local h = e.frame.h
|
||||
|
||||
-- wrap if needed
|
||||
if string.len(text) > w then
|
||||
local remaining = true
|
||||
local s_start = 1
|
||||
local s_end = w
|
||||
local i = 1
|
||||
|
||||
lines = {}
|
||||
|
||||
while remaining do
|
||||
local line = string.sub(text, s_start, s_end)
|
||||
|
||||
if line == "" then
|
||||
remaining = false
|
||||
else
|
||||
lines[i] = line
|
||||
|
||||
s_start = s_end + 1
|
||||
s_end = s_end + w
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- output message
|
||||
for i = 1, #lines do
|
||||
local cur_x, cur_y = e.window.getCursorPos()
|
||||
|
||||
if i > 1 and cur_x > 1 then
|
||||
if cur_y == h then
|
||||
e.window.scroll(1)
|
||||
e.window.setCursorPos(1, cur_y)
|
||||
else
|
||||
e.window.setCursorPos(1, cur_y + 1)
|
||||
end
|
||||
end
|
||||
|
||||
e.window.write(lines[i])
|
||||
end
|
||||
|
||||
return e.get()
|
||||
end
|
||||
|
||||
return textbox
|
Loading…
Reference in New Issue
Block a user