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
|
||||
Reference in New Issue
Block a user