diff --git a/coordinator/configure.lua b/coordinator/configure.lua index a46c179..3afe54a 100644 --- a/coordinator/configure.lua +++ b/coordinator/configure.lua @@ -42,8 +42,8 @@ local RIGHT = core.ALIGN.RIGHT -- changes to the config data/format to let the user know local changes = { - {"v1.2.4", { "Added temperature scale options" } }, - {"v1.2.12", { "Added main UI theme", "Added front panel UI theme", "Added color accessibility modes" } } + { "v1.2.4", { "Added temperature scale options" } }, + { "v1.2.12", { "Added main UI theme", "Added front panel UI theme", "Added color accessibility modes" } } } ---@class crd_configurator diff --git a/reactor-plc/configure.lua b/reactor-plc/configure.lua index 445f1fb..80ef86c 100644 --- a/reactor-plc/configure.lua +++ b/reactor-plc/configure.lua @@ -36,9 +36,9 @@ local RIGHT = core.ALIGN.RIGHT -- changes to the config data/format to let the user know local changes = { - {"v1.6.2", { "AuthKey minimum length is now 8 (if set)" } }, - {"v1.6.8", { "ConnTimeout can now have a fractional part" } }, - {"v1.2.12", { "Added front panel UI theme", "Added color accessibility modes" } } + { "v1.6.2", { "AuthKey minimum length is now 8 (if set)" } }, + { "v1.6.8", { "ConnTimeout can now have a fractional part" } }, + { "v1.6.15", { "Added front panel UI theme", "Added color accessibility modes" } } } ---@class plc_configurator @@ -70,6 +70,7 @@ local g_lg_fg_bg = cpair(colors.gray, colors.lightGray) local nav_fg_bg = bw_fg_bg local btn_act_fg_bg = cpair(colors.white, colors.gray) +---@class _plc_cfg_tool_ctl local tool_ctl = { ask_config = false, has_config = false, diff --git a/rtu/configure.lua b/rtu/configure.lua index 131623b..cfda26d 100644 --- a/rtu/configure.lua +++ b/rtu/configure.lua @@ -24,6 +24,8 @@ local RadioButton = require("graphics.elements.controls.radio_button") local NumberField = require("graphics.elements.form.number_field") local TextField = require("graphics.elements.form.text_field") +local IndLight = require("graphics.elements.indicators.light") + local println = util.println local tri = util.trinary @@ -73,7 +75,8 @@ assert(#PORT_DSGN == rsio.NUM_PORTS) -- changes to the config data/format to let the user know local changes = { - {"v1.7.9", { "ConnTimeout can now have a fractional part" } } + { "v1.7.9", { "ConnTimeout can now have a fractional part" } }, + { "v1.7.15", { "Added front panel UI theme", "Added color accessibility modes" } } } ---@class rtu_rs_definition @@ -119,13 +122,15 @@ local g_lg_fg_bg = cpair(colors.gray, colors.lightGray) local nav_fg_bg = bw_fg_bg local btn_act_fg_bg = cpair(colors.white, colors.gray) +---@class _rtu_cfg_tool_ctl local tool_ctl = { ask_config = false, has_config = false, viewing_config = false, importing_legacy = false, importing_any_dc = false, - peri_cfg_editing = false, ---@type string|false + jumped_to_color = false, + peri_cfg_editing = false, ---@type integer|false peri_cfg_manual = false, rs_cfg_port = IO.F_SCRAM, ---@type IO_PORT rs_cfg_editing = false, ---@type integer|false @@ -133,6 +138,9 @@ local tool_ctl = { view_gw_cfg = nil, ---@type graphics_element dev_cfg = nil, ---@type graphics_element rs_cfg = nil, ---@type graphics_element + color_cfg = nil, ---@type graphics_element + color_next = nil, ---@type graphics_element + color_apply = nil, ---@type graphics_element settings_apply = nil, ---@type graphics_element settings_confirm = nil, ---@type graphics_element @@ -181,7 +189,9 @@ local tmp_cfg = { AuthKey = nil, ---@type string|nil LogMode = 0, LogPath = "", - LogDebug = false + LogDebug = false, + FrontPanelTheme = 1, + ColorMode = 1 } ---@class rtu_config @@ -198,7 +208,9 @@ local fields = { { "AuthKey", "Facility Auth Key", "" }, { "LogMode", "Log Mode", log.MODE.APPEND }, { "LogPath", "Log Path", "/log.txt" }, - { "LogDebug","Log Debug Messages", false } + { "LogDebug","Log Debug Messages", false }, + { "FrontPanelTheme", "Front Panel Theme", 1 }, + { "ColorMode", "Color Mode", 1 } } local side_options = { "Top", "Bottom", "Left", "Right", "Front", "Back" } @@ -266,12 +278,13 @@ local function config_view(display) local spkr_cfg = Div{parent=root_pane_div,x=1,y=1} local net_cfg = Div{parent=root_pane_div,x=1,y=1} local log_cfg = Div{parent=root_pane_div,x=1,y=1} + local clr_cfg = Div{parent=root_pane_div,x=1,y=1} local summary = Div{parent=root_pane_div,x=1,y=1} local changelog = Div{parent=root_pane_div,x=1,y=1} local peri_cfg = Div{parent=root_pane_div,x=1,y=1} local rs_cfg = Div{parent=root_pane_div,x=1,y=1} - local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,spkr_cfg,net_cfg,log_cfg,summary,changelog,peri_cfg,rs_cfg}} + local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,spkr_cfg,net_cfg,log_cfg,clr_cfg,summary,changelog,peri_cfg,rs_cfg}} --#region Main Page @@ -290,7 +303,7 @@ local function config_view(display) tool_ctl.gen_summary(settings_cfg) tool_ctl.settings_apply.hide(true) tool_ctl.settings_confirm.hide(true) - main_pane.set_value(5) + main_pane.set_value(6) end if fs.exists("/rtu/config.lua") then @@ -300,12 +313,12 @@ local function config_view(display) local function show_peri_conns() tool_ctl.gen_peri_summary(ini_cfg) - main_pane.set_value(7) + main_pane.set_value(8) end local function show_rs_conns() tool_ctl.gen_rs_summary(ini_cfg) - main_pane.set_value(8) + main_pane.set_value(9) end PushButton{parent=main_page,x=2,y=y_start,min_width=19,text="Configure Gateway",callback=function()main_pane.set_value(2)end,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg} @@ -313,15 +326,24 @@ local function config_view(display) tool_ctl.dev_cfg = PushButton{parent=main_page,x=2,y=y_start+4,min_width=24,text="Peripheral Connections",callback=show_peri_conns,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=btn_act_fg_bg,dis_fg_bg=cpair(colors.lightGray,colors.white)} tool_ctl.rs_cfg = PushButton{parent=main_page,x=2,y=y_start+6,min_width=22,text="Redstone Connections",callback=show_rs_conns,fg_bg=cpair(colors.black,colors.yellow),active_fg_bg=btn_act_fg_bg,dis_fg_bg=cpair(colors.lightGray,colors.white)} + local function jump_color() + tool_ctl.jumped_to_color = true + tool_ctl.color_next.hide() + tool_ctl.color_apply.show(true) + main_pane.set_value(5) + end + + PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg} + tool_ctl.color_cfg = PushButton{parent=main_page,x=23,y=17,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + if not tool_ctl.has_config then tool_ctl.view_gw_cfg.disable() tool_ctl.dev_cfg.disable() tool_ctl.rs_cfg.disable() + tool_ctl.color_cfg.disable() end - PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg} - PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} - --#endregion --#region Speakers @@ -480,11 +502,8 @@ local function config_view(display) tmp_cfg.LogMode = mode.get_value() - 1 tmp_cfg.LogPath = path.get_value() tmp_cfg.LogDebug = en_dbg.get_value() - tool_ctl.gen_summary(tmp_cfg) - tool_ctl.viewing_config = false - tool_ctl.importing_legacy = false - tool_ctl.settings_apply.show() - tool_ctl.settings_confirm.hide(true) + tool_ctl.color_apply.hide(true) + tool_ctl.color_next.show() main_pane.set_value(5) else path_err.show() end end @@ -494,6 +513,106 @@ local function config_view(display) --#endregion + --#region Color Options + + local clr_c_1 = Div{parent=clr_cfg,x=2,y=4,width=49} + local clr_c_2 = Div{parent=clr_cfg,x=2,y=4,width=49} + local clr_c_3 = Div{parent=clr_cfg,x=2,y=4,width=49} + local clr_c_4 = Div{parent=clr_cfg,x=2,y=4,width=49} + + local clr_pane = MultiPane{parent=clr_cfg,x=1,y=4,panes={clr_c_1,clr_c_2,clr_c_3,clr_c_4}} + + TextBox{parent=clr_cfg,x=1,y=2,height=1,text=" Color Configuration",fg_bg=cpair(colors.black,colors.magenta)} + + TextBox{parent=clr_c_1,x=1,y=1,height=2,text="Here you can select the color theme for the front panel."} + TextBox{parent=clr_c_1,x=1,y=4,height=2,text="Click 'Accessibility' below to access color blind assistive options.",fg_bg=g_lg_fg_bg} + + TextBox{parent=clr_c_1,x=1,y=7,height=1,text="Front Panel Theme"} + local fp_theme = RadioButton{parent=clr_c_1,x=1,y=8,default=ini_cfg.FrontPanelTheme,options={"Sandstone","Basalt"},callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.magenta} + + TextBox{parent=clr_c_2,x=1,y=1,height=6,text="By default, this project uses green/red heavily to distinguish ok and not, with some indicators also using multiple colors. By selecting a color blindness below, blues will be used instead of greens on indicators and multi-color indicators will be split up as space permits."} + + local function recolor(value) + if value == 1 then + for i = 1, #style.colors do term.setPaletteColor(style.colors[i].c, style.colors[i].hex) end + elseif value == 2 then + term.setPaletteColor(colors.green, 0x1081ff) + term.setPaletteColor(colors.yellow, 0xf5e633) + term.setPaletteColor(colors.red, 0xff521a) + elseif value == 3 then + term.setPaletteColor(colors.green, 0x1081ff) + term.setPaletteColor(colors.yellow, 0xf7c311) + term.setPaletteColor(colors.red, 0xfb5615) + elseif value == 4 then + term.setPaletteColor(colors.green, 0x00ecff) + term.setPaletteColor(colors.yellow, 0xffbc00) + term.setPaletteColor(colors.red, 0xff0000) + end + end + + local c_mode = RadioButton{parent=clr_c_2,x=1,y=8,default=ini_cfg.ColorMode,options={"None","Protanopia","Deuteranopia","Tritanopia"},callback=recolor,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.magenta} + + local _ = IndLight{parent=clr_c_2,x=20,y=8,label="Good",colors=cpair(colors.black,colors.green),value=true} + _ = IndLight{parent=clr_c_2,x=20,y=9,label="Warning",colors=cpair(colors.black,colors.yellow),value=true} + _ = IndLight{parent=clr_c_2,x=20,y=10,label="Bad",colors=cpair(colors.black,colors.red),value=true} + + TextBox{parent=clr_c_2,x=20,y=12,height=6,text="Exact color varies by theme.",fg_bg=g_lg_fg_bg} + + PushButton{parent=clr_c_2,x=44,y=14,min_width=6,text="Done",callback=function()clr_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + local function back_from_colors() + main_pane.set_value(util.trinary(tool_ctl.jumped_to_color, 1, 4)) + tool_ctl.jumped_to_color = false + recolor(1) + end + + local function show_access() + clr_pane.set_value(2) + recolor(c_mode.get_value()) + end + + local function submit_colors() + tmp_cfg.FrontPanelTheme = fp_theme.get_value() + tmp_cfg.ColorMode = c_mode.get_value() + + if tool_ctl.jumped_to_color then + settings.set("FrontPanelTheme", tmp_cfg.FrontPanelTheme) + settings.set("ColorMode", tmp_cfg.ColorMode) + + if settings.save("/rtu.settings") then + load_settings(settings_cfg, true) + load_settings(ini_cfg) + clr_pane.set_value(3) + else + clr_pane.set_value(4) + end + else + tool_ctl.gen_summary(tmp_cfg) + tool_ctl.viewing_config = false + tool_ctl.importing_legacy = false + tool_ctl.settings_apply.show() + tool_ctl.settings_confirm.hide(true) + main_pane.set_value(6) + end + end + + PushButton{parent=clr_c_1,x=1,y=14,text="\x1b Back",callback=back_from_colors,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=clr_c_1,x=8,y=14,min_width=15,text="Accessibility",callback=show_access,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + tool_ctl.color_next = PushButton{parent=clr_c_1,x=44,y=14,text="Next \x1a",callback=submit_colors,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + tool_ctl.color_apply = PushButton{parent=clr_c_1,x=43,y=14,min_width=7,text="Apply",callback=submit_colors,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg} + + tool_ctl.color_apply.hide() + + TextBox{parent=clr_c_3,x=1,y=1,height=1,text="Settings saved!"} + PushButton{parent=clr_c_3,x=1,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} + PushButton{parent=clr_c_3,x=44,y=14,min_width=6,text="Home",callback=function()tool_ctl.go_home()end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + TextBox{parent=clr_c_4,x=1,y=1,height=5,text="Failed to save the settings file.\n\nThere may not be enough space for the modification or server file permissions may be denying writes."} + PushButton{parent=clr_c_4,x=1,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} + PushButton{parent=clr_c_4,x=44,y=14,min_width=6,text="Home",callback=function()tool_ctl.go_home()end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + --#endregion + --#region Summary and Saving local sum_c_1 = Div{parent=summary,x=2,y=4,width=49} @@ -520,7 +639,7 @@ local function config_view(display) end tool_ctl.viewing_config = false - else main_pane.set_value(4) end + else main_pane.set_value(5) end end ---@param element graphics_element @@ -552,6 +671,8 @@ local function config_view(display) try_set(mode, ini_cfg.LogMode) try_set(path, ini_cfg.LogPath) try_set(en_dbg, ini_cfg.LogDebug) + try_set(fp_theme, ini_cfg.FrontPanelTheme) + try_set(c_mode, ini_cfg.ColorMode) if not exclude_conns then tmp_cfg.Peripherals = deep_copy_peri(ini_cfg.Peripherals) @@ -1257,7 +1378,7 @@ local function config_view(display) tool_ctl.gen_summary(tmp_cfg) if tool_ctl.importing_any_dc then sum_pane.set_value(7) else sum_pane.set_value(1) end - main_pane.set_value(5) + main_pane.set_value(6) tool_ctl.settings_apply.hide(true) tool_ctl.settings_confirm.show() tool_ctl.importing_legacy = true @@ -1271,6 +1392,7 @@ local function config_view(display) main_pane.set_value(1) net_pane.set_value(1) + clr_pane.set_value(1) sum_pane.set_value(1) peri_pane.set_value(1) rs_pane.set_value(1) @@ -1301,8 +1423,14 @@ local function config_view(display) local raw = cfg[f[1]] local val = util.strval(raw) - if f[1] == "AuthKey" then val = string.rep("*", string.len(val)) end - if f[1] == "LogMode" then val = util.trinary(raw == log.MODE.APPEND, "append", "replace") end + if f[1] == "AuthKey" then val = string.rep("*", string.len(val)) + elseif f[1] == "LogMode" then val = util.trinary(raw == log.MODE.APPEND, "append", "replace") + elseif f[1] == "FrontPanelTheme" then + if raw == 1 then val = "Sandstone" elseif raw == 2 then val = "Basalt" end + elseif f[1] == "ColorMode" then + if raw == 1 then val = "Standard" elseif raw == 2 then val = "Protanopia" elseif raw == 3 then val = "Deuteranopia" elseif raw == 4 then val = "Tritanopia" end + end + if val == "nil" then val = "" end local c = util.trinary(alternate, g_lg_fg_bg, cpair(colors.gray,colors.white)) diff --git a/rtu/panel/front_panel.lua b/rtu/panel/front_panel.lua index be81b27..9989e9a 100644 --- a/rtu/panel/front_panel.lua +++ b/rtu/panel/front_panel.lua @@ -22,8 +22,6 @@ local ALIGN = core.ALIGN local cpair = core.cpair -local disabled_fg = style.fp.disabled_fg - local ind_grn = style.ind_grn local UNIT_TYPE_LABELS = { "UNKNOWN", "REDSTONE", "BOILER", "TURBINE", "DYNAMIC TANK", "IND MATRIX", "SPS", "SNA", "ENV DETECTOR" } @@ -32,6 +30,8 @@ local UNIT_TYPE_LABELS = { "UNKNOWN", "REDSTONE", "BOILER", "TURBINE", "DYNAMIC ---@param panel graphics_element main displaybox ---@param units table unit list local function init(panel, units) + local disabled_fg = style.fp.disabled_fg + TextBox{parent=panel,y=1,text="RTU GATEWAY",alignment=ALIGN.CENTER,height=1,fg_bg=style.theme.header} -- diff --git a/rtu/panel/style.lua b/rtu/panel/style.lua index 0b646a3..36fd542 100644 --- a/rtu/panel/style.lua +++ b/rtu/panel/style.lua @@ -10,9 +10,21 @@ local style = {} local cpair = core.cpair -style.theme = themes.basalt +style.theme = themes.sandstone style.fp = themes.get_fp_style(style.theme) style.ind_grn = cpair(colors.green, colors.green_off) +-- set theme per configuration +---@param fp integer fp theme ID (1 = sandstone, 2 = basalt) +function style.set_theme(fp) + if fp == 1 then + style.theme = themes.sandstone + elseif fp == 2 then + style.theme = themes.basalt + end + + style.fp = themes.get_fp_style(style.theme) +end + return style diff --git a/rtu/renderer.lua b/rtu/renderer.lua index 642823a..2a1a235 100644 --- a/rtu/renderer.lua +++ b/rtu/renderer.lua @@ -19,11 +19,15 @@ local ui = { -- try to start the UI ---@param units table RTU units +---@param theme integer front panel theme ID (1 = sandstone, 2 = basalt) ---@return boolean success, any error_msg -function renderer.try_start_ui(units) +function renderer.try_start_ui(units, theme) local status, msg = true, nil if ui.display == nil then + -- set theme + style.set_theme(theme) + -- reset terminal term.setTextColor(colors.white) term.setBackgroundColor(colors.black) diff --git a/rtu/rtu.lua b/rtu/rtu.lua index 6c2b01f..5e49cf9 100644 --- a/rtu/rtu.lua +++ b/rtu/rtu.lua @@ -29,15 +29,20 @@ function rtu.load_config() config.Redstone = settings.get("Redstone") config.SpeakerVolume = settings.get("SpeakerVolume") + config.SVR_Channel = settings.get("SVR_Channel") config.RTU_Channel = settings.get("RTU_Channel") config.ConnTimeout = settings.get("ConnTimeout") config.TrustedRange = settings.get("TrustedRange") config.AuthKey = settings.get("AuthKey") + config.LogMode = settings.get("LogMode") config.LogPath = settings.get("LogPath") config.LogDebug = settings.get("LogDebug") + config.FrontPanelTheme = settings.get("FrontPanelTheme") + config.ColorMode = settings.get("ColorMode") + local cfv = util.new_validator() cfv.assert_type_num(config.SpeakerVolume) @@ -61,6 +66,11 @@ function rtu.load_config() cfv.assert_type_str(config.LogPath) cfv.assert_type_bool(config.LogDebug) + cfv.assert_type_int(config.FrontPanelTheme) + cfv.assert_range(config.FrontPanelTheme, 1, 2) + cfv.assert_type_int(config.ColorMode) + cfv.assert_range(config.ColorMode, 1, 4) + cfv.assert_type_table(config.Peripherals) cfv.assert_type_table(config.Redstone) diff --git a/rtu/startup.lua b/rtu/startup.lua index 90b81a0..8888d05 100644 --- a/rtu/startup.lua +++ b/rtu/startup.lua @@ -506,7 +506,7 @@ local function main() if sys_config() then -- start UI local message - rtu_state.fp_ok, message = renderer.try_start_ui(units) + rtu_state.fp_ok, message = renderer.try_start_ui(units, config.FrontPanelTheme) if not rtu_state.fp_ok then println_ts(util.c("UI error: ", message)) diff --git a/supervisor/configure.lua b/supervisor/configure.lua index 34398b6..0b63519 100644 --- a/supervisor/configure.lua +++ b/supervisor/configure.lua @@ -22,6 +22,8 @@ local RadioButton = require("graphics.elements.controls.radio_button") local NumberField = require("graphics.elements.form.number_field") local TextField = require("graphics.elements.form.text_field") +local IndLight = require("graphics.elements.indicators.light") + local println = util.println local tri = util.trinary @@ -32,7 +34,9 @@ local CENTER = core.ALIGN.CENTER local RIGHT = core.ALIGN.RIGHT -- changes to the config data/format to let the user know -local changes = {} +local changes = { + { "v1.2.12", { "Added front panel UI theme", "Added color accessibility modes" } } +} ---@class svr_configurator local configurator = {} @@ -63,13 +67,18 @@ local g_lg_fg_bg = cpair(colors.gray, colors.lightGray) local nav_fg_bg = bw_fg_bg local btn_act_fg_bg = cpair(colors.white, colors.gray) +---@class _svr_cfg_tool_ctl local tool_ctl = { ask_config = false, has_config = false, viewing_config = false, importing_legacy = false, + jumped_to_color = false, view_cfg = nil, ---@type graphics_element + color_cfg = nil, ---@type graphics_element + color_next = nil, ---@type graphics_element + color_apply = nil, ---@type graphics_element settings_apply = nil, ---@type graphics_element gen_summary = nil, ---@type function @@ -108,6 +117,8 @@ local tmp_cfg = { LogMode = 0, LogPath = "", LogDebug = false, + FrontPanelTheme = 1, + ColorMode = 1 } ---@class svr_config @@ -134,7 +145,9 @@ local fields = { { "AuthKey", "Facility Auth Key" , ""}, { "LogMode", "Log Mode", log.MODE.APPEND }, { "LogPath", "Log Path", "/log.txt" }, - { "LogDebug","Log Debug Messages", false } + { "LogDebug","Log Debug Messages", false }, + { "FrontPanelTheme", "Front Panel Theme", 1 }, + { "ColorMode", "Color Mode", 1 } } -- load data from the settings file @@ -164,11 +177,12 @@ local function config_view(display) local svr_cfg = Div{parent=root_pane_div,x=1,y=1} local net_cfg = Div{parent=root_pane_div,x=1,y=1} local log_cfg = Div{parent=root_pane_div,x=1,y=1} + local clr_cfg = Div{parent=root_pane_div,x=1,y=1} local summary = Div{parent=root_pane_div,x=1,y=1} local changelog = Div{parent=root_pane_div,x=1,y=1} local import_err = Div{parent=root_pane_div,x=1,y=1} - local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,svr_cfg,net_cfg,log_cfg,summary,changelog,import_err}} + local main_pane = MultiPane{parent=root_pane_div,x=1,y=1,panes={main_page,svr_cfg,net_cfg,log_cfg,clr_cfg,summary,changelog,import_err}} -- Main Page @@ -185,7 +199,7 @@ local function config_view(display) tool_ctl.viewing_config = true tool_ctl.gen_summary(settings_cfg) tool_ctl.settings_apply.hide(true) - main_pane.set_value(5) + main_pane.set_value(6) end if fs.exists("/supervisor/config.lua") then @@ -196,10 +210,21 @@ local function config_view(display) PushButton{parent=main_page,x=2,y=y_start,min_width=18,text="Configure System",callback=function()main_pane.set_value(2)end,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg} tool_ctl.view_cfg = PushButton{parent=main_page,x=2,y=y_start+2,min_width=20,text="View Configuration",callback=view_config,fg_bg=cpair(colors.black,colors.blue),active_fg_bg=btn_act_fg_bg,dis_fg_bg=cpair(colors.lightGray,colors.white)} - if not tool_ctl.has_config then tool_ctl.view_cfg.disable() end + local function jump_color() + tool_ctl.jumped_to_color = true + tool_ctl.color_next.hide() + tool_ctl.color_apply.show(true) + main_pane.set_value(5) + end PushButton{parent=main_page,x=2,y=17,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=btn_act_fg_bg} - PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(6)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + tool_ctl.color_cfg = PushButton{parent=main_page,x=23,y=17,min_width=15,text="Color Options",callback=jump_color,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=main_page,x=39,y=17,min_width=12,text="Change Log",callback=function()main_pane.set_value(7)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + if not tool_ctl.has_config then + tool_ctl.view_cfg.disable() + tool_ctl.color_cfg.disable() + end --#region Facility @@ -721,10 +746,8 @@ local function config_view(display) tmp_cfg.LogMode = mode.get_value() - 1 tmp_cfg.LogPath = path.get_value() tmp_cfg.LogDebug = en_dbg.get_value() - tool_ctl.gen_summary(tmp_cfg) - tool_ctl.viewing_config = false - tool_ctl.importing_legacy = false - tool_ctl.settings_apply.show() + tool_ctl.color_apply.hide(true) + tool_ctl.color_next.show() main_pane.set_value(5) else path_err.show() end end @@ -734,6 +757,110 @@ local function config_view(display) --#endregion + --#region Color Options + + local clr_c_1 = Div{parent=clr_cfg,x=2,y=4,width=49} + local clr_c_2 = Div{parent=clr_cfg,x=2,y=4,width=49} + local clr_c_3 = Div{parent=clr_cfg,x=2,y=4,width=49} + local clr_c_4 = Div{parent=clr_cfg,x=2,y=4,width=49} + + local clr_pane = MultiPane{parent=clr_cfg,x=1,y=4,panes={clr_c_1,clr_c_2,clr_c_3,clr_c_4}} + + TextBox{parent=clr_cfg,x=1,y=2,height=1,text=" Color Configuration",fg_bg=cpair(colors.black,colors.magenta)} + + TextBox{parent=clr_c_1,x=1,y=1,height=2,text="Here you can select the color theme for the front panel."} + TextBox{parent=clr_c_1,x=1,y=4,height=2,text="Click 'Accessibility' below to access color blind assistive options.",fg_bg=g_lg_fg_bg} + + TextBox{parent=clr_c_1,x=1,y=7,height=1,text="Front Panel Theme"} + local fp_theme = RadioButton{parent=clr_c_1,x=1,y=8,default=ini_cfg.FrontPanelTheme,options={"Sandstone","Basalt"},callback=function()end,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.magenta} + + TextBox{parent=clr_c_2,x=1,y=1,height=6,text="By default, this project uses green/red heavily to distinguish ok and not, with some indicators also using multiple colors. By selecting a color blindness below, blues will be used instead of greens on indicators and multi-color indicators will be split up as space permits."} + + local function recolor(value) + if value == 1 then + for i = 1, #style.colors do term.setPaletteColor(style.colors[i].c, style.colors[i].hex) end + elseif value == 2 then + term.setPaletteColor(colors.green, 0x1081ff) + term.setPaletteColor(colors.yellow, 0xf5e633) + term.setPaletteColor(colors.red, 0xff521a) + elseif value == 3 then + term.setPaletteColor(colors.green, 0x1081ff) + term.setPaletteColor(colors.yellow, 0xf7c311) + term.setPaletteColor(colors.red, 0xfb5615) + elseif value == 4 then + term.setPaletteColor(colors.green, 0x00ecff) + term.setPaletteColor(colors.yellow, 0xffbc00) + term.setPaletteColor(colors.red, 0xff0000) + end + end + + local c_mode = RadioButton{parent=clr_c_2,x=1,y=8,default=ini_cfg.ColorMode,options={"None","Protanopia","Deuteranopia","Tritanopia"},callback=recolor,radio_colors=cpair(colors.lightGray,colors.black),select_color=colors.magenta} + + local _ = IndLight{parent=clr_c_2,x=20,y=8,label="Good",colors=cpair(colors.black,colors.green),value=true} + _ = IndLight{parent=clr_c_2,x=20,y=9,label="Warning",colors=cpair(colors.black,colors.yellow),value=true} + _ = IndLight{parent=clr_c_2,x=20,y=10,label="Bad",colors=cpair(colors.black,colors.red),value=true} + + TextBox{parent=clr_c_2,x=20,y=12,height=6,text="Exact color varies by theme.",fg_bg=g_lg_fg_bg} + + PushButton{parent=clr_c_2,x=44,y=14,min_width=6,text="Done",callback=function()clr_pane.set_value(1)end,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + local function back_from_colors() + main_pane.set_value(util.trinary(tool_ctl.jumped_to_color, 1, 4)) + tool_ctl.jumped_to_color = false + recolor(1) + end + + local function show_access() + clr_pane.set_value(2) + recolor(c_mode.get_value()) + end + + local function submit_colors() + tmp_cfg.FrontPanelTheme = fp_theme.get_value() + tmp_cfg.ColorMode = c_mode.get_value() + + if tool_ctl.jumped_to_color then + settings.set("FrontPanelTheme", tmp_cfg.FrontPanelTheme) + settings.set("ColorMode", tmp_cfg.ColorMode) + + if settings.save("/supervisor.settings") then + load_settings(settings_cfg, true) + load_settings(ini_cfg) + clr_pane.set_value(3) + else + clr_pane.set_value(4) + end + else + tool_ctl.gen_summary(tmp_cfg) + tool_ctl.viewing_config = false + tool_ctl.importing_legacy = false + tool_ctl.settings_apply.show() + main_pane.set_value(6) + end + end + + PushButton{parent=clr_c_1,x=1,y=14,text="\x1b Back",callback=back_from_colors,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + PushButton{parent=clr_c_1,x=8,y=14,min_width=15,text="Accessibility",callback=show_access,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + tool_ctl.color_next = PushButton{parent=clr_c_1,x=44,y=14,text="Next \x1a",callback=submit_colors,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + tool_ctl.color_apply = PushButton{parent=clr_c_1,x=43,y=14,min_width=7,text="Apply",callback=submit_colors,fg_bg=cpair(colors.black,colors.green),active_fg_bg=btn_act_fg_bg} + + tool_ctl.color_apply.hide() + + local function c_go_home() + main_pane.set_value(1) + clr_pane.set_value(1) + end + + TextBox{parent=clr_c_3,x=1,y=1,height=1,text="Settings saved!"} + PushButton{parent=clr_c_3,x=1,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} + PushButton{parent=clr_c_3,x=44,y=14,min_width=6,text="Home",callback=c_go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + TextBox{parent=clr_c_4,x=1,y=1,height=5,text="Failed to save the settings file.\n\nThere may not be enough space for the modification or server file permissions may be denying writes."} + PushButton{parent=clr_c_4,x=1,y=14,min_width=6,text="Exit",callback=exit,fg_bg=cpair(colors.black,colors.red),active_fg_bg=cpair(colors.white,colors.gray)} + PushButton{parent=clr_c_4,x=44,y=14,min_width=6,text="Home",callback=c_go_home,fg_bg=nav_fg_bg,active_fg_bg=btn_act_fg_bg} + + --#endregion + --#region Summary and Saving local sum_c_1 = Div{parent=summary,x=2,y=4,width=49} @@ -754,7 +881,7 @@ local function config_view(display) tool_ctl.importing_legacy = false tool_ctl.settings_apply.show() else - main_pane.set_value(4) + main_pane.set_value(5) end end @@ -787,6 +914,8 @@ local function config_view(display) try_set(mode, ini_cfg.LogMode) try_set(path, ini_cfg.LogPath) try_set(en_dbg, ini_cfg.LogDebug) + try_set(fp_theme, ini_cfg.FrontPanelTheme) + try_set(c_mode, ini_cfg.ColorMode) for i = 1, #ini_cfg.CoolingConfig do local cfg, elems = ini_cfg.CoolingConfig[i], tool_ctl.cooling_elems[i] @@ -824,6 +953,7 @@ local function config_view(display) main_pane.set_value(1) svr_pane.set_value(1) net_pane.set_value(1) + clr_pane.set_value(1) sum_pane.set_value(1) end @@ -887,7 +1017,7 @@ local function config_view(display) if config.REACTOR_COOLING == nil or tmp_cfg.UnitCount ~= #config.REACTOR_COOLING then import_err_msg.set_value("Cooling configuration table length must match the number of units.") - main_pane.set_value(7) + main_pane.set_value(8) return end @@ -896,7 +1026,7 @@ local function config_view(display) if type(cfg) ~= "table" then import_err_msg.set_value("Cooling configuration for unit " .. i .. " must be a table.") - main_pane.set_value(7) + main_pane.set_value(8) return end @@ -907,14 +1037,14 @@ local function config_view(display) if not (util.is_int(tmp_cfg.FacilityTankMode) and tmp_cfg.FacilityTankMode >= 0 and tmp_cfg.FacilityTankMode <= 8) then import_err_msg.set_value("Invalid tank mode present in config. FAC_TANK_MODE must be a number 0 through 8.") - main_pane.set_value(7) + main_pane.set_value(8) return end if config.FAC_TANK_MODE > 0 then if config.FAC_TANK_DEFS == nil or tmp_cfg.UnitCount ~= #config.FAC_TANK_DEFS then import_err_msg.set_value("Facility tank definitions table length must match the number of units when using facility tanks.") - main_pane.set_value(7) + main_pane.set_value(8) return end @@ -945,7 +1075,7 @@ local function config_view(display) tool_ctl.gen_summary(tmp_cfg) sum_pane.set_value(1) - main_pane.set_value(5) + main_pane.set_value(6) tool_ctl.importing_legacy = true end @@ -976,6 +1106,10 @@ local function config_view(display) if f[1] == "AuthKey" then val = string.rep("*", string.len(val)) elseif f[1] == "LogMode" then val = util.trinary(raw == log.MODE.APPEND, "append", "replace") + elseif f[1] == "FrontPanelTheme" then + if raw == 1 then val = "Sandstone" elseif raw == 2 then val = "Basalt" end + elseif f[1] == "ColorMode" then + if raw == 1 then val = "Standard" elseif raw == 2 then val = "Protanopia" elseif raw == 3 then val = "Deuteranopia" elseif raw == 4 then val = "Tritanopia" end elseif f[1] == "CoolingConfig" and type(cfg.CoolingConfig) == "table" then val = "" diff --git a/supervisor/panel/components/pdg_entry.lua b/supervisor/panel/components/pdg_entry.lua index 7156285..740bb37 100644 --- a/supervisor/panel/components/pdg_entry.lua +++ b/supervisor/panel/components/pdg_entry.lua @@ -17,18 +17,17 @@ local ALIGN = core.ALIGN local cpair = core.cpair -local s_hi_box = style.theme.highlight_box -local s_hi_bright = style.theme.highlight_box_bright - local label_fg = style.fp.label_fg -- create a pocket diagnostics list entry ---@param parent graphics_element parent ---@param id integer PDG session ID local function init(parent, id) + local s_hi_box = style.theme.highlight_box + -- root div local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true} - local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=s_hi_bright} + local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=style.theme.highlight_box_bright} local ps_prefix = "pdg_" .. id .. "_" diff --git a/supervisor/panel/components/rtu_entry.lua b/supervisor/panel/components/rtu_entry.lua index 518dfe9..e09a048 100644 --- a/supervisor/panel/components/rtu_entry.lua +++ b/supervisor/panel/components/rtu_entry.lua @@ -17,18 +17,17 @@ local ALIGN = core.ALIGN local cpair = core.cpair -local s_hi_box = style.theme.highlight_box -local s_hi_bright = style.theme.highlight_box_bright - local label_fg = style.fp.label_fg -- create an RTU list entry ---@param parent graphics_element parent ---@param id integer RTU session ID local function init(parent, id) + local s_hi_box = style.theme.highlight_box + -- root div local root = Div{parent=parent,x=2,y=2,height=4,width=parent.get_width()-2,hidden=true} - local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=s_hi_bright} + local entry = Div{parent=root,x=2,y=1,height=3,fg_bg=style.theme.highlight_box_bright} local ps_prefix = "rtu_" .. id .. "_" diff --git a/supervisor/panel/front_panel.lua b/supervisor/panel/front_panel.lua index fccb5b0..add7fcf 100644 --- a/supervisor/panel/front_panel.lua +++ b/supervisor/panel/front_panel.lua @@ -29,17 +29,17 @@ local ALIGN = core.ALIGN local cpair = core.cpair -local s_hi_box = style.theme.highlight_box -local s_hi_bright = style.theme.highlight_box_bright - -local label_fg = style.fp.label_fg -local label_d_fg = style.fp.label_d_fg - local ind_grn = style.ind_grn -- create new front panel view ---@param panel graphics_element main displaybox local function init(panel) + local s_hi_box = style.theme.highlight_box + local s_hi_bright = style.theme.highlight_box_bright + + local label_fg = style.fp.label_fg + local label_d_fg = style.fp.label_d_fg + TextBox{parent=panel,y=1,text="SCADA SUPERVISOR",alignment=ALIGN.CENTER,height=1,fg_bg=style.theme.header} local page_div = Div{parent=panel,x=1,y=3} diff --git a/supervisor/panel/style.lua b/supervisor/panel/style.lua index 7237bfb..e3f1138 100644 --- a/supervisor/panel/style.lua +++ b/supervisor/panel/style.lua @@ -15,4 +15,16 @@ style.fp = themes.get_fp_style(style.theme) style.ind_grn = cpair(colors.green, colors.green_off) +-- set theme per configuration +---@param fp integer fp theme ID (1 = sandstone, 2 = basalt) +function style.set_theme(fp) + if fp == 1 then + style.theme = themes.sandstone + elseif fp == 2 then + style.theme = themes.basalt + end + + style.fp = themes.get_fp_style(style.theme) +end + return style diff --git a/supervisor/renderer.lua b/supervisor/renderer.lua index 42fe771..8f9389f 100644 --- a/supervisor/renderer.lua +++ b/supervisor/renderer.lua @@ -19,11 +19,15 @@ local ui = { } -- try to start the UI +---@param theme integer front panel theme ID (1 = sandstone, 2 = basalt) ---@return boolean success, any error_msg -function renderer.try_start_ui() +function renderer.try_start_ui(theme) local status, msg = true, nil if ui.display == nil then + -- set theme + style.set_theme(theme) + -- reset terminal term.setTextColor(colors.white) term.setBackgroundColor(colors.black) diff --git a/supervisor/startup.lua b/supervisor/startup.lua index a35081c..d9c2229 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -118,7 +118,7 @@ local function main() databus.tx_hw_modem(true) -- start UI - local fp_ok, message = renderer.try_start_ui() + local fp_ok, message = renderer.try_start_ui(config.FrontPanelTheme) if not fp_ok then println_ts(util.c("UI error: ", message)) diff --git a/supervisor/supervisor.lua b/supervisor/supervisor.lua index 27bf22c..43536c6 100644 --- a/supervisor/supervisor.lua +++ b/supervisor/supervisor.lua @@ -43,6 +43,9 @@ function supervisor.load_config() config.LogPath = settings.get("LogPath") config.LogDebug = settings.get("LogDebug") + config.FrontPanelTheme = settings.get("FrontPanelTheme") + config.ColorMode = settings.get("ColorMode") + local cfv = util.new_validator() cfv.assert_type_int(config.UnitCount) @@ -81,6 +84,11 @@ function supervisor.load_config() cfv.assert_type_str(config.LogPath) cfv.assert_type_bool(config.LogDebug) + cfv.assert_type_int(config.FrontPanelTheme) + cfv.assert_range(config.FrontPanelTheme, 1, 2) + cfv.assert_type_int(config.ColorMode) + cfv.assert_range(config.ColorMode, 1, 4) + return cfv.valid() end