cc-mek-scada/graphics/elements/rectangle.lua

102 lines
4.0 KiB
Lua

-- Rectangle Graphics Element
local util = require("scada-common.util")
local element = require("graphics.element")
---@class rectangle_args
---@field border? graphics_border
---@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 rectangle
---@param args rectangle_args
local function rectangle(args)
-- create new graphics element base object
local e = element.new(args)
-- draw bordered box if requested
-- element constructor will have drawn basic colored rectangle regardless
if args.border ~= nil then
e.window.setCursorPos(1, 1)
local border_width = args.border.width
local border_blit = colors.toBlit(args.border.color)
local width_x2 = border_width * 2
local inner_width = e.frame.w - width_x2
-- check dimensions
assert(width_x2 <= e.frame.w, "graphics.elements.rectangle: border too thick for width")
assert(width_x2 <= e.frame.h, "graphics.elements.rectangle: border too thick for height")
-- form the basic line strings and top/bottom blit strings
local spaces = util.spaces(e.frame.w)
local blit_fg = util.strrep(e.fg_bg.blit_fgd, e.frame.w)
local blit_bg_sides = ""
local blit_bg_top_bot = util.strrep(border_blit, e.frame.w)
-- partial bars
local p_a = util.spaces(border_width) .. util.strrep("\x8f", inner_width) .. util.spaces(border_width)
local p_b = util.spaces(border_width) .. util.strrep("\x83", inner_width) .. util.spaces(border_width)
local p_inv_fg = util.strrep(border_blit, border_width) .. util.strrep(e.fg_bg.blit_bkg, inner_width) ..
util.strrep(border_blit, border_width)
local p_inv_bg = util.strrep(e.fg_bg.blit_bkg, border_width) .. util.strrep(border_blit, inner_width) ..
util.strrep(e.fg_bg.blit_bkg, border_width)
-- 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
if x <= border_width or x > (e.frame.w - border_width) then
blit_bg_sides = blit_bg_sides .. border_blit
else
blit_bg_sides = blit_bg_sides .. e.fg_bg.blit_bkg
end
end
-- draw rectangle with borders
for y = 1, e.frame.h do
e.window.setCursorPos(1, y)
if y <= border_width then
-- partial pixel fill
if args.border.even and y == border_width then
if width_x2 % 3 == 1 then
e.window.blit(p_b, p_inv_bg, p_inv_fg)
elseif width_x2 % 3 == 2 then
e.window.blit(p_a, p_inv_bg, p_inv_fg)
else
-- skip line
e.window.blit(spaces, blit_fg, blit_bg_sides)
end
else
e.window.blit(spaces, blit_fg, blit_bg_top_bot)
end
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 width_x2 % 3 == 1 then
e.window.blit(p_a, p_inv_fg, blit_bg_top_bot)
elseif width_x2 % 3 == 2 then
e.window.blit(p_b, p_inv_fg, blit_bg_top_bot)
else
-- skip line
e.window.blit(spaces, blit_fg, blit_bg_sides)
end
else
e.window.blit(spaces, blit_fg, blit_bg_top_bot)
end
else
e.window.blit(spaces, blit_fg, blit_bg_sides)
end
end
end
return e.get()
end
return rectangle