Small docs update

This commit is contained in:
Robert Jelic
2025-02-24 20:51:58 +01:00
parent 1d48b8ea32
commit a51b91722d
22 changed files with 442 additions and 94 deletions

3
.gitignore vendored
View File

@@ -4,4 +4,5 @@ lua-ls-cc-tweaked-main
test.xml
ascii.lua
tests
testWorkflows
testWorkflows
basaltImage.lua

View File

@@ -68,7 +68,7 @@ end
local function createScreen(index)
local screen = main:addFrame(coloring)
:onMouseScroll(function(self, direction)
:onScroll(function(self, direction)
local height = getChildrenHeight(self)
local scrollOffset = self:getOffsetY()
local maxScroll = height - self:getHeight()
@@ -129,7 +129,7 @@ nextButton = main:addButton()
:setText("Next")
:setPosition("{parent.width - 9}", "{parent.height - 1}")
:setIgnoreOffset(true)
:onMouseClick(function() switchScreen(1) end)
:onClick(function() switchScreen(1) end)
backButton = main:addButton()
:setBackground("{self.clicked and colors.black or colors.white}")
@@ -138,7 +138,7 @@ backButton = main:addButton()
:setText("Back")
:setPosition(2, "{parent.height - 1}")
:setIgnoreOffset(true)
:onMouseClick(function() switchScreen(-1) end)
:onClick(function() switchScreen(-1) end)
:setVisible(false)
-- Screen 1: Welcome
@@ -608,7 +608,7 @@ installButton = progressScreen:addButton()
:setText("Install")
:setPosition("{parent.width - 9}", "{parent.height - 3}")
:setSize(9, 1)
:onMouseClick(function(self)
:onClick(function(self)
if(currentlyInstalling)then
return
end
@@ -621,7 +621,7 @@ local closeButton = progressScreen:addButton()
:setText("Close")
:setPosition("{parent.width - 9}", "{parent.height - 1}")
:setSize(9, 1)
:onMouseClick(function(self)
:onClick(function(self)
basalt.stop()
end)

View File

@@ -1,9 +1,8 @@
local PropertySystem = require("propertySystem")
local uuid = require("libraries/utils").uuid
---@configDescription The base class for all UI elements in Basalt
---@configDefault true
---@configDescription The base class for all UI elements in Basalt.
--- The base class for all UI elements in Basalt
--- The base class for all UI elements in Basalt. This class provides basic properties and event handling functionality.
--- @class BaseElement : PropertySystem
local BaseElement = setmetatable({}, PropertySystem)
BaseElement.__index = BaseElement
@@ -34,7 +33,6 @@ BaseElement.defineProperty(BaseElement, "eventCallbacks", {default = {}, type =
function BaseElement.defineEvent(class, eventName, requiredEvent)
-- Events auf Klassenebene speichern, wie bei Properties
if not rawget(class, '_eventConfigs') then
class._eventConfigs = {}
end
@@ -46,17 +44,15 @@ end
function BaseElement.registerEventCallback(class, callbackName, ...)
local methodName = callbackName:match("^on") and callbackName or "on"..callbackName
local events = {...} -- Alle Events als varargs
local mainEvent = events[1] -- Erstes Event ist immer das Haupt-Event
local events = {...}
local mainEvent = events[1]
class[methodName] = function(self, ...)
-- Alle Events aktivieren
for _, sysEvent in ipairs(events) do
if not self._registeredEvents[sysEvent] then
self:listenEvent(sysEvent, true)
end
end
-- Callback für das Haupt-Event registrieren
self:registerCallback(mainEvent, ...)
return self
end
@@ -85,11 +81,10 @@ function BaseElement:init(props, basalt)
self._registeredEvents = {}
local currentClass = getmetatable(self).__index
-- Events Sammeln
local events = {}
currentClass = self
while currentClass do
if type(currentClass) == "table" and currentClass._eventConfigs then
for eventName, config in pairs(currentClass._eventConfigs) do
@@ -237,7 +232,6 @@ end
--- @shortDescription Destroys the element and cleans up all references
--- @usage element:destroy()
function BaseElement:destroy()
-- Remove from parent if exists
if self.parent then
self.parent:removeChild(self)
end

View File

@@ -109,11 +109,24 @@ function BaseFrame:setCursor(x, y, blink, color)
self._render:setCursor(x, y, blink, color)
end
---@private
function BaseFrame:mouse_up(button, x, y)
Container.mouse_up(self, button, x, y)
Container.mouse_release(self, button, x, y)
end
---@private
function BaseFrame:term_resize()
local width, height = self.get("term").getSize()
if(width == self.get("width") and height == self.get("height")) then
return
end
self.set("width", width)
self.set("height", height)
self._render:setSize(width, height)
self._renderUpdate = true
end
--- Renders the Frame
--- @shortDescription Renders the Frame
function BaseFrame:render()
@@ -126,15 +139,4 @@ function BaseFrame:render()
end
end
function BaseFrame:term_resize()
local width, height = self.get("term").getSize()
if(width == self.get("width") and height == self.get("height")) then
return
end
self.set("width", width)
self.set("height", height)
self._render:setSize(width, height)
self._renderUpdate = true
end
return BaseFrame

View File

@@ -1,10 +1,9 @@
local elementManager = require("elementManager")
local VisualElement = elementManager.getElement("VisualElement")
local getCenteredPosition = require("libraries/utils").getCenteredPosition
---@cofnigDescription This is a button. It is a visual element that can be clicked.
---@configDefault true
---@cofnigDescription The Button is a standard button element with click handling and state management.
--- This is the button class. It is a visual element that can be clicked.
--- The Button is a standard button element with click handling and state management.
---@class Button : VisualElement
---@configDescription Standard button element with click handling and state management
local Button = setmetatable({}, VisualElement)

View File

@@ -1,6 +1,7 @@
local VisualElement = require("elements/VisualElement")
---@cofnigDescription This is a checkbox. It is a visual element that can be checked.
--- This is the checkbox class. It is a visual element that can be checked.
--- The Checkbox is a visual element that can be checked.
---@class Checkbox : VisualElement
local Checkbox = setmetatable({}, VisualElement)
Checkbox.__index = Checkbox

View File

@@ -330,6 +330,13 @@ local function convertMousePosition(self, event, ...)
return args
end
--- Calls a event on all children
--- @shortDescription Calls a event on all children
--- @param visibleOnly boolean Whether to only call the event on visible children
--- @param event string The event to call
--- @vararg any The event arguments
--- @return boolean handled Whether the event was handled
--- @return table child? The child that handled the event
function Container:callChildrenEvents(visibleOnly, event, ...)
local children = visibleOnly and self.get("visibleChildrenEvents") or self.get("childrenEvents")
if children[event] then
@@ -392,12 +399,23 @@ function Container:mouse_up(button, x, y)
return false
end
--- Handles mouse release events
--- @shortDescription Handles mouse release events
--- @param button number The button that was clicked
--- @param x number The x position of the click
--- @param y number The y position of the click
function Container:mouse_release(button, x, y)
VisualElement.mouse_release(self, button, x, y)
local args = convertMousePosition(self, "mouse_release", button, x, y)
self:callChildrenEvents(false, "mouse_release", table.unpack(args))
end
--- Handles mouse move events
--- @shortDescription Handles mouse move events
--- @param _ number unknown
--- @param x number The x position of the click
--- @param y number The y position of the click
--- @return boolean handled Whether the event was handled
function Container:mouse_move(_, x, y)
if VisualElement.mouse_move(self, _, x, y) then
local args = convertMousePosition(self, "mouse_move", _, x, y)
@@ -409,6 +427,12 @@ function Container:mouse_move(_, x, y)
return false
end
--- Handles mouse drag events
--- @shortDescription Handles mouse drag events
--- @param button number The button that was clicked
--- @param x number The x position of the click
--- @param y number The y position of the click
--- @return boolean handled Whether the event was handled
function Container:mouse_drag(button, x, y)
if VisualElement.mouse_drag(self, button, x, y) then
local args = convertMousePosition(self, "mouse_drag", button, x, y)
@@ -420,6 +444,12 @@ function Container:mouse_drag(button, x, y)
return false
end
--- Handles mouse scroll events
--- @shortDescription Handles mouse scroll events
--- @param direction number The direction of the scroll
--- @param x number The x position of the click
--- @param y number The y position of the click
--- @return boolean handled Whether the event was handled
function Container:mouse_scroll(direction, x, y)
local args = convertMousePosition(self, "mouse_scroll", direction, x, y)
local success, child = self:callChildrenEvents(true, "mouse_scroll", table.unpack(args))

View File

@@ -7,7 +7,6 @@ local tHex = require("libraries/colorHex")
--- This is the dropdown class. It is a visual element that can show a list of selectable items in a dropdown menu.
---@class Dropdown : List
local Dropdown = setmetatable({}, List)
Dropdown.__index = Dropdown

View File

@@ -1,12 +1,17 @@
local elementManager = require("elementManager")
local Container = elementManager.getElement("Container")
---@configDescription A flexbox container that arranges its children in a flexible layout.
--- This is the Flexbox class. It is a container that arranges its children in a flexible layout.
---@class Flexbox : Container
local Flexbox = setmetatable({}, Container)
Flexbox.__index = Flexbox
---@property flexDirection string "row" The direction of the flexbox layout "row" or "column"
Flexbox.defineProperty(Flexbox, "flexDirection", {default = "row", type = "string"})
---@property flexSpacing number 1 The spacing between flex items
Flexbox.defineProperty(Flexbox, "flexSpacing", {default = 1, type = "number"})
---@property flexJustifyContent string "flex-start" The alignment of flex items along the main axis
Flexbox.defineProperty(Flexbox, "flexJustifyContent", {
default = "flex-start",
type = "string",
@@ -17,6 +22,8 @@ Flexbox.defineProperty(Flexbox, "flexJustifyContent", {
return value
end
})
---@property flexWrap boolean false Whether to wrap flex items onto multiple lines
---@property flexUpdateLayout boolean false Whether to update the layout of the flexbox
Flexbox.defineProperty(Flexbox, "flexWrap", {default = false, type = "boolean"})
Flexbox.defineProperty(Flexbox, "flexUpdateLayout", {default = false, type = "boolean"})
@@ -226,6 +233,7 @@ local function updateLayout(self, direction, spacing, justifyContent, wrap)
end
--- Creates a new Flexbox instance
--- @shortDescription Creates a new Flexbox instance
--- @return Flexbox object The newly created Flexbox instance
--- @usage local element = Flexbox.new("myId", basalt)
function Flexbox.new()
@@ -239,11 +247,21 @@ function Flexbox.new()
return self
end
--- Initializes the Flexbox instance
--- @shortDescription Initializes the Flexbox instance
--- @param props table The properties to initialize the element with
--- @param basalt table The basalt instance
--- @return Flexbox self The initialized instance
function Flexbox:init(props, basalt)
Container.init(self, props, basalt)
self.set("type", "Flexbox")
return self
end
--- Adds a child element to the flexbox
--- @shortDescription Adds a child element to the flexbox
--- @param element Element The child element to add
--- @return Flexbox self The flexbox instance
function Flexbox:addChild(element)
Container.addChild(self, element)
@@ -257,6 +275,10 @@ function Flexbox:addChild(element)
return self
end
--- Removes a child element from the flexbox
--- @shortDescription Removes a child element from the flexbox
--- @param element Element The child element to remove
--- @return Flexbox self The flexbox instance
function Flexbox:removeChild(element)
Container.removeChild(self, element)
@@ -276,7 +298,8 @@ function Flexbox:removeChild(element)
return self
end
--- Adds a new line break to the flexbox.
--- Adds a new line break to the flexbox
--- @shortDescription Adds a new line break to the flexbox.
---@param self Flexbox The element itself
---@return Flexbox
function Flexbox:addLineBreak()
@@ -284,6 +307,9 @@ function Flexbox:addLineBreak()
return self
end
--- Renders the flexbox and its children
--- @shortDescription Renders the flexbox and its children
--- @return Flexbox self The flexbox instance
function Flexbox:render()
if(self.get("flexUpdateLayout"))then
updateLayout(self, self.get("flexDirection"), self.get("flexSpacing"), self.get("flexJustifyContent"), self.get("flexWrap"))

View File

@@ -1,5 +1,6 @@
local elementManager = require("elementManager")
local Container = elementManager.getElement("Container")
---@configDescription A frame element that serves as a grouping container for other elements.
--- This is the frame class. It serves as a grouping container for other elements.
---@class Frame : Container

205
src/elements/Image.lua Normal file
View File

@@ -0,0 +1,205 @@
local elementManager = require("elementManager")
local VisualElement = elementManager.getElement("VisualElement")
local tHex = require("libraries/colorHex")
---@configDescription An element that displays an image in bimg format
---@configDefault false
--- This is the Image element class which can be used to display bimg format images.
--- The bimg format is a universal ComputerCraft image format.
--- See: https://github.com/SkyTheCodeMaster/bimg
---@class Image : VisualElement
local Image = setmetatable({}, VisualElement)
Image.__index = Image
---@property bimg table {} The bimg image data
Image.defineProperty(Image, "bimg", {default = {}, type = "table", canTriggerRender = true})
---@property currentFrame number 1 Current animation frame
Image.defineProperty(Image, "currentFrame", {default = 1, type = "number", canTriggerRender = true})
---@property metadata table {} Image metadata (version, palette, etc)
Image.defineProperty(Image, "metadata", {default = {}, type = "table"})
function Image.new()
local self = setmetatable({}, Image):__init()
return self
end
function Image:init(props, basalt)
VisualElement.init(self, props, basalt)
self.set("type", "Image")
return self
end
--- Loads a bimg format image
--- @param bimgData table The bimg image data
function Image:loadBimg(bimgData)
if type(bimgData) ~= "table" then return self end
local frames = {}
local metadata = {}
for k, v in pairs(bimgData) do
if type(k) == "number" then
frames[k] = v
else
metadata[k] = v
end
end
self.set("bimg", frames)
self.set("metadata", metadata)
if frames[1] and frames[1][1] then
self.set("width", #frames[1][1][2])
self.set("height", #frames[1])
end
return self
end
--- Gets pixel information at position
--- @param x number X position
--- @param y number Y position
--- @return number? fg Foreground color
--- @return number? bg Background color
--- @return string? char Character at position
function Image:getPixelData(x, y)
local frame = self.get("bimg")[self.get("currentFrame")]
if not frame or not frame[y] then return end
local text = frame[y][1]
local fg = frame[y][2]
local bg = frame[y][3]
if not text or not fg or not bg then return end
local fgColor = tonumber(fg:sub(x,x), 16)
local bgColor = tonumber(bg:sub(x,x), 16)
local char = text:sub(x,x)
return fgColor, bgColor, char
end
--- Sets character at position
--- @param x number X position
--- @param y number Y position
--- @param char string Single character to set
function Image:setChar(x, y, char)
if type(char) ~= "string" or #char ~= 1 then return self end
local frame = self.get("bimg")[self.get("currentFrame")]
if not frame then
frame = {{}, {}, {}}
self.get("bimg")[self.get("currentFrame")] = frame
end
if not frame[y] then
frame[y] = {"", "", ""}
end
local text = frame[y][1]
while #text < x do
text = text .. " "
end
frame[y][1] = text:sub(1, x-1) .. char .. text:sub(x+1)
self:updateRender()
return self
end
--- Sets foreground color at position
--- @param x number X position
--- @param y number Y position
--- @param color number Color value (0-15)
function Image:setFg(x, y, color)
if type(color) ~= "number" then return self end
local frame = self.get("bimg")[self.get("currentFrame")]
if not frame then
frame = {{}, {}, {}}
self.get("bimg")[self.get("currentFrame")] = frame
end
if not frame[y] then
frame[y] = {"", "", ""}
end
local fg = frame[y][2]
while #fg < x do
fg = fg .. "f"
end
frame[y][2] = fg:sub(1, x-1) .. tHex[color] .. fg:sub(x+1)
self:updateRender()
return self
end
--- Sets background color at position
--- @param x number X position
--- @param y number Y position
--- @param color number Color value (0-15)
function Image:setBg(x, y, color)
if type(color) ~= "number" then return self end
local frame = self.get("bimg")[self.get("currentFrame")]
if not frame then
frame = {{}, {}, {}}
self.get("bimg")[self.get("currentFrame")] = frame
end
if not frame[y] then
frame[y] = {"", "", ""}
end
local bg = frame[y][3]
while #bg < x do
bg = bg .. "f"
end
frame[y][3] = bg:sub(1, x-1) .. tHex[color] .. bg:sub(x+1)
self:updateRender()
return self
end
--- Sets all properties at position
--- @param x number X position
--- @param y number Y position
--- @param char string? Character to set (optional)
--- @param fg number? Foreground color (optional)
--- @param bg number? Background color (optional)
function Image:setPixel(x, y, char, fg, bg)
if char then self:setChar(x, y, char) end
if fg then self:setFg(x, y, fg) end
if bg then self:setBg(x, y, bg) end
return self
end
function Image:nextFrame()
if not self.get("metadata").animation then return end
local frames = self.get("bimg")
local current = self.get("currentFrame")
local next = current + 1
if next > #frames then next = 1 end
self.set("currentFrame", next)
return self
end
function Image:render()
VisualElement.render(self)
local frame = self.get("bimg")[self.get("currentFrame")]
if not frame then return end
for y, line in ipairs(frame) do
local text = line[1]
local fg = line[2]
local bg = line[3]
if text and fg and bg then
self:blit(1, y, text, fg, bg)
end
end
end
return Image

View File

@@ -1,7 +1,6 @@
local VisualElement = require("elements/VisualElement")
local tHex = require("libraries/colorHex")
---@configDescription A text input field with various features
---@configDefault true
--- This is the input class. It provides a text input field that can handle user input with various features like
--- cursor movement, text manipulation, placeholder text, and input validation.

View File

@@ -1,6 +1,7 @@
local elementManager = require("elementManager")
local VisualElement = elementManager.getElement("VisualElement")
local wrapText = require("libraries/utils").wrapText
---@configDescription A simple text display element that automatically resizes its width based on the text content.
--- This is the label class. It provides a simple text display element that automatically
--- resizes its width based on the text content.

View File

@@ -1,6 +1,5 @@
local VisualElement = require("elements/VisualElement")
---@configDescription A scrollable list of selectable items
---@configDefault true
--- This is the list class. It provides a scrollable list of selectable items with support for
--- custom item rendering, separators, and selection handling.
@@ -151,7 +150,7 @@ function List:mouse_scroll(direction, x, y)
if self:isInBounds(x, y) then
local offset = self.get("offset")
local maxOffset = math.max(0, #self.get("items") - self.get("height"))
offset = math.min(maxOffset, math.max(0, offset + direction))
self.set("offset", offset)
return true

View File

@@ -1,7 +1,7 @@
local VisualElement = require("elements/VisualElement")
local List = require("elements/List")
local tHex = require("libraries/colorHex")
---@configDescription A horizontal menu bar with selectable
---@configDescription A horizontal menu bar with selectable items.
--- This is the menu class. It provides a horizontal menu bar with selectable items.
--- Menu items are displayed in a single row and can have custom colors and callbacks.

View File

@@ -2,17 +2,18 @@ local elementManager = require("elementManager")
local VisualElement = elementManager.getElement("VisualElement")
local errorManager = require("errorManager")
--TODO:
-- Rendering optimization (only render when screen changed)
-- Eventsystem improvement
-- Cursor is sometimes not visible on time
--- @configDescription A program that runs in a window
--- This is the program class. It provides a program that runs in a window.
---@class Program : VisualElement
local Program = setmetatable({}, VisualElement)
Program.__index = Program
--- @property program table nil The program instance
Program.defineProperty(Program, "program", {default = nil, type = "table"})
--- @property path string "" The path to the program
Program.defineProperty(Program, "path", {default = "", type = "string"})
--- @property running boolean false Whether the program is running
Program.defineProperty(Program, "running", {default = false, type = "boolean"})
Program.defineEvent(Program, "key")
@@ -28,6 +29,7 @@ local BasaltProgram = {}
BasaltProgram.__index = BasaltProgram
local newPackage = dofile("rom/modules/main/cc/require.lua").make
---@private
function BasaltProgram.new()
local self = setmetatable({}, BasaltProgram)
self.env = {}
@@ -35,6 +37,7 @@ function BasaltProgram.new()
return self
end
---@private
function BasaltProgram:run(path, width, height)
self.window = window.create(term.current(), 1, 1, width, height, false)
local pPath = shell.resolveProgram(path)
@@ -79,10 +82,12 @@ function BasaltProgram:run(path, width, height)
end
end
---@private
function BasaltProgram:resize(width, height)
self.window.reposition(1, 1, width, height)
end
---@private
function BasaltProgram:resume(event, ...)
if self.coroutine==nil or coroutine.status(self.coroutine)=="dead" then return end
if(self.filter~=nil)then
@@ -103,11 +108,13 @@ function BasaltProgram:resume(event, ...)
return ok, result
end
---@private
function BasaltProgram:stop()
end
--- Creates a new Program instance
--- @shortDescription Creates a new Program instance
--- @return Program object The newly created Program instance
--- @usage local element = Program.new("myId", basalt)
function Program.new()
@@ -118,11 +125,21 @@ function Program.new()
return self
end
--- Initializes the Program instanceProperty
--- @shortDescription Initializes the Program instance
--- @param props table The properties to initialize the element with
--- @param basalt table The basalt instance
--- @return Program self The initialized instance
function Program:init(props, basalt)
VisualElement.init(self, props, basalt)
self.set("type", "Program")
return self
end
--- Executes a program
--- @shortDescription Executes a program
--- @param path string The path to the program
--- @return Program self The Program instance
function Program:execute(path)
self.set("path", path)
self.set("running", true)
@@ -133,6 +150,11 @@ function Program:execute(path)
return self
end
--- Handles all incomming events
--- @shortDescription Handles all incomming events
--- @param event string The event to handle
--- @param ... any The event arguments
--- @return any result The event result
function Program:dispatchEvent(event, ...)
local program = self.get("program")
local result = VisualElement.dispatchEvent(self, event, ...)
@@ -148,6 +170,8 @@ function Program:dispatchEvent(event, ...)
return result
end
--- Gets called when the element gets focused
--- @shortDescription Gets called when the element gets focused
function Program:focus()
if(VisualElement.focus(self))then
local program = self.get("program")
@@ -159,6 +183,8 @@ function Program:focus()
end
end
--- Renders the program
--- @shortDescription Renders the program
function Program:render()
VisualElement.render(self)
local program = self.get("program")

View File

@@ -54,6 +54,11 @@ function Scrollbar.new()
return self
end
--- Initializes the Scrollbar instance
--- @shortDescription Initializes the Scrollbar instance
--- @param props table The properties to initialize the element with
--- @param basalt table The basalt instance
--- @return Scrollbar self The initialized instance
function Scrollbar:init(props, basalt)
VisualElement.init(self, props, basalt)
self.set("type", "Scrollbar")
@@ -61,6 +66,7 @@ function Scrollbar:init(props, basalt)
end
--- Attaches the scrollbar to an element's property
--- @shortDescription Attaches the scrollbar to an element's property
--- @param element BaseElement The element to attach to
--- @param config table Configuration {property = "propertyName", min = number|function, max = number|function}
--- @return Scrollbar self The scrollbar instance
@@ -72,6 +78,9 @@ function Scrollbar:attach(element, config)
return self
end
--- Updates the attached element's property based on the scrollbar value
--- @shortDescription Updates the attached element's property based on the scrollbar value
--- @return Scrollbar self The scrollbar instance
function Scrollbar:updateAttachedElement()
local element = self.get("attachedElement")
if not element then return end
@@ -85,6 +94,7 @@ function Scrollbar:updateAttachedElement()
local mappedValue = min + (value / 100) * (max - min)
element.set(self.get("attachedProperty"), math.floor(mappedValue + 0.5))
return self
end
local function getScrollbarSize(self)
@@ -96,6 +106,12 @@ local function getRelativeScrollPosition(self, x, y)
return self.get("orientation") == "vertical" and relY or relX
end
--- Handles mouse click events
--- @shortDescription Handles mouse click events
--- @param button number The mouse button clicked
--- @param x number The x position of the click
--- @param y number The y position of the click
--- @return boolean Whether the event was handled
function Scrollbar:mouse_click(button, x, y)
if VisualElement.mouse_click(self, button, x, y) then
local size = getScrollbarSize(self)
@@ -116,6 +132,12 @@ function Scrollbar:mouse_click(button, x, y)
end
end
--- Handles mouse drag events
--- @shortDescription Handles mouse drag events
--- @param button number The mouse button being dragged
--- @param x number The x position of the drag
--- @param y number The y position of the drag
--- @return boolean Whether the event was handled
function Scrollbar:mouse_drag(button, x, y)
if(VisualElement.mouse_drag(self, button, x, y))then
local size = getScrollbarSize(self)
@@ -134,6 +156,12 @@ function Scrollbar:mouse_drag(button, x, y)
end
end
--- Handles mouse scroll events
--- @shortDescription Handles mouse scroll events
--- @param direction number The scroll direction (1 for up, -1 for down)
--- @param x number The x position of the scroll
--- @param y number The y position of the scroll
--- @return boolean Whether the event was handled
function Scrollbar:mouse_scroll(direction, x, y)
if not self:isInBounds(x, y) then return false end
direction = direction > 0 and -1 or 1
@@ -146,6 +174,8 @@ function Scrollbar:mouse_scroll(direction, x, y)
return true
end
--- Renders the Scrollbar
--- @shortDescription Renders the scrollbar
function Scrollbar:render()
VisualElement.render(self)

View File

@@ -74,6 +74,12 @@ function Slider:mouse_click(button, x, y)
end
Slider.mouse_drag = Slider.mouse_click
--- Handles mouse release events
--- @shortDescription Handles mouse release events
--- @param button number The mouse button that was released
--- @param x number The x position of the release
--- @param y number The y position of the release
--- @return boolean handled Whether the event was handled
function Slider:mouse_scroll(direction, x, y)
if self:isInBounds(x, y) then
local step = self.get("step")

View File

@@ -52,28 +52,6 @@ function Table:init(props, basalt)
return self
end
--- Sets the table columns
--- @shortDescription Sets the table columns configuration
--- @param columns table[] Array of column definitions {name="Name", width=10}
--- @return Table self The Table instance
--- @usage table:setColumns({{name="ID", width=4}, {name="Name", width=10}})
function Table:setColumns(columns)
-- Columns Format: {{name="ID", width=4}, {name="Name", width=10}}
self.set("columns", columns)
return self
end
--- Sets the table data
--- @shortDescription Sets the table data
--- @param data table[] Array of row data arrays
--- @return Table self The Table instance
--- @usage table:setData({{"1", "Item One"}, {"2", "Item Two"}})
function Table:setData(data)
-- Data Format: {{"1", "Item One"}, {"2", "Item Two"}}
self.set("data", data)
return self
end
--- Sorts the table data by column
--- @shortDescription Sorts the table data by the specified column
--- @param columnIndex number The index of the column to sort by

View File

@@ -30,6 +30,9 @@ TextBox.defineEvent(TextBox, "key")
TextBox.defineEvent(TextBox, "char")
TextBox.defineEvent(TextBox, "mouse_scroll")
--- Creates a new TextBox instance
--- @shortDescription Creates a new TextBox instance
--- @return TextBox self The newly created TextBox instance
function TextBox.new()
local self = setmetatable({}, TextBox):__init()
self.set("width", 20)
@@ -37,6 +40,11 @@ function TextBox.new()
return self
end
--- Initializes the TextBox instance
--- @shortDescription Initializes the TextBox instance
--- @param props table The properties to initialize the element with
--- @param basalt table The basalt instance
--- @return TextBox self The initialized instance
function TextBox:init(props, basalt)
VisualElement.init(self, props, basalt)
self.set("type", "TextBox")
@@ -44,6 +52,7 @@ function TextBox:init(props, basalt)
end
--- Adds a new syntax highlighting pattern
--- @shortDescription Adds a new syntax highlighting pattern
--- @param pattern string The regex pattern to match
--- @param color colors The color to apply
function TextBox:addSyntaxPattern(pattern, color)
@@ -98,6 +107,9 @@ local function backspace(self)
self:updateRender()
end
--- Updates the viewport to keep the cursor in view
--- @shortDescription Updates the viewport to keep the cursor in view
--- @return TextBox self The TextBox instance
function TextBox:updateViewport()
local cursorX = self.get("cursorX")
local cursorY = self.get("cursorY")
@@ -119,14 +131,23 @@ function TextBox:updateViewport()
elseif cursorY - scrollY < 1 then
self.set("scrollY", cursorY - 1)
end
return self
end
--- Handles character input
--- @shortDescription Handles character input
--- @param char string The character that was typed
--- @return boolean handled Whether the event was handled
function TextBox:char(char)
if not self.get("editable") or not self.get("focused") then return false end
insertChar(self, char)
return true
end
--- Handles key events
--- @shortDescription Handles key events
--- @param key number The key that was pressed
--- @return boolean handled Whether the event was handled
function TextBox:key(key)
if not self.get("editable") or not self.get("focused") then return false end
local lines = self.get("lines")
@@ -163,6 +184,12 @@ function TextBox:key(key)
return true
end
--- Handles mouse scroll events
--- @shortDescription Handles mouse scroll events
--- @param direction number The scroll direction
--- @param x number The x position of the scroll
--- @param y number The y position of the scroll
--- @return boolean handled Whether the event was handled
function TextBox:mouse_scroll(direction, x, y)
if self:isInBounds(x, y) then
local scrollY = self.get("scrollY")
@@ -172,7 +199,7 @@ function TextBox:mouse_scroll(direction, x, y)
local maxScroll = math.max(0, #lines - height + 2)
local newScroll = math.max(0, math.min(maxScroll, scrollY + direction))
self.set("scrollY", newScroll)
self:updateRender()
return true
@@ -180,6 +207,12 @@ function TextBox:mouse_scroll(direction, x, y)
return false
end
--- Handles mouse click events
--- @shortDescription Handles mouse click events
--- @param button number The button that was clicked
--- @param x number The x position of the click
--- @param y number The y position of the click
--- @return boolean handled Whether the event was handled
function TextBox:mouse_click(button, x, y)
if VisualElement.mouse_click(self, button, x, y) then
local relX, relY = self:getRelativePosition(x, y)
@@ -199,6 +232,10 @@ function TextBox:mouse_click(button, x, y)
return false
end
--- Sets the text of the TextBox
--- @shortDescription Sets the text of the TextBox
--- @param text string The text to set
--- @return TextBox self The TextBox instance
function TextBox:setText(text)
local lines = {}
if text == "" then
@@ -212,6 +249,9 @@ function TextBox:setText(text)
return self
end
--- Gets the text of the TextBox
--- @shortDescription Gets the text of the TextBox
--- @return string text The text of the TextBox
function TextBox:getText()
return table.concat(self.get("lines"), "\n")
end
@@ -220,7 +260,7 @@ local function applySyntaxHighlighting(self, line)
local text = line
local colors = string.rep(tHex[self.get("foreground")], #text)
local patterns = self.get("syntaxPatterns")
for _, syntax in ipairs(patterns) do
local start = 1
while true do
@@ -234,6 +274,8 @@ local function applySyntaxHighlighting(self, line)
return text, colors
end
--- Renders the TextBox
--- @shortDescription Renders the TextBox with syntax highlighting
function TextBox:render()
VisualElement.render(self)

View File

@@ -1,5 +1,6 @@
local VisualElement = require("elements/VisualElement")
local sub = string.sub
---@cofnigDescription The tree element provides a hierarchical view of nodes that can be expanded and collapsed, with support for selection and scrolling.
--- This is the tree class. It provides a hierarchical view of nodes that can be expanded and collapsed,
--- with support for selection and scrolling.
@@ -8,7 +9,12 @@ local Tree = setmetatable({}, VisualElement)
Tree.__index = Tree
---@property nodes table {} The tree structure containing node objects with {text, children} properties
Tree.defineProperty(Tree, "nodes", {default = {}, type = "table", canTriggerRender = true})
Tree.defineProperty(Tree, "nodes", {default = {}, type = "table", canTriggerRender = true, setter = function(self, value)
if #value > 0 then
self.get("expandedNodes")[value[1]] = true
end
return value
end})
---@property selectedNode table? nil Currently selected node
Tree.defineProperty(Tree, "selectedNode", {default = nil, type = "table", canTriggerRender = true})
---@property expandedNodes table {} Table of nodes that are currently expanded
@@ -48,19 +54,6 @@ function Tree:init(props, basalt)
return self
end
--- Sets the tree nodes
--- @shortDescription Sets the tree nodes and expands the root node
--- @param nodes table[] Array of node objects
--- @return Tree self The Tree instance
--- @usage tree:setNodes({{text="Root", children={{text="Child"}}}})
function Tree:setNodes(nodes)
self.set("nodes", nodes)
if #nodes > 0 then
self.get("expandedNodes")[nodes[1]] = true
end
return self
end
--- Expands a node
--- @shortDescription Expands a node to show its children
--- @param node table The node to expand
@@ -107,6 +100,12 @@ local function flattenTree(nodes, expandedNodes, level, result)
return result
end
--- Handles mouse click events
--- @shortDescription Handles mouse click events for node selection and expansion
--- @param button number The button that was clicked
--- @param x number The x position of the click
--- @param y number The y position of the click
--- @return boolean handled Whether the event was handled
function Tree:mouse_click(button, x, y)
if VisualElement.mouse_click(self, button, x, y) then
local relX, relY = self:getRelativePosition(x, y)
@@ -137,7 +136,12 @@ function Tree:onSelect(callback)
return self
end
---@private
--- Handles mouse scroll events
--- @shortDescription Handles mouse scroll events for vertical scrolling
--- @param direction number The scroll direction (1 for up, -1 for down)
--- @param x number The x position of the scroll
--- @param y number The y position of the scroll
--- @return boolean handled Whether the event was handled
function Tree:mouse_scroll(direction, x, y)
if VisualElement.mouse_scroll(self, direction, x, y) then
local flatNodes = flattenTree(self.get("nodes"), self.get("expandedNodes"))
@@ -163,6 +167,8 @@ function Tree:getNodeSize()
return width, height
end
--- Renders the tree
--- @shortDescription Renders the tree with nodes, selection and scrolling
function Tree:render()
VisualElement.render(self)

View File

@@ -2,7 +2,6 @@ local elementManager = require("elementManager")
local BaseElement = elementManager.getElement("BaseElement")
local tHex = require("libraries/colorHex")
---@configDescription The Visual Element class which is the base class for all visual UI elements
---@configDefault true
--- This is the visual element class. It serves as the base class for all visual UI elements
--- and provides core functionality for positioning, sizing, colors, and rendering.
@@ -79,24 +78,28 @@ VisualElement.combineProperties(VisualElement, "size", "width", "height")
---@combinedProperty color {foreground background} Combined foreground, background colors
VisualElement.combineProperties(VisualElement, "color", "foreground", "background")
---@event onMouseClick {button number, x number, y number} Fired on mouse click
---@event onMouseUp {button number, x number, y number} Fired on mouse button release
---@event onMouseRelease {button number, x number, y number} Fired when mouse leaves while clicked
---@event onMouseDrag {button number, x number, y number} Fired when mouse moves while clicked
---@event onClick {button, x, y} Fired on mouse click
---@event onMouseUp {button, x, y} Fired on mouse button release
---@event onRelease {button, x, y} Fired when mouse leaves while clicked
---@event onDrag {button, x, y} Fired when mouse moves while clicked
---@event onScroll {direction, x, y} Fired on mouse scroll
---@event onEnter {-} Fired when mouse enters element
---@event onLeave {-} Fired when mouse leaves element
---@event onFocus {-} Fired when element receives focus
---@event onBlur {-} Fired when element loses focus
---@event onKey {key number, code number, isRepeat boolean} Fired on key press
---@event onKeyUp {key number, code number} Fired on key release
---@event onChar {char string} Fired on character input
---@event onKey {key} Fired on key press
---@event onKeyUp {key} Fired on key release
---@event onChar {char} Fired on character input
VisualElement.defineEvent(VisualElement, "focus")
VisualElement.defineEvent(VisualElement, "blur")
VisualElement.registerEventCallback(VisualElement, "MouseClick", "mouse_click", "mouse_up")
VisualElement.registerEventCallback(VisualElement, "Click", "mouse_click", "mouse_up")
VisualElement.registerEventCallback(VisualElement, "MouseUp", "mouse_up", "mouse_click")
VisualElement.registerEventCallback(VisualElement, "MouseDrag", "mouse_drag", "mouse_click", "mouse_up")
VisualElement.registerEventCallback(VisualElement, "MouseScroll", "mouse_scroll")
VisualElement.registerEventCallback(VisualElement, "MouseEnter", "mouse_enter", "mouse_move")
VisualElement.registerEventCallback(VisualElement, "Drag", "mouse_drag", "mouse_click", "mouse_up")
VisualElement.registerEventCallback(VisualElement, "Scroll", "mouse_scroll")
VisualElement.registerEventCallback(VisualElement, "Enter", "mouse_enter", "mouse_move")
VisualElement.registerEventCallback(VisualElement, "LeEave", "mouse_leave", "mouse_move")
VisualElement.registerEventCallback(VisualElement, "Focus", "focus", "blur")
VisualElement.registerEventCallback(VisualElement, "Blur", "blur", "focus")