2022-06-08 16:27:28 +00:00
|
|
|
-- Rectangle Graphics Element
|
|
|
|
|
2022-06-08 17:08:48 +00:00
|
|
|
local util = require("scada-common.util")
|
2022-06-08 16:27:28 +00:00
|
|
|
|
2022-06-08 17:18:14 +00:00
|
|
|
local element = require("graphics.element")
|
|
|
|
|
2022-06-08 16:27:28 +00:00
|
|
|
---@class rectangle_args
|
|
|
|
---@field border? graphics_border
|
2022-12-11 04:56:07 +00:00
|
|
|
---@field thin? boolean true to use extra thin even borders
|
2023-04-09 01:35:16 +00:00
|
|
|
---@field even_inner? boolean true to make the inner area of a border even
|
2022-06-08 16:27:28 +00:00
|
|
|
---@field parent graphics_element
|
2022-07-28 14:09:34 +00:00
|
|
|
---@field id? string element id
|
2022-06-08 16:27:28 +00:00
|
|
|
---@field x? integer 1 if omitted
|
2023-07-10 03:42:44 +00:00
|
|
|
---@field y? integer auto incremented if omitted
|
2022-06-08 16:27:28 +00:00
|
|
|
---@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
|
2022-06-11 21:06:32 +00:00
|
|
|
---@field fg_bg? cpair foreground/background colors
|
2023-05-25 21:40:16 +00:00
|
|
|
---@field hidden? boolean true to hide on initial draw
|
2022-06-08 16:27:28 +00:00
|
|
|
|
|
|
|
-- new rectangle
|
|
|
|
---@param args rectangle_args
|
2022-07-28 14:09:34 +00:00
|
|
|
---@return graphics_element element, element_id id
|
2022-06-08 16:27:28 +00:00
|
|
|
local function rectangle(args)
|
2023-09-30 15:46:47 +00:00
|
|
|
element.assert(args.border ~= nil or args.thin ~= true, "thin requires border to be provided")
|
2022-12-11 04:56:07 +00:00
|
|
|
|
|
|
|
-- if thin, then width will always need to be 1
|
|
|
|
if args.thin == true then
|
|
|
|
args.border.width = 1
|
|
|
|
args.border.even = true
|
|
|
|
end
|
|
|
|
|
2022-06-19 15:20:09 +00:00
|
|
|
-- offset children
|
2023-05-31 00:43:33 +00:00
|
|
|
local offset_x = 0
|
|
|
|
local offset_y = 0
|
2022-06-19 15:20:09 +00:00
|
|
|
if args.border ~= nil then
|
2023-05-31 00:43:33 +00:00
|
|
|
offset_x = args.border.width
|
|
|
|
offset_y = args.border.width
|
2022-06-19 15:20:09 +00:00
|
|
|
|
|
|
|
-- slightly different y offset if the border is set to even
|
|
|
|
if args.border.even then
|
|
|
|
local width_x2 = (2 * args.border.width)
|
2023-05-31 00:43:33 +00:00
|
|
|
offset_y = math.floor(width_x2 / 3) + util.trinary(width_x2 % 3 > 0, 1, 0)
|
2022-06-19 15:20:09 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-06-08 17:08:48 +00:00
|
|
|
-- create new graphics element base object
|
2023-06-07 22:38:00 +00:00
|
|
|
local e = element.new(args, offset_x, offset_y)
|
2022-06-08 16:27:28 +00:00
|
|
|
|
2023-05-31 00:43:33 +00:00
|
|
|
-- create content window for child elements
|
|
|
|
e.content_window = window.create(e.window, 1 + offset_x, 1 + offset_y, e.frame.w - (2 * offset_x), e.frame.h - (2 * offset_y))
|
|
|
|
e.content_window.setBackgroundColor(e.fg_bg.bkg)
|
|
|
|
e.content_window.setTextColor(e.fg_bg.fgd)
|
|
|
|
e.content_window.clear()
|
|
|
|
|
2022-06-08 16:27:28 +00:00
|
|
|
-- draw bordered box if requested
|
|
|
|
-- element constructor will have drawn basic colored rectangle regardless
|
|
|
|
if args.border ~= nil then
|
2023-08-31 01:11:57 +00:00
|
|
|
e.w_set_cur(1, 1)
|
2022-06-08 16:27:28 +00:00
|
|
|
|
2023-05-31 00:43:33 +00:00
|
|
|
local border_width = offset_x
|
|
|
|
local border_height = offset_y
|
2022-06-08 16:27:28 +00:00
|
|
|
local border_blit = colors.toBlit(args.border.color)
|
2022-06-18 05:33:45 +00:00
|
|
|
local width_x2 = border_width * 2
|
|
|
|
local inner_width = e.frame.w - width_x2
|
2022-06-08 16:27:28 +00:00
|
|
|
|
2022-06-08 17:18:14 +00:00
|
|
|
-- check dimensions
|
2023-09-30 15:46:47 +00:00
|
|
|
element.assert(width_x2 <= e.frame.w, "border too thick for width")
|
|
|
|
element.assert(width_x2 <= e.frame.h, "border too thick for height")
|
2022-06-18 05:33:45 +00:00
|
|
|
|
|
|
|
-- form the basic line strings and top/bottom blit strings
|
|
|
|
local spaces = util.spaces(e.frame.w)
|
2023-08-30 23:30:46 +00:00
|
|
|
local blit_fg = string.rep(e.fg_bg.blit_fgd, e.frame.w)
|
2022-12-11 04:56:07 +00:00
|
|
|
local blit_fg_sides = blit_fg
|
2022-06-18 05:33:45 +00:00
|
|
|
local blit_bg_sides = ""
|
2023-08-30 23:30:46 +00:00
|
|
|
local blit_bg_top_bot = string.rep(border_blit, e.frame.w)
|
2022-06-08 17:08:48 +00:00
|
|
|
|
2022-06-18 05:33:45 +00:00
|
|
|
-- partial bars
|
2023-04-09 01:35:16 +00:00
|
|
|
local p_a, p_b, p_s
|
2022-12-11 04:56:07 +00:00
|
|
|
if args.thin == true then
|
2023-04-09 01:35:16 +00:00
|
|
|
if args.even_inner == true then
|
2023-08-30 23:30:46 +00:00
|
|
|
p_a = "\x9c" .. string.rep("\x8c", inner_width) .. "\x93"
|
|
|
|
p_b = "\x8d" .. string.rep("\x8c", inner_width) .. "\x8e"
|
2023-04-09 01:35:16 +00:00
|
|
|
else
|
2023-08-30 23:30:46 +00:00
|
|
|
p_a = "\x97" .. string.rep("\x83", inner_width) .. "\x94"
|
|
|
|
p_b = "\x8a" .. string.rep("\x8f", inner_width) .. "\x85"
|
2023-04-09 01:35:16 +00:00
|
|
|
end
|
|
|
|
|
2022-12-11 04:56:07 +00:00
|
|
|
p_s = "\x95" .. util.spaces(inner_width) .. "\x95"
|
2023-04-09 01:35:16 +00:00
|
|
|
else
|
|
|
|
if args.even_inner == true then
|
2023-08-30 23:30:46 +00:00
|
|
|
p_a = string.rep("\x83", inner_width + width_x2)
|
|
|
|
p_b = string.rep("\x8f", inner_width + width_x2)
|
2023-04-09 01:35:16 +00:00
|
|
|
else
|
2023-08-30 23:30:46 +00:00
|
|
|
p_a = util.spaces(border_width) .. string.rep("\x8f", inner_width) .. util.spaces(border_width)
|
|
|
|
p_b = util.spaces(border_width) .. string.rep("\x83", inner_width) .. util.spaces(border_width)
|
2023-04-09 01:35:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
p_s = spaces
|
2022-12-11 04:56:07 +00:00
|
|
|
end
|
|
|
|
|
2023-08-30 23:30:46 +00:00
|
|
|
local p_inv_fg = string.rep(border_blit, border_width) .. string.rep(e.fg_bg.blit_bkg, inner_width) ..
|
|
|
|
string.rep(border_blit, border_width)
|
|
|
|
local p_inv_bg = string.rep(e.fg_bg.blit_bkg, border_width) .. string.rep(border_blit, inner_width) ..
|
|
|
|
string.rep(e.fg_bg.blit_bkg, border_width)
|
2022-06-08 16:27:28 +00:00
|
|
|
|
2022-12-11 04:56:07 +00:00
|
|
|
if args.thin == true then
|
2023-08-30 23:30:46 +00:00
|
|
|
p_inv_fg = e.fg_bg.blit_bkg .. string.rep(e.fg_bg.blit_bkg, inner_width) .. string.rep(border_blit, border_width)
|
|
|
|
p_inv_bg = border_blit .. string.rep(border_blit, inner_width) .. string.rep(e.fg_bg.blit_bkg, border_width)
|
2022-12-11 04:56:07 +00:00
|
|
|
|
2023-08-30 23:30:46 +00:00
|
|
|
blit_fg_sides = border_blit .. string.rep(e.fg_bg.blit_bkg, inner_width) .. e.fg_bg.blit_bkg
|
2022-12-11 04:56:07 +00:00
|
|
|
end
|
|
|
|
|
2022-06-08 16:27:28 +00:00
|
|
|
-- form the body blit strings (sides are border, inside is normal)
|
|
|
|
for x = 1, e.frame.w do
|
|
|
|
-- edges get border color, center gets normal
|
2022-06-18 05:33:45 +00:00
|
|
|
if x <= border_width or x > (e.frame.w - border_width) then
|
2022-12-11 04:56:07 +00:00
|
|
|
if args.thin and x == 1 then
|
|
|
|
blit_bg_sides = blit_bg_sides .. e.fg_bg.blit_bkg
|
|
|
|
else
|
|
|
|
blit_bg_sides = blit_bg_sides .. border_blit
|
|
|
|
end
|
2022-06-08 16:27:28 +00:00
|
|
|
else
|
|
|
|
blit_bg_sides = blit_bg_sides .. e.fg_bg.blit_bkg
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- draw rectangle with borders
|
2023-09-29 23:34:10 +00:00
|
|
|
function e.redraw()
|
|
|
|
for y = 1, e.frame.h do
|
|
|
|
e.w_set_cur(1, y)
|
|
|
|
-- top border
|
|
|
|
if y <= border_height then
|
|
|
|
-- partial pixel fill
|
|
|
|
if args.border.even and y == border_height then
|
|
|
|
if args.thin == true then
|
|
|
|
e.w_blit(p_a, p_inv_bg, p_inv_fg)
|
2022-12-11 04:56:07 +00:00
|
|
|
else
|
2023-09-29 23:34:10 +00:00
|
|
|
local _fg = util.trinary(args.even_inner == true, string.rep(e.fg_bg.blit_bkg, e.frame.w), p_inv_bg)
|
|
|
|
local _bg = util.trinary(args.even_inner == true, blit_bg_top_bot, p_inv_fg)
|
|
|
|
|
|
|
|
if width_x2 % 3 == 1 then
|
|
|
|
e.w_blit(p_b, _fg, _bg)
|
|
|
|
elseif width_x2 % 3 == 2 then
|
|
|
|
e.w_blit(p_a, _fg, _bg)
|
|
|
|
else
|
|
|
|
-- skip line
|
|
|
|
e.w_blit(spaces, blit_fg, blit_bg_sides)
|
|
|
|
end
|
2022-12-11 04:56:07 +00:00
|
|
|
end
|
2023-09-29 23:34:10 +00:00
|
|
|
else
|
|
|
|
e.w_blit(spaces, blit_fg, blit_bg_top_bot)
|
2022-06-18 05:33:45 +00:00
|
|
|
end
|
2023-09-29 23:34:10 +00:00
|
|
|
-- bottom border
|
|
|
|
elseif y > (e.frame.h - border_width) then
|
|
|
|
-- partial pixel fill
|
|
|
|
if args.border.even and y == ((e.frame.h - border_width) + 1) then
|
|
|
|
if args.thin == true then
|
|
|
|
if args.even_inner == true then
|
|
|
|
e.w_blit(p_b, blit_bg_top_bot, string.rep(e.fg_bg.blit_bkg, e.frame.w))
|
|
|
|
else
|
|
|
|
e.w_blit(p_b, string.rep(e.fg_bg.blit_bkg, e.frame.w), blit_bg_top_bot)
|
|
|
|
end
|
2023-04-09 01:35:16 +00:00
|
|
|
else
|
2023-09-29 23:34:10 +00:00
|
|
|
local _fg = util.trinary(args.even_inner == true, blit_bg_top_bot, p_inv_fg)
|
|
|
|
local _bg = util.trinary(args.even_inner == true, string.rep(e.fg_bg.blit_bkg, e.frame.w), blit_bg_top_bot)
|
|
|
|
|
|
|
|
if width_x2 % 3 == 1 then
|
|
|
|
e.w_blit(p_a, _fg, _bg)
|
|
|
|
elseif width_x2 % 3 == 2 then
|
|
|
|
e.w_blit(p_b, _fg, _bg)
|
|
|
|
else
|
|
|
|
-- skip line
|
|
|
|
e.w_blit(spaces, blit_fg, blit_bg_sides)
|
|
|
|
end
|
2023-04-09 01:35:16 +00:00
|
|
|
end
|
2022-06-18 05:33:45 +00:00
|
|
|
else
|
2023-09-29 23:34:10 +00:00
|
|
|
e.w_blit(spaces, blit_fg, blit_bg_top_bot)
|
2022-06-18 05:33:45 +00:00
|
|
|
end
|
|
|
|
else
|
2023-09-29 23:34:10 +00:00
|
|
|
if args.thin == true then
|
|
|
|
e.w_blit(p_s, blit_fg_sides, blit_bg_sides)
|
|
|
|
else
|
|
|
|
e.w_blit(p_s, blit_fg, blit_bg_sides)
|
|
|
|
end
|
2022-12-11 04:56:07 +00:00
|
|
|
end
|
2022-06-08 16:27:28 +00:00
|
|
|
end
|
|
|
|
end
|
2023-09-29 23:34:10 +00:00
|
|
|
|
|
|
|
-- initial draw of border
|
|
|
|
e.redraw()
|
2022-06-08 16:27:28 +00:00
|
|
|
end
|
|
|
|
|
2023-05-30 23:51:10 +00:00
|
|
|
return e.complete()
|
2022-06-08 16:27:28 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
return rectangle
|