diff --git a/graphics/core.lua b/graphics/core.lua index 3d23dfc..adb9806 100644 --- a/graphics/core.lua +++ b/graphics/core.lua @@ -30,6 +30,20 @@ graphics.TEXT_ALIGN = { RIGHT = 3 } +---@class graphics_border +---@field width integer +---@field color color + +---@param width integer +---@param color color +---@return graphics_border +function graphics.border(width, color) + return { + width = width, + color = color + } +end + ---@class graphics_frame ---@field x integer ---@field y integer diff --git a/graphics/element.lua b/graphics/element.lua index 7078bc9..97b88f7 100644 --- a/graphics/element.lua +++ b/graphics/element.lua @@ -23,6 +23,7 @@ function element.new(args) local protected = { window = nil, ---@type table + fg_bg = core.graphics.cpair(colors.white, colors.black), frame = core.graphics.gframe(1, 1, 1, 1) } @@ -56,6 +57,7 @@ function element.new(args) protected.window.setBackgroundColor(args.fg_bg.bkg) protected.window.setTextColor(args.fg_bg.fgd) protected.window.clear() + protected.fg_bg = args.fg_bg end -- record position diff --git a/graphics/elements/rectangle.lua b/graphics/elements/rectangle.lua new file mode 100644 index 0000000..90c0a4d --- /dev/null +++ b/graphics/elements/rectangle.lua @@ -0,0 +1,64 @@ +-- Rectangle Graphics Element + +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 rectangle 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.setCursorPos(1, 1) + + local border_width = args.border.width + local border_blit = colors.toBlit(args.border.color) + local spaces = "" + local blit_fg = "" + local blit_bg_top_bot = "" + local blit_bg_sides = "" + + -- form the basic and top/bottom blit strings + for _ = 1, e.frame.w do + spaces = spaces .. " " + blit_fg = blit_fg .. e.fg_bg.blit_fgd + blit_bg_top_bot = blit_bg_top_bot .. border_blit + end + + -- 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.setCursorPos(y, 1) + if y <= border_width or y > (e.frame.h - border_width) then + e.blit(spaces, blit_fg, blit_bg_top_bot) + else + e.blit(spaces, blit_fg, blit_bg_sides) + end + end + end + + return e.get() +end + +return rectangle