Docs Update
This commit is contained in:
@@ -7,7 +7,6 @@ local btn = main:addButton()
|
|||||||
:setY(5)
|
:setY(5)
|
||||||
:onMouseClick(function()
|
:onMouseClick(function()
|
||||||
main:logContainerBenchmarks("render")
|
main:logContainerBenchmarks("render")
|
||||||
--main:stopChildrenBenchmark("render")
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local prog = main:addProgram()
|
local prog = main:addProgram()
|
||||||
|
|||||||
39
generate-docs.lua
Normal file
39
generate-docs.lua
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
local markdown = require("tools/markdown")
|
||||||
|
local log = require("src/log")
|
||||||
|
|
||||||
|
if not fs.exists("docs/references") then
|
||||||
|
fs.makeDir("docs/references")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function processFile(inputFile)
|
||||||
|
local parsed = markdown.parseFile(inputFile)
|
||||||
|
local md = markdown.makeMarkdown(parsed)
|
||||||
|
|
||||||
|
local relativePath = inputFile:match("Basalt2/src/(.+)")
|
||||||
|
if not relativePath then return end
|
||||||
|
|
||||||
|
local outputFile = "docs/references/" .. relativePath:gsub("%.lua$", "")
|
||||||
|
|
||||||
|
local dir = fs.getDir(outputFile)
|
||||||
|
if not fs.exists(dir) then
|
||||||
|
fs.makeDir(dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
--print(string.format("Processing: %s -> %s", inputFile, outputFile))
|
||||||
|
|
||||||
|
markdown.saveToFile(outputFile, md)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function processDirectory(path)
|
||||||
|
for _, file in ipairs(fs.list(path)) do
|
||||||
|
local fullPath = fs.combine(path, file)
|
||||||
|
if fs.isDir(fullPath) then
|
||||||
|
processDirectory(fullPath)
|
||||||
|
elseif file:match("%.lua$") and not file:match("LuaLS%.lua$") then
|
||||||
|
processFile(fullPath)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
processDirectory("Basalt2/src")
|
||||||
@@ -10,6 +10,9 @@ local defaultPath = package.path
|
|||||||
local format = "path;/path/?.lua;/path/?/init.lua;"
|
local format = "path;/path/?.lua;/path/?/init.lua;"
|
||||||
local main = format:gsub("path", dir)
|
local main = format:gsub("path", dir)
|
||||||
|
|
||||||
|
--- This class manages elements and plugins. It loads elements and plugins from the elements and plugins directories
|
||||||
|
--- and then applies the plugins to the elements. It also provides a way to get elements and APIs.
|
||||||
|
--- @class ElementManager
|
||||||
local ElementManager = {}
|
local ElementManager = {}
|
||||||
ElementManager._elements = {}
|
ElementManager._elements = {}
|
||||||
ElementManager._plugins = {}
|
ElementManager._plugins = {}
|
||||||
@@ -55,6 +58,9 @@ if fs.exists(pluginsDirectory) then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Loads an element by name. This will load the element and apply any plugins to it.
|
||||||
|
--- @param name string The name of the element to load
|
||||||
|
--- @usage ElementManager.loadElement("Button")
|
||||||
function ElementManager.loadElement(name)
|
function ElementManager.loadElement(name)
|
||||||
if not ElementManager._elements[name].loaded then
|
if not ElementManager._elements[name].loaded then
|
||||||
package.path = main.."rom/?"
|
package.path = main.."rom/?"
|
||||||
@@ -106,6 +112,9 @@ function ElementManager.loadElement(name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets an element by name. If the element is not loaded, it will try to load it first.
|
||||||
|
--- @param name string The name of the element to get
|
||||||
|
--- @return table Element The element class
|
||||||
function ElementManager.getElement(name)
|
function ElementManager.getElement(name)
|
||||||
if not ElementManager._elements[name].loaded then
|
if not ElementManager._elements[name].loaded then
|
||||||
ElementManager.loadElement(name)
|
ElementManager.loadElement(name)
|
||||||
@@ -113,10 +122,15 @@ function ElementManager.getElement(name)
|
|||||||
return ElementManager._elements[name].class
|
return ElementManager._elements[name].class
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets a list of all elements
|
||||||
|
--- @return table ElementList A list of all elements
|
||||||
function ElementManager.getElementList()
|
function ElementManager.getElementList()
|
||||||
return ElementManager._elements
|
return ElementManager._elements
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets an Plugin API by name
|
||||||
|
--- @param name string The name of the API to get
|
||||||
|
--- @return table API The API
|
||||||
function ElementManager.getAPI(name)
|
function ElementManager.getAPI(name)
|
||||||
return ElementManager._APIs[name]
|
return ElementManager._APIs[name]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ BaseElement.defineProperty(BaseElement, "name", {default = "", type = "string"})
|
|||||||
BaseElement.defineProperty(BaseElement, "eventCallbacks", {default = {}, type = "table"})
|
BaseElement.defineProperty(BaseElement, "eventCallbacks", {default = {}, type = "table"})
|
||||||
|
|
||||||
--- Registers an event that this class can listen to
|
--- Registers an event that this class can listen to
|
||||||
|
--- @shortDescription Registers an event that this class can listen to
|
||||||
--- @param class table The class to add the event to
|
--- @param class table The class to add the event to
|
||||||
--- @param eventName string The name of the event to register
|
--- @param eventName string The name of the event to register
|
||||||
--- @usage BaseElement.listenTo(MyClass, "mouse_click")
|
--- @usage BaseElement.listenTo(MyClass, "mouse_click")
|
||||||
@@ -42,16 +43,18 @@ function BaseElement.listenTo(class, eventName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a new BaseElement instance
|
--- Creates a new BaseElement instance
|
||||||
|
--- @shortDescription Creates a new BaseElement instance
|
||||||
--- @param props table The properties to initialize the element with
|
--- @param props table The properties to initialize the element with
|
||||||
--- @param basalt table The basalt instance
|
--- @param basalt table The basalt instance
|
||||||
--- @return table The newly created BaseElement instance
|
--- @return table The newly created BaseElement instance
|
||||||
--- @usage local element = BaseElement.new("myId", basalt)
|
--- @usage local element = BaseElement.new()
|
||||||
function BaseElement.new()
|
function BaseElement.new()
|
||||||
local self = setmetatable({}, BaseElement):__init()
|
local self = setmetatable({}, BaseElement):__init()
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Initializes the BaseElement instance
|
--- Initializes the BaseElement instance
|
||||||
|
--- @shortDescription Initializes the BaseElement instance
|
||||||
--- @param props table The properties to initialize the element with
|
--- @param props table The properties to initialize the element with
|
||||||
--- @param basalt table The basalt instance
|
--- @param basalt table The basalt instance
|
||||||
--- @return table self The initialized instance
|
--- @return table self The initialized instance
|
||||||
@@ -76,6 +79,7 @@ function BaseElement:init(props, basalt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Post initialization
|
--- Post initialization
|
||||||
|
--- @shortDescription Post initialization
|
||||||
--- @return table self The BaseElement instance
|
--- @return table self The BaseElement instance
|
||||||
function BaseElement:postInit()
|
function BaseElement:postInit()
|
||||||
if(self._props)then
|
if(self._props)then
|
||||||
@@ -88,6 +92,7 @@ function BaseElement:postInit()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Checks if the element is a specific type
|
--- Checks if the element is a specific type
|
||||||
|
--- @shortDescription Checks if the element is a specific type
|
||||||
--- @param type string The type to check for
|
--- @param type string The type to check for
|
||||||
--- @return boolean Whether the element is of the specified type
|
--- @return boolean Whether the element is of the specified type
|
||||||
function BaseElement:isType(type)
|
function BaseElement:isType(type)
|
||||||
@@ -100,6 +105,7 @@ function BaseElement:isType(type)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Enables or disables event listening for a specific event
|
--- Enables or disables event listening for a specific event
|
||||||
|
--- @shortDescription Enables or disables event listening for a specific event
|
||||||
--- @param eventName string The name of the event to listen for
|
--- @param eventName string The name of the event to listen for
|
||||||
--- @param enable? boolean Whether to enable or disable the event (default: true)
|
--- @param enable? boolean Whether to enable or disable the event (default: true)
|
||||||
--- @return table self The BaseElement instance
|
--- @return table self The BaseElement instance
|
||||||
@@ -123,6 +129,7 @@ function BaseElement:listenEvent(eventName, enable)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Registers a callback function for an event
|
--- Registers a callback function for an event
|
||||||
|
--- @shortDescription Registers a callback function
|
||||||
--- @param event string The event to register the callback for
|
--- @param event string The event to register the callback for
|
||||||
--- @param callback function The callback function to register
|
--- @param callback function The callback function to register
|
||||||
--- @return table self The BaseElement instance
|
--- @return table self The BaseElement instance
|
||||||
@@ -141,6 +148,7 @@ function BaseElement:registerCallback(event, callback)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Triggers an event and calls all registered callbacks
|
--- Triggers an event and calls all registered callbacks
|
||||||
|
--- @shortDescription Triggers an event and calls all registered callbacks
|
||||||
--- @param event string The event to fire
|
--- @param event string The event to fire
|
||||||
--- @param ... any Additional arguments to pass to the callbacks
|
--- @param ... any Additional arguments to pass to the callbacks
|
||||||
--- @return table self The BaseElement instance
|
--- @return table self The BaseElement instance
|
||||||
@@ -156,6 +164,7 @@ function BaseElement:fireEvent(event, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles all events
|
--- Handles all events
|
||||||
|
--- @shortDescription Handles all events
|
||||||
--- @param event string The event to handle
|
--- @param event string The event to handle
|
||||||
--- @vararg any The arguments for the event
|
--- @vararg any The arguments for the event
|
||||||
--- @return boolean? handled Whether the event was handled
|
--- @return boolean? handled Whether the event was handled
|
||||||
@@ -167,6 +176,7 @@ function BaseElement:dispatchEvent(event, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- The default event handler for all events
|
--- The default event handler for all events
|
||||||
|
--- @shortDescription The default event handler for all events
|
||||||
--- @param event string The event to handle
|
--- @param event string The event to handle
|
||||||
--- @vararg any The arguments for the event
|
--- @vararg any The arguments for the event
|
||||||
--- @return boolean? handled Whether the event was handled
|
--- @return boolean? handled Whether the event was handled
|
||||||
@@ -175,6 +185,7 @@ function BaseElement:handleEvent(event, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the base frame of the element
|
--- Returns the base frame of the element
|
||||||
|
--- @shortDescription Returns the base frame of the element
|
||||||
--- @return table BaseFrame The base frame of the element
|
--- @return table BaseFrame The base frame of the element
|
||||||
function BaseElement:getBaseFrame()
|
function BaseElement:getBaseFrame()
|
||||||
if self.parent then
|
if self.parent then
|
||||||
@@ -184,6 +195,7 @@ function BaseElement:getBaseFrame()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Destroys the element and cleans up all references
|
--- Destroys the element and cleans up all references
|
||||||
|
--- @shortDescription Destroys the element and cleans up all references
|
||||||
--- @usage element:destroy()
|
--- @usage element:destroy()
|
||||||
function BaseElement:destroy()
|
function BaseElement:destroy()
|
||||||
-- Remove from parent if exists
|
-- Remove from parent if exists
|
||||||
@@ -206,6 +218,7 @@ function BaseElement:destroy()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Requests a render update for this element
|
--- Requests a render update for this element
|
||||||
|
--- @shortDescription Requests a render update for this element
|
||||||
--- @usage element:updateRender()
|
--- @usage element:updateRender()
|
||||||
function BaseElement:updateRender()
|
function BaseElement:updateRender()
|
||||||
if(self.parent) then
|
if(self.parent) then
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ local elementManager = require("elementManager")
|
|||||||
local Container = elementManager.getElement("Container")
|
local Container = elementManager.getElement("Container")
|
||||||
local Render = require("render")
|
local Render = require("render")
|
||||||
|
|
||||||
|
--- This is the base frame class. It is the root element of all elements and the only element without a parent.
|
||||||
---@class BaseFrame : Container
|
---@class BaseFrame : Container
|
||||||
|
---@field _render Render The render object
|
||||||
|
---@field _renderUpdate boolean Whether the render object needs to be updated
|
||||||
local BaseFrame = setmetatable({}, Container)
|
local BaseFrame = setmetatable({}, Container)
|
||||||
BaseFrame.__index = BaseFrame
|
BaseFrame.__index = BaseFrame
|
||||||
|
|
||||||
---@property text term term nil text
|
---@property text term nil The terminal object to render to
|
||||||
BaseFrame.defineProperty(BaseFrame, "term", {default = nil, type = "table", setter = function(self, value)
|
BaseFrame.defineProperty(BaseFrame, "term", {default = nil, type = "table", setter = function(self, value)
|
||||||
if value == nil or value.setCursorPos == nil then
|
if value == nil or value.setCursorPos == nil then
|
||||||
return value
|
return value
|
||||||
@@ -19,6 +22,10 @@ BaseFrame.defineProperty(BaseFrame, "term", {default = nil, type = "table", sett
|
|||||||
return value
|
return value
|
||||||
end})
|
end})
|
||||||
|
|
||||||
|
--- Creates a new Frame instance
|
||||||
|
--- @shortDescription Creates a new Frame instance
|
||||||
|
--- @return BaseFrame object The newly created Frame instance
|
||||||
|
--- @usage local element = BaseFrame.new()
|
||||||
function BaseFrame.new()
|
function BaseFrame.new()
|
||||||
local self = setmetatable({}, BaseFrame):__init()
|
local self = setmetatable({}, BaseFrame):__init()
|
||||||
self.set("term", term.current())
|
self.set("term", term.current())
|
||||||
@@ -26,32 +33,73 @@ function BaseFrame.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the Frame instance
|
||||||
|
--- @shortDescription Initializes the Frame instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return table self The initialized instance
|
||||||
function BaseFrame:init(props, basalt)
|
function BaseFrame:init(props, basalt)
|
||||||
Container.init(self, props, basalt)
|
Container.init(self, props, basalt)
|
||||||
self.set("type", "BaseFrame")
|
self.set("type", "BaseFrame")
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders a multiBlit to the render Object
|
||||||
|
--- @shortDescription Renders a multiBlit to the render Object
|
||||||
|
--- @param x number The x position to render to
|
||||||
|
--- @param y number The y position to render to
|
||||||
|
--- @param width number The width of the text
|
||||||
|
--- @param height number The height of the text
|
||||||
|
--- @param text string The text to render
|
||||||
|
--- @param fg string The foreground color
|
||||||
|
--- @param bg string The background color
|
||||||
function BaseFrame:multiBlit(x, y, width, height, text, fg, bg)
|
function BaseFrame:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
self._render:multiBlit(x, y, width, height, text, fg, bg)
|
self._render:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders a text with a foreground color to the render Object
|
||||||
|
--- @shortDescription Renders a text with a foreground color to the render Object
|
||||||
|
--- @param x number The x position to render to
|
||||||
|
--- @param y number The y position to render to
|
||||||
|
--- @param text string The text to render
|
||||||
|
--- @param fg colors The foreground color
|
||||||
function BaseFrame:textFg(x, y, text, fg)
|
function BaseFrame:textFg(x, y, text, fg)
|
||||||
self._render:textFg(x, y, text, fg)
|
self._render:textFg(x, y, text, fg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders a text with a background color to the render Object
|
||||||
|
--- @shortDescription Renders a text with a background color to the render Object
|
||||||
|
--- @param x number The x position to render to
|
||||||
|
--- @param y number The y position to render to
|
||||||
|
--- @param text string The text to render
|
||||||
|
--- @param bg colors The background color
|
||||||
function BaseFrame:textBg(x, y, text, bg)
|
function BaseFrame:textBg(x, y, text, bg)
|
||||||
self._render:textBg(x, y, text, bg)
|
self._render:textBg(x, y, text, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders a text with a foreground and background color to the render Object
|
||||||
|
--- @shortDescription Renders a text with a foreground and background color to the render Object
|
||||||
|
--- @param x number The x position to render to
|
||||||
|
--- @param y number The y position to render to
|
||||||
|
--- @param text string The text to render
|
||||||
|
--- @param fg string The foreground color
|
||||||
|
--- @param bg string The background color
|
||||||
function BaseFrame:blit(x, y, text, fg, bg)
|
function BaseFrame:blit(x, y, text, fg, bg)
|
||||||
self._render:blit(x, y, text, fg, bg)
|
self._render:blit(x, y, text, fg, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Sets the cursor position
|
||||||
|
--- @shortDescription Sets the cursor position
|
||||||
|
--- @param x number The x position to set the cursor to
|
||||||
|
--- @param y number The y position to set the cursor to
|
||||||
|
--- @param blink boolean Whether the cursor should blink
|
||||||
function BaseFrame:setCursor(x, y, blink)
|
function BaseFrame:setCursor(x, y, blink)
|
||||||
local term = self.get("term")
|
local term = self.get("term")
|
||||||
self._render:setCursor(x, y, blink)
|
self._render:setCursor(x, y, blink)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the Frame
|
||||||
|
--- @shortDescription Renders the Frame
|
||||||
function BaseFrame:render()
|
function BaseFrame:render()
|
||||||
if(self._renderUpdate) then
|
if(self._renderUpdate) then
|
||||||
if self._render ~= nil then
|
if self._render ~= nil then
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ local elementManager = require("elementManager")
|
|||||||
local VisualElement = elementManager.getElement("VisualElement")
|
local VisualElement = elementManager.getElement("VisualElement")
|
||||||
local getCenteredPosition = require("libraries/utils").getCenteredPosition
|
local getCenteredPosition = require("libraries/utils").getCenteredPosition
|
||||||
|
|
||||||
|
--- This is the button class. It is a visual element that can be clicked.
|
||||||
---@class Button : VisualElement
|
---@class Button : VisualElement
|
||||||
local Button = setmetatable({}, VisualElement)
|
local Button = setmetatable({}, VisualElement)
|
||||||
Button.__index = Button
|
Button.__index = Button
|
||||||
@@ -14,6 +15,7 @@ Button.listenTo(Button, "mouse_click")
|
|||||||
Button.listenTo(Button, "mouse_up")
|
Button.listenTo(Button, "mouse_up")
|
||||||
|
|
||||||
--- Creates a new Button instance
|
--- Creates a new Button instance
|
||||||
|
--- @shortDescription Creates a new Button instance
|
||||||
--- @return table self The created instance
|
--- @return table self The created instance
|
||||||
function Button.new()
|
function Button.new()
|
||||||
local self = setmetatable({}, Button):__init()
|
local self = setmetatable({}, Button):__init()
|
||||||
@@ -24,6 +26,7 @@ function Button.new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Initializes the Button instance
|
--- Initializes the Button instance
|
||||||
|
--- @shortDescription Initializes the Button instance
|
||||||
--- @param props table The properties to initialize the element with
|
--- @param props table The properties to initialize the element with
|
||||||
--- @param basalt table The basalt instance
|
--- @param basalt table The basalt instance
|
||||||
function Button:init(props, basalt)
|
function Button:init(props, basalt)
|
||||||
@@ -32,6 +35,7 @@ function Button:init(props, basalt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Renders the Button
|
--- Renders the Button
|
||||||
|
--- @shortDescription Renders the Button
|
||||||
function Button:render()
|
function Button:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
local text = self.get("text")
|
local text = self.get("text")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
local VisualElement = require("elements/VisualElement")
|
local VisualElement = require("elements/VisualElement")
|
||||||
|
|
||||||
|
--- This is the checkbox class. It is a visual element that can be checked.
|
||||||
---@class Checkbox : VisualElement
|
---@class Checkbox : VisualElement
|
||||||
local Checkbox = setmetatable({}, VisualElement)
|
local Checkbox = setmetatable({}, VisualElement)
|
||||||
Checkbox.__index = Checkbox
|
Checkbox.__index = Checkbox
|
||||||
@@ -14,6 +15,7 @@ Checkbox.defineProperty(Checkbox, "symbol", {default = "x", type = "string"})
|
|||||||
Checkbox.listenTo(Checkbox, "mouse_click")
|
Checkbox.listenTo(Checkbox, "mouse_click")
|
||||||
|
|
||||||
--- Creates a new Checkbox instance
|
--- Creates a new Checkbox instance
|
||||||
|
--- @shortDescription Creates a new Checkbox instance
|
||||||
--- @return Checkbox self The created instance
|
--- @return Checkbox self The created instance
|
||||||
function Checkbox.new()
|
function Checkbox.new()
|
||||||
local self = setmetatable({}, Checkbox):__init()
|
local self = setmetatable({}, Checkbox):__init()
|
||||||
@@ -23,6 +25,7 @@ function Checkbox.new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Initializes the Checkbox instance
|
--- Initializes the Checkbox instance
|
||||||
|
--- @shortDescription Initializes the Checkbox instance
|
||||||
--- @param props table The properties to initialize the element with
|
--- @param props table The properties to initialize the element with
|
||||||
--- @param basalt table The basalt instance
|
--- @param basalt table The basalt instance
|
||||||
function Checkbox:init(props, basalt)
|
function Checkbox:init(props, basalt)
|
||||||
@@ -31,10 +34,11 @@ function Checkbox:init(props, basalt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles mouse click events
|
--- Handles mouse click events
|
||||||
|
--- @shortDescription Handles mouse click events
|
||||||
--- @param button number The button that was clicked
|
--- @param button number The button that was clicked
|
||||||
--- @param x number The x position of the click
|
--- @param x number The x position of the click
|
||||||
--- @param y number The y position of the click
|
--- @param y number The y position of the click
|
||||||
--- @return boolean Whether the event was handled
|
--- @return boolean Clicked Whether the event was handled
|
||||||
function Checkbox:mouse_click(button, x, y)
|
function Checkbox:mouse_click(button, x, y)
|
||||||
if VisualElement.mouse_click(self, button, x, y) then
|
if VisualElement.mouse_click(self, button, x, y) then
|
||||||
self.set("checked", not self.get("checked"))
|
self.set("checked", not self.get("checked"))
|
||||||
@@ -45,6 +49,7 @@ function Checkbox:mouse_click(button, x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Renders the Checkbox
|
--- Renders the Checkbox
|
||||||
|
--- @shortDescription Renders the Checkbox
|
||||||
function Checkbox:render()
|
function Checkbox:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ local split = require("libraries/utils").split
|
|||||||
|
|
||||||
local max = math.max
|
local max = math.max
|
||||||
|
|
||||||
|
--- The container class. It is a visual element that can contain other elements. It is the base class for all containers,
|
||||||
|
--- like Frames, BaseFrames, and more.
|
||||||
---@class Container : VisualElement
|
---@class Container : VisualElement
|
||||||
local Container = setmetatable({}, VisualElement)
|
local Container = setmetatable({}, VisualElement)
|
||||||
Container.__index = Container
|
Container.__index = Container
|
||||||
@@ -66,6 +68,7 @@ for k, _ in pairs(elementManager:getElementList()) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a new Container instance
|
--- Creates a new Container instance
|
||||||
|
--- @shortDescription Creates a new Container instance
|
||||||
--- @return Container self The new container instance
|
--- @return Container self The new container instance
|
||||||
function Container.new()
|
function Container.new()
|
||||||
local self = setmetatable({}, Container):__init()
|
local self = setmetatable({}, Container):__init()
|
||||||
@@ -73,6 +76,7 @@ function Container.new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Initializes the Container instance
|
--- Initializes the Container instance
|
||||||
|
--- @shortDescription Initializes the Container instance
|
||||||
--- @param props table The properties to initialize the element with
|
--- @param props table The properties to initialize the element with
|
||||||
--- @param basalt table The basalt instance
|
--- @param basalt table The basalt instance
|
||||||
function Container:init(props, basalt)
|
function Container:init(props, basalt)
|
||||||
@@ -81,6 +85,7 @@ function Container:init(props, basalt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Returns whether a child is visible
|
--- Returns whether a child is visible
|
||||||
|
--- @shortDescription Returns whether a child is visible
|
||||||
--- @param child table The child to check
|
--- @param child table The child to check
|
||||||
--- @return boolean boolean the child is visible
|
--- @return boolean boolean the child is visible
|
||||||
function Container:isChildVisible(child)
|
function Container:isChildVisible(child)
|
||||||
@@ -95,6 +100,7 @@ function Container:isChildVisible(child)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Adds a child to the container
|
--- Adds a child to the container
|
||||||
|
--- @shortDescription Adds a child to the container
|
||||||
--- @param child table The child to add
|
--- @param child table The child to add
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
function Container:addChild(child)
|
function Container:addChild(child)
|
||||||
@@ -138,6 +144,7 @@ local function sortAndFilterChildren(self, children)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Clears the container
|
--- Clears the container
|
||||||
|
--- @shortDescription Clears the container
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
function Container:clear()
|
function Container:clear()
|
||||||
self.set("children", {})
|
self.set("children", {})
|
||||||
@@ -150,6 +157,7 @@ function Container:clear()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Sorts the children of the container
|
--- Sorts the children of the container
|
||||||
|
--- @shortDescription Sorts the children of the container
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
function Container:sortChildren()
|
function Container:sortChildren()
|
||||||
self.set("visibleChildren", sortAndFilterChildren(self, self._values.children))
|
self.set("visibleChildren", sortAndFilterChildren(self, self._values.children))
|
||||||
@@ -158,6 +166,7 @@ function Container:sortChildren()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Sorts the children events of the container
|
--- Sorts the children events of the container
|
||||||
|
--- @shortDescription Sorts the children events of the container
|
||||||
--- @param eventName string The event name to sort
|
--- @param eventName string The event name to sort
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
function Container:sortChildrenEvents(eventName)
|
function Container:sortChildrenEvents(eventName)
|
||||||
@@ -169,6 +178,7 @@ function Container:sortChildrenEvents(eventName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Registers the children events of the container
|
--- Registers the children events of the container
|
||||||
|
--- @shortDescription Registers the children events of the container
|
||||||
--- @param child table The child to register events for
|
--- @param child table The child to register events for
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
function Container:registerChildrenEvents(child)
|
function Container:registerChildrenEvents(child)
|
||||||
@@ -180,6 +190,7 @@ function Container:registerChildrenEvents(child)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Registers the children events of the container
|
--- Registers the children events of the container
|
||||||
|
--- @shortDescription Registers the children events of the container
|
||||||
--- @param child table The child to register events for
|
--- @param child table The child to register events for
|
||||||
--- @param eventName string The event name to register
|
--- @param eventName string The event name to register
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
@@ -206,6 +217,7 @@ function Container:registerChildEvent(child, eventName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Unregisters the children events of the container
|
--- Unregisters the children events of the container
|
||||||
|
--- @shortDescription Unregisters the children events of the container
|
||||||
--- @param child table The child to unregister events for
|
--- @param child table The child to unregister events for
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
function Container:removeChildrenEvents(child)
|
function Container:removeChildrenEvents(child)
|
||||||
@@ -217,6 +229,7 @@ function Container:removeChildrenEvents(child)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Unregisters the children events of the container
|
--- Unregisters the children events of the container
|
||||||
|
--- @shortDescription Unregisters the children events of the container
|
||||||
--- @param child table The child to unregister events for
|
--- @param child table The child to unregister events for
|
||||||
--- @param eventName string The event name to unregister
|
--- @param eventName string The event name to unregister
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
@@ -243,6 +256,7 @@ function Container:unregisterChildEvent(child, eventName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Removes a child from the container
|
--- Removes a child from the container
|
||||||
|
--- @shortDescription Removes a child from the container
|
||||||
--- @param child table The child to remove
|
--- @param child table The child to remove
|
||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
function Container:removeChild(child)
|
function Container:removeChild(child)
|
||||||
@@ -258,6 +272,7 @@ function Container:removeChild(child)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Removes a child from the container
|
--- Removes a child from the container
|
||||||
|
--- @shortDescription Removes a child from the container
|
||||||
--- @param path string The path to the child to remove
|
--- @param path string The path to the child to remove
|
||||||
--- @return Container? self The container instance
|
--- @return Container? self The container instance
|
||||||
function Container:getChild(path)
|
function Container:getChild(path)
|
||||||
@@ -303,9 +318,10 @@ local function callChildrenEvents(self, visibleOnly, event, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Default handler for events
|
--- Default handler for events
|
||||||
|
--- @shortDescription Default handler for events
|
||||||
--- @param event string The event to handle
|
--- @param event string The event to handle
|
||||||
--- @vararg any The event arguments
|
--- @vararg any The event arguments
|
||||||
--- @return boolean Whether the event was handled
|
--- @return boolean handled Whether the event was handled
|
||||||
function Container:handleEvent(event, ...)
|
function Container:handleEvent(event, ...)
|
||||||
VisualElement.handleEvent(self, event, ...)
|
VisualElement.handleEvent(self, event, ...)
|
||||||
local args = convertMousePosition(self, event, ...)
|
local args = convertMousePosition(self, event, ...)
|
||||||
@@ -313,10 +329,11 @@ function Container:handleEvent(event, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles mouse click events
|
--- Handles mouse click events
|
||||||
|
--- @shortDescription Handles mouse click events
|
||||||
--- @param button number The button that was clicked
|
--- @param button number The button that was clicked
|
||||||
--- @param x number The x position of the click
|
--- @param x number The x position of the click
|
||||||
--- @param y number The y position of the click
|
--- @param y number The y position of the click
|
||||||
--- @return boolean Whether the event was handled
|
--- @return boolean handled Whether the event was handled
|
||||||
function Container:mouse_click(button, x, y)
|
function Container:mouse_click(button, x, y)
|
||||||
if VisualElement.mouse_click(self, button, x, y) then
|
if VisualElement.mouse_click(self, button, x, y) then
|
||||||
local args = convertMousePosition(self, "mouse_click", button, x, y)
|
local args = convertMousePosition(self, "mouse_click", button, x, y)
|
||||||
@@ -332,10 +349,11 @@ function Container:mouse_click(button, x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles mouse up events
|
--- Handles mouse up events
|
||||||
|
--- @shortDescription Handles mouse up events
|
||||||
--- @param button number The button that was clicked
|
--- @param button number The button that was clicked
|
||||||
--- @param x number The x position of the click
|
--- @param x number The x position of the click
|
||||||
--- @param y number The y position of the click
|
--- @param y number The y position of the click
|
||||||
--- @return boolean Whether the event was handled
|
--- @return boolean handled Whether the event was handled
|
||||||
function Container:mouse_up(button, x, y)
|
function Container:mouse_up(button, x, y)
|
||||||
if VisualElement.mouse_up(self, button, x, y) then
|
if VisualElement.mouse_up(self, button, x, y) then
|
||||||
local args = convertMousePosition(self, "mouse_up", button, x, y)
|
local args = convertMousePosition(self, "mouse_up", button, x, y)
|
||||||
@@ -348,8 +366,9 @@ function Container:mouse_up(button, x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles key events
|
--- Handles key events
|
||||||
|
--- @shortDescription Handles key events
|
||||||
--- @param key number The key that was pressed
|
--- @param key number The key that was pressed
|
||||||
--- @return boolean Whether the event was handled
|
--- @return boolean handled Whether the event was handled
|
||||||
function Container:key(key)
|
function Container:key(key)
|
||||||
if self.get("focusedChild") then
|
if self.get("focusedChild") then
|
||||||
return self.get("focusedChild"):dispatchEvent("key", key)
|
return self.get("focusedChild"):dispatchEvent("key", key)
|
||||||
@@ -358,8 +377,9 @@ function Container:key(key)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles char events
|
--- Handles char events
|
||||||
|
--- @shortDescription Handles char events
|
||||||
--- @param char string The character that was pressed
|
--- @param char string The character that was pressed
|
||||||
--- @return boolean Whether the event was handled
|
--- @return boolean handled Whether the event was handled
|
||||||
function Container:char(char)
|
function Container:char(char)
|
||||||
if self.get("focusedChild") then
|
if self.get("focusedChild") then
|
||||||
return self.get("focusedChild"):dispatchEvent("char", char)
|
return self.get("focusedChild"):dispatchEvent("char", char)
|
||||||
@@ -368,8 +388,9 @@ function Container:char(char)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles key up events
|
--- Handles key up events
|
||||||
|
--- @shortDescription Handles key up events
|
||||||
--- @param key number The key that was released
|
--- @param key number The key that was released
|
||||||
--- @return boolean Whether the event was handled
|
--- @return boolean handled Whether the event was handled
|
||||||
function Container:key_up(key)
|
function Container:key_up(key)
|
||||||
if self.get("focusedChild") then
|
if self.get("focusedChild") then
|
||||||
return self.get("focusedChild"):dispatchEvent("key_up", key)
|
return self.get("focusedChild"):dispatchEvent("key_up", key)
|
||||||
@@ -378,6 +399,7 @@ function Container:key_up(key)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Draws multiple lines of text, fg and bg strings, it is usually used in the render loop
|
--- Draws multiple lines of text, fg and bg strings, it is usually used in the render loop
|
||||||
|
--- @shortDescription Draws multiple lines of text, fg and bg strings
|
||||||
--- @param x number The x position to draw the text
|
--- @param x number The x position to draw the text
|
||||||
--- @param y number The y position to draw the text
|
--- @param y number The y position to draw the text
|
||||||
--- @param width number The width of the text
|
--- @param width number The width of the text
|
||||||
@@ -399,6 +421,7 @@ function Container:multiBlit(x, y, width, height, text, fg, bg)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Draws a line of text and fg as color, it is usually used in the render loop
|
--- Draws a line of text and fg as color, it is usually used in the render loop
|
||||||
|
--- @shortDescription Draws a line of text and fg as color
|
||||||
--- @param x number The x position to draw the text
|
--- @param x number The x position to draw the text
|
||||||
--- @param y number The y position to draw the text
|
--- @param y number The y position to draw the text
|
||||||
--- @param text string The text to draw
|
--- @param text string The text to draw
|
||||||
@@ -418,6 +441,7 @@ function Container:textFg(x, y, text, fg)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Draws a line of text and fg and bg as colors, it is usually used in the render loop
|
--- Draws a line of text and fg and bg as colors, it is usually used in the render loop
|
||||||
|
--- @shortDescription Draws a line of text and fg and bg as colors
|
||||||
--- @param x number The x position to draw the text
|
--- @param x number The x position to draw the text
|
||||||
--- @param y number The y position to draw the text
|
--- @param y number The y position to draw the text
|
||||||
--- @param text string The text to draw
|
--- @param text string The text to draw
|
||||||
@@ -445,6 +469,7 @@ function Container:blit(x, y, text, fg, bg)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Renders the container
|
--- Renders the container
|
||||||
|
--- @shortDescription Renders the container
|
||||||
function Container:render()
|
function Container:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
if not self.get("childrenSorted")then
|
if not self.get("childrenSorted")then
|
||||||
@@ -464,6 +489,9 @@ function Container:render()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Destroys the container and its children
|
||||||
|
--- @shortDescription Destroys the container and its children
|
||||||
|
--- @return Container self The container instance
|
||||||
function Container:destroy()
|
function Container:destroy()
|
||||||
for _, child in ipairs(self._values.children) do
|
for _, child in ipairs(self._values.children) do
|
||||||
child:destroy()
|
child:destroy()
|
||||||
|
|||||||
@@ -2,15 +2,24 @@ local VisualElement = require("elements/VisualElement")
|
|||||||
local List = require("elements/List")
|
local List = require("elements/List")
|
||||||
local tHex = require("libraries/colorHex")
|
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
|
---@class Dropdown : List
|
||||||
local Dropdown = setmetatable({}, List)
|
local Dropdown = setmetatable({}, List)
|
||||||
Dropdown.__index = Dropdown
|
Dropdown.__index = Dropdown
|
||||||
|
|
||||||
|
---@property isOpen boolean false Whether the dropdown menu is currently open
|
||||||
Dropdown.defineProperty(Dropdown, "isOpen", {default = false, type = "boolean", canTriggerRender = true})
|
Dropdown.defineProperty(Dropdown, "isOpen", {default = false, type = "boolean", canTriggerRender = true})
|
||||||
|
---@property dropdownHeight number 5 Maximum height of the dropdown menu when open
|
||||||
Dropdown.defineProperty(Dropdown, "dropdownHeight", {default = 5, type = "number"})
|
Dropdown.defineProperty(Dropdown, "dropdownHeight", {default = 5, type = "number"})
|
||||||
|
---@property selectedText string "" The text to show when no item is selected
|
||||||
Dropdown.defineProperty(Dropdown, "selectedText", {default = "", type = "string"})
|
Dropdown.defineProperty(Dropdown, "selectedText", {default = "", type = "string"})
|
||||||
Dropdown.defineProperty(Dropdown, "dropSymbol", {default = "\31", type = "string"}) -- ▼ Symbol
|
---@property dropSymbol string "\31" The symbol to show for dropdown indication
|
||||||
|
Dropdown.defineProperty(Dropdown, "dropSymbol", {default = "\31", type = "string"})
|
||||||
|
|
||||||
|
--- Creates a new Dropdown instance
|
||||||
|
--- @shortDescription Creates a new Dropdown instance
|
||||||
|
--- @return Dropdown self The newly created Dropdown instance
|
||||||
|
--- @usage local dropdown = Dropdown.new()
|
||||||
function Dropdown.new()
|
function Dropdown.new()
|
||||||
local self = setmetatable({}, Dropdown):__init()
|
local self = setmetatable({}, Dropdown):__init()
|
||||||
self.set("width", 16)
|
self.set("width", 16)
|
||||||
@@ -19,17 +28,29 @@ function Dropdown.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the Dropdown instance
|
||||||
|
--- @shortDescription Initializes the Dropdown instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return Dropdown self The initialized instance
|
||||||
function Dropdown:init(props, basalt)
|
function Dropdown:init(props, basalt)
|
||||||
List.init(self, props, basalt)
|
List.init(self, props, basalt)
|
||||||
self.set("type", "Dropdown")
|
self.set("type", "Dropdown")
|
||||||
|
return self
|
||||||
end
|
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 Dropdown:mouse_click(button, x, y)
|
function Dropdown:mouse_click(button, x, y)
|
||||||
if not VisualElement.mouse_click(self, button, x, y) then return false end
|
if not VisualElement.mouse_click(self, button, x, y) then return false end
|
||||||
|
|
||||||
local relX, relY = self:getRelativePosition(x, y)
|
local relX, relY = self:getRelativePosition(x, y)
|
||||||
|
|
||||||
if relY == 1 then -- Klick auf Header
|
if relY == 1 then
|
||||||
self.set("isOpen", not self.get("isOpen"))
|
self.set("isOpen", not self.get("isOpen"))
|
||||||
if not self.get("isOpen") then
|
if not self.get("isOpen") then
|
||||||
self.set("height", 1)
|
self.set("height", 1)
|
||||||
@@ -38,7 +59,6 @@ function Dropdown:mouse_click(button, x, y)
|
|||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
elseif self.get("isOpen") and relY > 1 then
|
elseif self.get("isOpen") and relY > 1 then
|
||||||
-- Offset für die Liste korrigieren (relY - 1 wegen Header)
|
|
||||||
local index = relY - 1 + self.get("offset")
|
local index = relY - 1 + self.get("offset")
|
||||||
local items = self.get("items")
|
local items = self.get("items")
|
||||||
|
|
||||||
@@ -63,10 +83,11 @@ function Dropdown:mouse_click(button, x, y)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the Dropdown
|
||||||
|
--- @shortDescription Renders the Dropdown
|
||||||
function Dropdown:render()
|
function Dropdown:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
|
|
||||||
-- Header rendern
|
|
||||||
local text = self.get("selectedText")
|
local text = self.get("selectedText")
|
||||||
if #text == 0 and self.get("selectedIndex") > 0 then
|
if #text == 0 and self.get("selectedIndex") > 0 then
|
||||||
local item = self.get("items")[self.get("selectedIndex")]
|
local item = self.get("items")[self.get("selectedIndex")]
|
||||||
@@ -77,16 +98,14 @@ function Dropdown:render()
|
|||||||
string.rep(tHex[self.get("foreground")], self.get("width")),
|
string.rep(tHex[self.get("foreground")], self.get("width")),
|
||||||
string.rep(tHex[self.get("background")], self.get("width")))
|
string.rep(tHex[self.get("background")], self.get("width")))
|
||||||
|
|
||||||
-- Items nur rendern wenn offen
|
|
||||||
if self.get("isOpen") then
|
if self.get("isOpen") then
|
||||||
local items = self.get("items")
|
local items = self.get("items")
|
||||||
local offset = self.get("offset")
|
local offset = self.get("offset")
|
||||||
local selected = self.get("selectedIndex")
|
local selected = self.get("selectedIndex")
|
||||||
local width = self.get("width")
|
local width = self.get("width")
|
||||||
|
|
||||||
-- Liste ab Zeile 2 rendern (unterhalb des Headers)
|
|
||||||
for i = 2, self.get("height") do
|
for i = 2, self.get("height") do
|
||||||
local itemIndex = i - 1 + offset -- -1 wegen Header
|
local itemIndex = i - 1 + offset
|
||||||
local item = items[itemIndex]
|
local item = items[itemIndex]
|
||||||
|
|
||||||
if item then
|
if item then
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
local elementManager = require("elementManager")
|
local elementManager = require("elementManager")
|
||||||
local Container = elementManager.getElement("Container")
|
local Container = elementManager.getElement("Container")
|
||||||
|
|
||||||
|
--- This is the frame class. It serves as a grouping container for other elements.
|
||||||
---@class Frame : Container
|
---@class Frame : Container
|
||||||
local Frame = setmetatable({}, Container)
|
local Frame = setmetatable({}, Container)
|
||||||
Frame.__index = Frame
|
Frame.__index = Frame
|
||||||
|
|
||||||
|
---@event onResize {width number, height number} Fired when the frame is resized
|
||||||
|
Frame.listenTo(Frame, "resize")
|
||||||
|
|
||||||
--- Creates a new Frame instance
|
--- Creates a new Frame instance
|
||||||
--- @return Frame object The newly created Frame instance
|
--- @shortDescription Creates a new Frame instance
|
||||||
--- @usage local element = Frame.new("myId", basalt)
|
--- @return Frame self The newly created Frame instance
|
||||||
|
--- @usage local frame = Frame.new()
|
||||||
function Frame.new()
|
function Frame.new()
|
||||||
local self = setmetatable({}, Frame):__init()
|
local self = setmetatable({}, Frame):__init()
|
||||||
self.set("width", 12)
|
self.set("width", 12)
|
||||||
@@ -18,9 +23,14 @@ function Frame.new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Initializes the Frame instance
|
--- Initializes the Frame instance
|
||||||
|
--- @shortDescription Initializes the Frame instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return Frame self The initialized instance
|
||||||
function Frame:init(props, basalt)
|
function Frame:init(props, basalt)
|
||||||
Container.init(self, props, basalt)
|
Container.init(self, props, basalt)
|
||||||
self.set("type", "Frame")
|
self.set("type", "Frame")
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
return Frame
|
return Frame
|
||||||
@@ -1,24 +1,27 @@
|
|||||||
local VisualElement = require("elements/VisualElement")
|
local VisualElement = require("elements/VisualElement")
|
||||||
local tHex = require("libraries/colorHex")
|
local tHex = require("libraries/colorHex")
|
||||||
|
|
||||||
|
--- 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.
|
||||||
---@class Input : VisualElement
|
---@class Input : VisualElement
|
||||||
local Input = setmetatable({}, VisualElement)
|
local Input = setmetatable({}, VisualElement)
|
||||||
Input.__index = Input
|
Input.__index = Input
|
||||||
|
|
||||||
---@property text string Input - text to be displayed
|
---@property text string - The current text content of the input
|
||||||
Input.defineProperty(Input, "text", {default = "", type = "string", canTriggerRender = true})
|
Input.defineProperty(Input, "text", {default = "", type = "string", canTriggerRender = true})
|
||||||
|
---@property cursorPos number 1 The current cursor position in the text
|
||||||
---@property cursorPos number Input - current cursor position
|
|
||||||
Input.defineProperty(Input, "cursorPos", {default = 1, type = "number"})
|
Input.defineProperty(Input, "cursorPos", {default = 1, type = "number"})
|
||||||
|
---@property viewOffset number 0 The horizontal scroll offset for viewing long text
|
||||||
---@property viewOffset number Input - offset of view
|
|
||||||
Input.defineProperty(Input, "viewOffset", {default = 0, type = "number", canTriggerRender = true})
|
Input.defineProperty(Input, "viewOffset", {default = 0, type = "number", canTriggerRender = true})
|
||||||
|
---@property maxLength number? nil Maximum length of input text (optional)
|
||||||
-- Neue Properties
|
|
||||||
Input.defineProperty(Input, "maxLength", {default = nil, type = "number"})
|
Input.defineProperty(Input, "maxLength", {default = nil, type = "number"})
|
||||||
Input.defineProperty(Input, "placeholder", {default = "asd", type = "string"})
|
---@property placeholder string ... Text to display when input is empty
|
||||||
|
Input.defineProperty(Input, "placeholder", {default = "...", type = "string"})
|
||||||
|
---@property placeholderColor color gray Color of the placeholder text
|
||||||
Input.defineProperty(Input, "placeholderColor", {default = colors.gray, type = "number"})
|
Input.defineProperty(Input, "placeholderColor", {default = colors.gray, type = "number"})
|
||||||
|
---@property focusedColor color blue Background color when input is focused
|
||||||
Input.defineProperty(Input, "focusedColor", {default = colors.blue, type = "number"})
|
Input.defineProperty(Input, "focusedColor", {default = colors.blue, type = "number"})
|
||||||
|
---@property pattern string? nil Regular expression pattern for input validation
|
||||||
Input.defineProperty(Input, "pattern", {default = nil, type = "string"})
|
Input.defineProperty(Input, "pattern", {default = nil, type = "string"})
|
||||||
|
|
||||||
Input.listenTo(Input, "mouse_click")
|
Input.listenTo(Input, "mouse_click")
|
||||||
@@ -26,6 +29,7 @@ Input.listenTo(Input, "key")
|
|||||||
Input.listenTo(Input, "char")
|
Input.listenTo(Input, "char")
|
||||||
|
|
||||||
--- Creates a new Input instance
|
--- Creates a new Input instance
|
||||||
|
--- @shortDescription Creates a new Input instance
|
||||||
--- @return Input object The newly created Input instance
|
--- @return Input object The newly created Input instance
|
||||||
--- @usage local element = Input.new("myId", basalt)
|
--- @usage local element = Input.new("myId", basalt)
|
||||||
function Input.new()
|
function Input.new()
|
||||||
@@ -35,13 +39,23 @@ function Input.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the Input instance
|
||||||
|
--- @shortDescription Initializes the Input instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return Input self The initialized instance
|
||||||
function Input:init(props, basalt)
|
function Input:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "Input")
|
self.set("type", "Input")
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles char events
|
||||||
|
--- @shortDescription Handles char events
|
||||||
|
--- @param char string The character that was typed
|
||||||
|
--- @return boolean handled Whether the event was handled
|
||||||
function Input:char(char)
|
function Input:char(char)
|
||||||
if not self.get("focused") then return end
|
if not self.get("focused") then return false end
|
||||||
local text = self.get("text")
|
local text = self.get("text")
|
||||||
local pos = self.get("cursorPos")
|
local pos = self.get("cursorPos")
|
||||||
local maxLength = self.get("maxLength")
|
local maxLength = self.get("maxLength")
|
||||||
@@ -54,10 +68,15 @@ function Input:char(char)
|
|||||||
self.set("cursorPos", pos + 1)
|
self.set("cursorPos", pos + 1)
|
||||||
self:updateRender()
|
self:updateRender()
|
||||||
self:updateViewport()
|
self:updateViewport()
|
||||||
|
return true
|
||||||
end
|
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 Input:key(key)
|
function Input:key(key)
|
||||||
if not self.get("focused") then return end
|
if not self.get("focused") then return false end
|
||||||
local pos = self.get("cursorPos")
|
local pos = self.get("cursorPos")
|
||||||
local text = self.get("text")
|
local text = self.get("text")
|
||||||
local viewOffset = self.get("viewOffset")
|
local viewOffset = self.get("viewOffset")
|
||||||
@@ -88,18 +107,29 @@ function Input:key(key)
|
|||||||
|
|
||||||
local relativePos = self.get("cursorPos") - self.get("viewOffset")
|
local relativePos = self.get("cursorPos") - self.get("viewOffset")
|
||||||
self:setCursor(relativePos, 1, true)
|
self:setCursor(relativePos, 1, true)
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles focus events
|
||||||
|
--- @shortDescription Handles focus events
|
||||||
function Input:focus()
|
function Input:focus()
|
||||||
VisualElement.focus(self)
|
VisualElement.focus(self)
|
||||||
self:updateRender()
|
self:updateRender()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles blur events
|
||||||
|
--- @shortDescription Handles blur events
|
||||||
function Input:blur()
|
function Input:blur()
|
||||||
VisualElement.blur(self)
|
VisualElement.blur(self)
|
||||||
self:updateRender()
|
self:updateRender()
|
||||||
end
|
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 Input:mouse_click(button, x, y)
|
function Input:mouse_click(button, x, y)
|
||||||
if VisualElement.mouse_click(self, button, x, y) then
|
if VisualElement.mouse_click(self, button, x, y) then
|
||||||
local relX, relY = self:getRelativePosition(x, y)
|
local relX, relY = self:getRelativePosition(x, y)
|
||||||
@@ -110,6 +140,8 @@ function Input:mouse_click(button, x, y)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Updates the input's viewport
|
||||||
|
--- @shortDescription Updates the input's viewport
|
||||||
function Input:updateViewport()
|
function Input:updateViewport()
|
||||||
local width = self.get("width")
|
local width = self.get("width")
|
||||||
local cursorPos = self.get("cursorPos")
|
local cursorPos = self.get("cursorPos")
|
||||||
@@ -128,6 +160,8 @@ function Input:updateViewport()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the input element
|
||||||
|
--- @shortDescription Renders the input element
|
||||||
function Input:render()
|
function Input:render()
|
||||||
local text = self.get("text")
|
local text = self.get("text")
|
||||||
local viewOffset = self.get("viewOffset")
|
local viewOffset = self.get("viewOffset")
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
local elementManager = require("elementManager")
|
local elementManager = require("elementManager")
|
||||||
local VisualElement = elementManager.getElement("VisualElement")
|
local VisualElement = elementManager.getElement("VisualElement")
|
||||||
|
|
||||||
|
--- This is the label class. It provides a simple text display element that automatically
|
||||||
|
--- resizes its width based on the text content.
|
||||||
---@class Label : VisualElement
|
---@class Label : VisualElement
|
||||||
local Label = setmetatable({}, VisualElement)
|
local Label = setmetatable({}, VisualElement)
|
||||||
Label.__index = Label
|
Label.__index = Label
|
||||||
|
|
||||||
---@property text string Label Label text to be displayed
|
---@property text string Label The text content to display. Can be a string or a function that returns a string
|
||||||
Label.defineProperty(Label, "text", {default = "Label", type = "string", setter = function(self, value)
|
Label.defineProperty(Label, "text", {default = "Label", type = "string", setter = function(self, value)
|
||||||
if(type(value)=="function")then value = value() end
|
if(type(value)=="function")then value = value() end
|
||||||
self.set("width", #value)
|
self.set("width", #value)
|
||||||
@@ -13,8 +15,9 @@ Label.defineProperty(Label, "text", {default = "Label", type = "string", setter
|
|||||||
end})
|
end})
|
||||||
|
|
||||||
--- Creates a new Label instance
|
--- Creates a new Label instance
|
||||||
--- @return Label object The newly created Label instance
|
--- @shortDescription Creates a new Label instance
|
||||||
--- @usage local element = Label.new("myId", basalt)
|
--- @return Label self The newly created Label instance
|
||||||
|
--- @usage local label = Label.new()
|
||||||
function Label.new()
|
function Label.new()
|
||||||
local self = setmetatable({}, Label):__init()
|
local self = setmetatable({}, Label):__init()
|
||||||
self.set("z", 3)
|
self.set("z", 3)
|
||||||
@@ -23,11 +26,19 @@ function Label.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the Label instance
|
||||||
|
--- @shortDescription Initializes the Label instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return Label self The initialized instance
|
||||||
function Label:init(props, basalt)
|
function Label:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "Label")
|
self.set("type", "Label")
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the Label
|
||||||
|
--- @shortDescription Renders the Label by drawing its text content
|
||||||
function Label:render()
|
function Label:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
local text = self.get("text")
|
local text = self.get("text")
|
||||||
|
|||||||
@@ -1,23 +1,30 @@
|
|||||||
local VisualElement = require("elements/VisualElement")
|
local VisualElement = require("elements/VisualElement")
|
||||||
|
|
||||||
|
--- This is the list class. It provides a scrollable list of selectable items with support for
|
||||||
|
--- custom item rendering, separators, and selection handling.
|
||||||
---@class List : VisualElement
|
---@class List : VisualElement
|
||||||
local List = setmetatable({}, VisualElement)
|
local List = setmetatable({}, VisualElement)
|
||||||
List.__index = List
|
List.__index = List
|
||||||
|
|
||||||
---@property items table List of items to display
|
---@property items table {} List of items to display. Items can be strings or tables with properties
|
||||||
List.defineProperty(List, "items", {default = {}, type = "table", canTriggerRender = true})
|
List.defineProperty(List, "items", {default = {}, type = "table", canTriggerRender = true})
|
||||||
---@property selectedIndex number Currently selected item index
|
---@property selectedIndex number 0 Index of the currently selected item (0 means no selection)
|
||||||
List.defineProperty(List, "selectedIndex", {default = 0, type = "number", canTriggerRender = true})
|
List.defineProperty(List, "selectedIndex", {default = 0, type = "number", canTriggerRender = true})
|
||||||
---@property selectable boolean Whether items can be selected
|
---@property selectable boolean true Whether items in the list can be selected
|
||||||
List.defineProperty(List, "selectable", {default = true, type = "boolean"})
|
List.defineProperty(List, "selectable", {default = true, type = "boolean"})
|
||||||
---@property offset number Scrolling offset
|
---@property offset number 0 Current scroll offset for viewing long lists
|
||||||
List.defineProperty(List, "offset", {default = 0, type = "number", canTriggerRender = true})
|
List.defineProperty(List, "offset", {default = 0, type = "number", canTriggerRender = true})
|
||||||
---@property selectedColor color Color for selected item
|
---@property selectedColor color blue Background color for the selected item
|
||||||
List.defineProperty(List, "selectedColor", {default = colors.blue, type = "number"})
|
List.defineProperty(List, "selectedColor", {default = colors.blue, type = "number"})
|
||||||
|
|
||||||
|
---@event onSelect {index number, item any} Fired when an item is selected
|
||||||
List.listenTo(List, "mouse_click")
|
List.listenTo(List, "mouse_click")
|
||||||
List.listenTo(List, "mouse_scroll")
|
List.listenTo(List, "mouse_scroll")
|
||||||
|
|
||||||
|
--- Creates a new List instance
|
||||||
|
--- @shortDescription Creates a new List instance
|
||||||
|
--- @return List self The newly created List instance
|
||||||
|
--- @usage local list = List.new()
|
||||||
function List.new()
|
function List.new()
|
||||||
local self = setmetatable({}, List):__init()
|
local self = setmetatable({}, List):__init()
|
||||||
self.set("width", 16)
|
self.set("width", 16)
|
||||||
@@ -26,11 +33,22 @@ function List.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the List instance
|
||||||
|
--- @shortDescription Initializes the List instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return List self The initialized instance
|
||||||
function List:init(props, basalt)
|
function List:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "List")
|
self.set("type", "List")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Adds an item to the list
|
||||||
|
--- @shortDescription Adds an item to the list
|
||||||
|
--- @param text string|table The item to add (string or item table)
|
||||||
|
--- @return List self The List instance
|
||||||
|
--- @usage list:addItem("New Item")
|
||||||
|
--- @usage list:addItem({text="Item", callback=function() end})
|
||||||
function List:addItem(text)
|
function List:addItem(text)
|
||||||
local items = self.get("items")
|
local items = self.get("items")
|
||||||
table.insert(items, text)
|
table.insert(items, text)
|
||||||
@@ -38,6 +56,11 @@ function List:addItem(text)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Removes an item from the list
|
||||||
|
--- @shortDescription Removes an item from the list
|
||||||
|
--- @param index number The index of the item to remove
|
||||||
|
--- @return List self The List instance
|
||||||
|
--- @usage list:removeItem(1)
|
||||||
function List:removeItem(index)
|
function List:removeItem(index)
|
||||||
local items = self.get("items")
|
local items = self.get("items")
|
||||||
table.remove(items, index)
|
table.remove(items, index)
|
||||||
@@ -45,6 +68,10 @@ function List:removeItem(index)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Clears all items from the list
|
||||||
|
--- @shortDescription Clears all items from the list
|
||||||
|
--- @return List self The List instance
|
||||||
|
--- @usage list:clear()
|
||||||
function List:clear()
|
function List:clear()
|
||||||
self.set("items", {})
|
self.set("items", {})
|
||||||
self.set("selectedIndex", 0)
|
self.set("selectedIndex", 0)
|
||||||
@@ -52,6 +79,12 @@ function List:clear()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles mouse click events
|
||||||
|
--- @shortDescription Handles mouse click events
|
||||||
|
--- @param button number The mouse button that was clicked
|
||||||
|
--- @param x number The x-coordinate of the click
|
||||||
|
--- @param y number The y-coordinate of the click
|
||||||
|
--- @return boolean Whether the event was handled
|
||||||
function List:mouse_click(button, x, y)
|
function List:mouse_click(button, x, y)
|
||||||
if button == 1 and self:isInBounds(x, y) and self.get("selectable") then
|
if button == 1 and self:isInBounds(x, y) and self.get("selectable") then
|
||||||
local _, index = self:getRelativePosition(x, y)
|
local _, index = self:getRelativePosition(x, y)
|
||||||
@@ -75,6 +108,12 @@ function List:mouse_click(button, x, y)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles mouse scroll events
|
||||||
|
--- @shortDescription Handles mouse scroll events
|
||||||
|
--- @param direction number The direction of the scroll (1 for down, -1 for up)
|
||||||
|
--- @param x number The x-coordinate of the scroll
|
||||||
|
--- @param y number The y-coordinate of the scroll
|
||||||
|
--- @return boolean Whether the event was handled
|
||||||
function List:mouse_scroll(direction, x, y)
|
function List:mouse_scroll(direction, x, y)
|
||||||
if self:isInBounds(x, y) then
|
if self:isInBounds(x, y) then
|
||||||
local offset = self.get("offset")
|
local offset = self.get("offset")
|
||||||
@@ -84,13 +123,21 @@ function List:mouse_scroll(direction, x, y)
|
|||||||
self.set("offset", offset)
|
self.set("offset", offset)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Registers a callback for the select event
|
||||||
|
--- @shortDescription Registers a callback for the select event
|
||||||
|
--- @param callback function The callback function to register
|
||||||
|
--- @return List self The List instance
|
||||||
|
--- @usage list:onSelect(function(index, item) print("Selected item:", index, item) end)
|
||||||
function List:onSelect(callback)
|
function List:onSelect(callback)
|
||||||
self:registerCallback("select", callback)
|
self:registerCallback("select", callback)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the list
|
||||||
|
--- @shortDescription Renders the list
|
||||||
function List:render()
|
function List:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,19 @@ local VisualElement = require("elements/VisualElement")
|
|||||||
local List = require("elements/List")
|
local List = require("elements/List")
|
||||||
local tHex = require("libraries/colorHex")
|
local tHex = require("libraries/colorHex")
|
||||||
|
|
||||||
|
--- This is the menu class. It provides a horizontal menu bar with selectable items and separators.
|
||||||
|
--- Menu items are displayed in a single row and can have custom colors and callbacks.
|
||||||
---@class Menu : List
|
---@class Menu : List
|
||||||
local Menu = setmetatable({}, List)
|
local Menu = setmetatable({}, List)
|
||||||
Menu.__index = Menu
|
Menu.__index = Menu
|
||||||
|
|
||||||
|
---@property separatorColor color gray The color used for separator items in the menu
|
||||||
Menu.defineProperty(Menu, "separatorColor", {default = colors.gray, type = "number"})
|
Menu.defineProperty(Menu, "separatorColor", {default = colors.gray, type = "number"})
|
||||||
|
|
||||||
|
--- Creates a new Menu instance
|
||||||
|
--- @shortDescription Creates a new Menu instance
|
||||||
|
--- @return Menu self The newly created Menu instance
|
||||||
|
--- @usage local menu = Menu.new()
|
||||||
function Menu.new()
|
function Menu.new()
|
||||||
local self = setmetatable({}, Menu):__init()
|
local self = setmetatable({}, Menu):__init()
|
||||||
self.set("width", 30)
|
self.set("width", 30)
|
||||||
@@ -16,12 +23,22 @@ function Menu.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the Menu instance
|
||||||
|
--- @shortDescription Initializes the Menu instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return Menu self The initialized instance
|
||||||
function Menu:init(props, basalt)
|
function Menu:init(props, basalt)
|
||||||
List.init(self, props, basalt)
|
List.init(self, props, basalt)
|
||||||
self.set("type", "Menu")
|
self.set("type", "Menu")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Sets the menu items
|
||||||
|
--- @shortDescription Sets the menu items and calculates total width
|
||||||
|
--- @param items table[] List of items with {text, separator, callback, foreground, background} properties
|
||||||
|
--- @return Menu self The Menu instance
|
||||||
|
--- @usage menu:setItems({{text="File"}, {separator=true}, {text="Edit"}})
|
||||||
function Menu:setItems(items)
|
function Menu:setItems(items)
|
||||||
local listItems = {}
|
local listItems = {}
|
||||||
local totalWidth = 0
|
local totalWidth = 0
|
||||||
@@ -40,6 +57,8 @@ function Menu:setItems(items)
|
|||||||
return List.setItems(self, listItems)
|
return List.setItems(self, listItems)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the menu
|
||||||
|
--- @shortDescription Renders the menu horizontally with proper spacing and colors
|
||||||
function Menu:render()
|
function Menu:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
local currentX = 1
|
local currentX = 1
|
||||||
@@ -63,6 +82,12 @@ function Menu:render()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles mouse click events
|
||||||
|
--- @shortDescription Handles mouse click events and item selection
|
||||||
|
--- @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 Whether the event was handled
|
||||||
function Menu:mouse_click(button, x, y)
|
function Menu:mouse_click(button, x, y)
|
||||||
if not VisualElement.mouse_click(self, button, x, y) then return false end
|
if not VisualElement.mouse_click(self, button, x, y) then return false end
|
||||||
if(self.get("selectable") == false) then return false end
|
if(self.get("selectable") == false) then return false end
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
local VisualElement = require("elements/VisualElement")
|
local VisualElement = require("elements/VisualElement")
|
||||||
|
|
||||||
|
--- This is the progress bar class. It provides a visual representation of progress
|
||||||
|
--- with optional percentage display and customizable colors.
|
||||||
---@class ProgressBar : VisualElement
|
---@class ProgressBar : VisualElement
|
||||||
local ProgressBar = setmetatable({}, VisualElement)
|
local ProgressBar = setmetatable({}, VisualElement)
|
||||||
ProgressBar.__index = ProgressBar
|
ProgressBar.__index = ProgressBar
|
||||||
|
|
||||||
---@property progress number Current progress (0-100)
|
---@property progress number 0 Current progress value (0-100)
|
||||||
ProgressBar.defineProperty(ProgressBar, "progress", {default = 0, type = "number", canTriggerRender = true})
|
ProgressBar.defineProperty(ProgressBar, "progress", {default = 0, type = "number", canTriggerRender = true})
|
||||||
---@property showPercentage boolean Show percentage text
|
---@property showPercentage boolean false Whether to show the percentage text in the center
|
||||||
ProgressBar.defineProperty(ProgressBar, "showPercentage", {default = false, type = "boolean"})
|
ProgressBar.defineProperty(ProgressBar, "showPercentage", {default = false, type = "boolean"})
|
||||||
---@property progressColor color Progress bar color
|
---@property progressColor color lime The color used for the filled portion of the progress bar
|
||||||
ProgressBar.defineProperty(ProgressBar, "progressColor", {default = colors.lime, type = "number"})
|
ProgressBar.defineProperty(ProgressBar, "progressColor", {default = colors.lime, type = "number"})
|
||||||
|
|
||||||
|
--- Creates a new ProgressBar instance
|
||||||
|
--- @shortDescription Creates a new ProgressBar instance
|
||||||
|
--- @return ProgressBar self The newly created ProgressBar instance
|
||||||
|
--- @usage local progressBar = ProgressBar.new()
|
||||||
function ProgressBar.new()
|
function ProgressBar.new()
|
||||||
local self = setmetatable({}, ProgressBar):__init()
|
local self = setmetatable({}, ProgressBar):__init()
|
||||||
self.set("width", 10)
|
self.set("width", 10)
|
||||||
@@ -18,11 +24,18 @@ function ProgressBar.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the ProgressBar instance
|
||||||
|
--- @shortDescription Initializes the ProgressBar instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return ProgressBar self The initialized instance
|
||||||
function ProgressBar:init(props, basalt)
|
function ProgressBar:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "ProgressBar")
|
self.set("type", "ProgressBar")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the ProgressBar
|
||||||
|
--- @shortDescription Renders the progress bar with filled portion and optional percentage text
|
||||||
function ProgressBar:render()
|
function ProgressBar:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
local width = self.get("width")
|
local width = self.get("width")
|
||||||
|
|||||||
@@ -1,24 +1,31 @@
|
|||||||
local VisualElement = require("elements/VisualElement")
|
local VisualElement = require("elements/VisualElement")
|
||||||
|
|
||||||
|
--- This is the slider class. It provides a draggable slider control that can be either horizontal or vertical,
|
||||||
|
--- with customizable colors and value ranges.
|
||||||
---@class Slider : VisualElement
|
---@class Slider : VisualElement
|
||||||
local Slider = setmetatable({}, VisualElement)
|
local Slider = setmetatable({}, VisualElement)
|
||||||
Slider.__index = Slider
|
Slider.__index = Slider
|
||||||
|
|
||||||
---@property step number 1 Current step position (1 to width/height)
|
---@property step number 1 Current position of the slider handle (1 to width/height)
|
||||||
Slider.defineProperty(Slider, "step", {default = 1, type = "number", canTriggerRender = true})
|
Slider.defineProperty(Slider, "step", {default = 1, type = "number", canTriggerRender = true})
|
||||||
---@property max number 100 Maximum value for value conversion
|
---@property max number 100 Maximum value for value conversion (maps slider position to this range)
|
||||||
Slider.defineProperty(Slider, "max", {default = 100, type = "number"})
|
Slider.defineProperty(Slider, "max", {default = 100, type = "number"})
|
||||||
---@property horizontal boolean true Whether the slider is horizontal
|
---@property horizontal boolean true Whether the slider is horizontal (false for vertical)
|
||||||
Slider.defineProperty(Slider, "horizontal", {default = true, type = "boolean", canTriggerRender = true})
|
Slider.defineProperty(Slider, "horizontal", {default = true, type = "boolean", canTriggerRender = true})
|
||||||
---@property barColor color color Colors for the slider bar
|
---@property barColor color gray Color of the slider track
|
||||||
Slider.defineProperty(Slider, "barColor", {default = colors.gray, type = "number", canTriggerRender = true})
|
Slider.defineProperty(Slider, "barColor", {default = colors.gray, type = "number", canTriggerRender = true})
|
||||||
---@property sliderColor color The color of the slider handle
|
---@property sliderColor color blue Color of the slider handle
|
||||||
Slider.defineProperty(Slider, "sliderColor", {default = colors.blue, type = "number", canTriggerRender = true})
|
Slider.defineProperty(Slider, "sliderColor", {default = colors.blue, type = "number", canTriggerRender = true})
|
||||||
|
|
||||||
|
---@event onChange {value number} Fired when the slider value changes
|
||||||
Slider.listenTo(Slider, "mouse_click")
|
Slider.listenTo(Slider, "mouse_click")
|
||||||
Slider.listenTo(Slider, "mouse_drag")
|
Slider.listenTo(Slider, "mouse_drag")
|
||||||
Slider.listenTo(Slider, "mouse_up")
|
Slider.listenTo(Slider, "mouse_up")
|
||||||
|
|
||||||
|
--- Creates a new Slider instance
|
||||||
|
--- @shortDescription Creates a new Slider instance
|
||||||
|
--- @return Slider self The newly created Slider instance
|
||||||
|
--- @usage local slider = Slider.new()
|
||||||
function Slider.new()
|
function Slider.new()
|
||||||
local self = setmetatable({}, Slider):__init()
|
local self = setmetatable({}, Slider):__init()
|
||||||
self.set("width", 8)
|
self.set("width", 8)
|
||||||
@@ -27,11 +34,20 @@ function Slider.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the Slider instance
|
||||||
|
--- @shortDescription Initializes the Slider instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return Slider self The initialized instance
|
||||||
function Slider:init(props, basalt)
|
function Slider:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "Slider")
|
self.set("type", "Slider")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the current value of the slider
|
||||||
|
--- @shortDescription Gets the current value mapped to the max range
|
||||||
|
--- @return number value The current value (0 to max)
|
||||||
|
--- @usage local value = slider:getValue()
|
||||||
function Slider:getValue()
|
function Slider:getValue()
|
||||||
local step = self.get("step")
|
local step = self.get("step")
|
||||||
local max = self.get("max")
|
local max = self.get("max")
|
||||||
@@ -39,6 +55,12 @@ function Slider:getValue()
|
|||||||
return math.floor((step - 1) * (max / (maxSteps - 1)))
|
return math.floor((step - 1) * (max / (maxSteps - 1)))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles mouse click events
|
||||||
|
--- @shortDescription Updates slider position on mouse click
|
||||||
|
--- @param button number The mouse 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 Slider:mouse_click(button, x, y)
|
function Slider:mouse_click(button, x, y)
|
||||||
if button == 1 and self:isInBounds(x, y) then
|
if button == 1 and self:isInBounds(x, y) then
|
||||||
local relX, relY = self:getRelativePosition(x, y)
|
local relX, relY = self:getRelativePosition(x, y)
|
||||||
@@ -62,6 +84,8 @@ function Slider:mouse_scroll(direction, x, y)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the slider
|
||||||
|
--- @shortDescription Renders the slider with track and handle
|
||||||
function Slider:render()
|
function Slider:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
local width = self.get("width")
|
local width = self.get("width")
|
||||||
|
|||||||
@@ -1,23 +1,38 @@
|
|||||||
local VisualElement = require("elements/VisualElement")
|
local VisualElement = require("elements/VisualElement")
|
||||||
local tHex = require("libraries/colorHex")
|
local tHex = require("libraries/colorHex")
|
||||||
|
|
||||||
|
--- This is the table class. It provides a sortable data grid with customizable columns,
|
||||||
|
--- row selection, and scrolling capabilities.
|
||||||
---@class Table : VisualElement
|
---@class Table : VisualElement
|
||||||
local Table = setmetatable({}, VisualElement)
|
local Table = setmetatable({}, VisualElement)
|
||||||
Table.__index = Table
|
Table.__index = Table
|
||||||
|
|
||||||
|
---@property columns table {} List of column definitions with {name, width} properties
|
||||||
Table.defineProperty(Table, "columns", {default = {}, type = "table"})
|
Table.defineProperty(Table, "columns", {default = {}, type = "table"})
|
||||||
|
---@property data table {} The table data as array of row arrays
|
||||||
Table.defineProperty(Table, "data", {default = {}, type = "table", canTriggerRender = true})
|
Table.defineProperty(Table, "data", {default = {}, type = "table", canTriggerRender = true})
|
||||||
|
---@property selectedRow number? nil Currently selected row index
|
||||||
Table.defineProperty(Table, "selectedRow", {default = nil, type = "number", canTriggerRender = true})
|
Table.defineProperty(Table, "selectedRow", {default = nil, type = "number", canTriggerRender = true})
|
||||||
|
---@property headerColor color blue Color of the column headers
|
||||||
Table.defineProperty(Table, "headerColor", {default = colors.blue, type = "number"})
|
Table.defineProperty(Table, "headerColor", {default = colors.blue, type = "number"})
|
||||||
|
---@property selectedColor color lightBlue Background color of selected row
|
||||||
Table.defineProperty(Table, "selectedColor", {default = colors.lightBlue, type = "number"})
|
Table.defineProperty(Table, "selectedColor", {default = colors.lightBlue, type = "number"})
|
||||||
|
---@property gridColor color gray Color of grid lines
|
||||||
Table.defineProperty(Table, "gridColor", {default = colors.gray, type = "number"})
|
Table.defineProperty(Table, "gridColor", {default = colors.gray, type = "number"})
|
||||||
|
---@property sortColumn number? nil Currently sorted column index
|
||||||
Table.defineProperty(Table, "sortColumn", {default = nil, type = "number"})
|
Table.defineProperty(Table, "sortColumn", {default = nil, type = "number"})
|
||||||
|
---@property sortDirection string "asc" Sort direction ("asc" or "desc")
|
||||||
Table.defineProperty(Table, "sortDirection", {default = "asc", type = "string"})
|
Table.defineProperty(Table, "sortDirection", {default = "asc", type = "string"})
|
||||||
|
---@property scrollOffset number 0 Current scroll position
|
||||||
Table.defineProperty(Table, "scrollOffset", {default = 0, type = "number", canTriggerRender = true})
|
Table.defineProperty(Table, "scrollOffset", {default = 0, type = "number", canTriggerRender = true})
|
||||||
|
|
||||||
Table.listenTo(Table, "mouse_click")
|
Table.listenTo(Table, "mouse_click")
|
||||||
Table.listenTo(Table, "mouse_scroll")
|
Table.listenTo(Table, "mouse_scroll")
|
||||||
|
|
||||||
|
--- Creates a new Table instance
|
||||||
|
--- @shortDescription Creates a new Table instance
|
||||||
|
--- @return Table self The newly created Table instance
|
||||||
|
--- @usage local table = Table.new()
|
||||||
function Table.new()
|
function Table.new()
|
||||||
local self = setmetatable({}, Table):__init()
|
local self = setmetatable({}, Table):__init()
|
||||||
self.set("width", 30)
|
self.set("width", 30)
|
||||||
@@ -26,24 +41,43 @@ function Table.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the Table instance
|
||||||
|
--- @shortDescription Initializes the Table instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return Table self The initialized instance
|
||||||
function Table:init(props, basalt)
|
function Table:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "Table")
|
self.set("type", "Table")
|
||||||
return self
|
return self
|
||||||
end
|
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)
|
function Table:setColumns(columns)
|
||||||
-- Columns Format: {{name="ID", width=4}, {name="Name", width=10}}
|
-- Columns Format: {{name="ID", width=4}, {name="Name", width=10}}
|
||||||
self.set("columns", columns)
|
self.set("columns", columns)
|
||||||
return self
|
return self
|
||||||
end
|
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)
|
function Table:setData(data)
|
||||||
-- Data Format: {{"1", "Item One"}, {"2", "Item Two"}}
|
-- Data Format: {{"1", "Item One"}, {"2", "Item Two"}}
|
||||||
self.set("data", data)
|
self.set("data", data)
|
||||||
return self
|
return self
|
||||||
end
|
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
|
||||||
|
--- @return Table self The Table instance
|
||||||
function Table:sortData(columnIndex)
|
function Table:sortData(columnIndex)
|
||||||
local data = self.get("data")
|
local data = self.get("data")
|
||||||
local direction = self.get("sortDirection")
|
local direction = self.get("sortDirection")
|
||||||
@@ -60,6 +94,12 @@ function Table:sortData(columnIndex)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles mouse click events
|
||||||
|
--- @shortDescription Handles header clicks for sorting and row selection
|
||||||
|
--- @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 Table:mouse_click(button, x, y)
|
function Table:mouse_click(button, x, y)
|
||||||
if not VisualElement.mouse_click(self, button, x, y) then return false end
|
if not VisualElement.mouse_click(self, button, x, y) then return false end
|
||||||
|
|
||||||
@@ -92,6 +132,12 @@ function Table:mouse_click(button, x, y)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles mouse scroll events
|
||||||
|
--- @shortDescription Handles scrolling through the table data
|
||||||
|
--- @param direction number The scroll direction (-1 up, 1 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 Table:mouse_scroll(direction, x, y)
|
function Table:mouse_scroll(direction, x, y)
|
||||||
local data = self.get("data")
|
local data = self.get("data")
|
||||||
local height = self.get("height")
|
local height = self.get("height")
|
||||||
@@ -103,6 +149,8 @@ function Table:mouse_scroll(direction, x, y)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Renders the table
|
||||||
|
--- @shortDescription Renders the table with headers, data and scrollbar
|
||||||
function Table:render()
|
function Table:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
|
|
||||||
|
|||||||
252
src/elements/TextBox.lua
Normal file
252
src/elements/TextBox.lua
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
local VisualElement = require("elements/VisualElement")
|
||||||
|
local tHex = require("libraries/colorHex")
|
||||||
|
|
||||||
|
---A multi-line text editor component with cursor support and text manipulation features
|
||||||
|
---@class TextBox : VisualElement
|
||||||
|
local TextBox = setmetatable({}, VisualElement)
|
||||||
|
TextBox.__index = TextBox
|
||||||
|
|
||||||
|
---@property lines table {} Array of text lines
|
||||||
|
TextBox.defineProperty(TextBox, "lines", {default = {""}, type = "table", canTriggerRender = true})
|
||||||
|
---@property cursorX number 1 Cursor X position
|
||||||
|
TextBox.defineProperty(TextBox, "cursorX", {default = 1, type = "number"})
|
||||||
|
---@property cursorY number 1 Cursor Y position (line number)
|
||||||
|
TextBox.defineProperty(TextBox, "cursorY", {default = 1, type = "number"})
|
||||||
|
---@property scrollX number 0 Horizontal scroll offset
|
||||||
|
TextBox.defineProperty(TextBox, "scrollX", {default = 0, type = "number", canTriggerRender = true})
|
||||||
|
---@property scrollY number 0 Vertical scroll offset
|
||||||
|
TextBox.defineProperty(TextBox, "scrollY", {default = 0, type = "number", canTriggerRender = true})
|
||||||
|
---@property editable boolean true Whether text can be edited
|
||||||
|
TextBox.defineProperty(TextBox, "editable", {default = true, type = "boolean"})
|
||||||
|
---@property syntaxPatterns table {} Syntax highlighting patterns
|
||||||
|
TextBox.defineProperty(TextBox, "syntaxPatterns", {default = {}, type = "table"})
|
||||||
|
|
||||||
|
TextBox.listenTo(TextBox, "mouse_click")
|
||||||
|
TextBox.listenTo(TextBox, "key")
|
||||||
|
TextBox.listenTo(TextBox, "char")
|
||||||
|
TextBox.listenTo(TextBox, "mouse_scroll")
|
||||||
|
|
||||||
|
function TextBox.new()
|
||||||
|
local self = setmetatable({}, TextBox):__init()
|
||||||
|
self.set("width", 20)
|
||||||
|
self.set("height", 10)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:init(props, basalt)
|
||||||
|
VisualElement.init(self, props, basalt)
|
||||||
|
self.set("type", "TextBox")
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Adds a new syntax highlighting pattern
|
||||||
|
--- @param pattern string The regex pattern to match
|
||||||
|
--- @param color color The color to apply
|
||||||
|
function TextBox:addSyntaxPattern(pattern, color)
|
||||||
|
table.insert(self.get("syntaxPatterns"), {pattern = pattern, color = color})
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
local function insertChar(self, char)
|
||||||
|
local lines = self.get("lines")
|
||||||
|
local cursorX = self.get("cursorX")
|
||||||
|
local cursorY = self.get("cursorY")
|
||||||
|
local currentLine = lines[cursorY]
|
||||||
|
lines[cursorY] = currentLine:sub(1, cursorX-1) .. char .. currentLine:sub(cursorX)
|
||||||
|
self.set("cursorX", cursorX + 1)
|
||||||
|
self:updateViewport()
|
||||||
|
self:updateRender()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function newLine(self)
|
||||||
|
local lines = self.get("lines")
|
||||||
|
local cursorX = self.get("cursorX")
|
||||||
|
local cursorY = self.get("cursorY")
|
||||||
|
local currentLine = lines[cursorY]
|
||||||
|
|
||||||
|
local restOfLine = currentLine:sub(cursorX)
|
||||||
|
lines[cursorY] = currentLine:sub(1, cursorX-1)
|
||||||
|
table.insert(lines, cursorY + 1, restOfLine)
|
||||||
|
|
||||||
|
self.set("cursorX", 1)
|
||||||
|
self.set("cursorY", cursorY + 1)
|
||||||
|
self:updateViewport()
|
||||||
|
self:updateRender()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function backspace(self)
|
||||||
|
local lines = self.get("lines")
|
||||||
|
local cursorX = self.get("cursorX")
|
||||||
|
local cursorY = self.get("cursorY")
|
||||||
|
local currentLine = lines[cursorY]
|
||||||
|
|
||||||
|
if cursorX > 1 then
|
||||||
|
lines[cursorY] = currentLine:sub(1, cursorX-2) .. currentLine:sub(cursorX)
|
||||||
|
self.set("cursorX", cursorX - 1)
|
||||||
|
elseif cursorY > 1 then
|
||||||
|
local previousLine = lines[cursorY-1]
|
||||||
|
self.set("cursorX", #previousLine + 1)
|
||||||
|
self.set("cursorY", cursorY - 1)
|
||||||
|
lines[cursorY-1] = previousLine .. currentLine
|
||||||
|
table.remove(lines, cursorY)
|
||||||
|
end
|
||||||
|
self:updateViewport()
|
||||||
|
self:updateRender()
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:updateViewport()
|
||||||
|
local cursorX = self.get("cursorX")
|
||||||
|
local cursorY = self.get("cursorY")
|
||||||
|
local scrollX = self.get("scrollX")
|
||||||
|
local scrollY = self.get("scrollY")
|
||||||
|
local width = self.get("width")
|
||||||
|
local height = self.get("height")
|
||||||
|
|
||||||
|
-- Horizontal scrolling
|
||||||
|
if cursorX - scrollX > width then
|
||||||
|
self.set("scrollX", cursorX - width)
|
||||||
|
elseif cursorX - scrollX < 1 then
|
||||||
|
self.set("scrollX", cursorX - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Vertical scrolling
|
||||||
|
if cursorY - scrollY > height then
|
||||||
|
self.set("scrollY", cursorY - height)
|
||||||
|
elseif cursorY - scrollY < 1 then
|
||||||
|
self.set("scrollY", cursorY - 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:char(char)
|
||||||
|
if not self.get("editable") or not self.get("focused") then return false end
|
||||||
|
insertChar(self, char)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:key(key)
|
||||||
|
if not self.get("editable") or not self.get("focused") then return false end
|
||||||
|
local lines = self.get("lines")
|
||||||
|
local cursorX = self.get("cursorX")
|
||||||
|
local cursorY = self.get("cursorY")
|
||||||
|
|
||||||
|
if key == keys.enter then
|
||||||
|
newLine(self)
|
||||||
|
elseif key == keys.backspace then
|
||||||
|
backspace(self)
|
||||||
|
elseif key == keys.left then
|
||||||
|
if cursorX > 1 then
|
||||||
|
self.set("cursorX", cursorX - 1)
|
||||||
|
elseif cursorY > 1 then
|
||||||
|
self.set("cursorY", cursorY - 1)
|
||||||
|
self.set("cursorX", #lines[cursorY-1] + 1)
|
||||||
|
end
|
||||||
|
elseif key == keys.right then
|
||||||
|
if cursorX <= #lines[cursorY] then
|
||||||
|
self.set("cursorX", cursorX + 1)
|
||||||
|
elseif cursorY < #lines then
|
||||||
|
self.set("cursorY", cursorY + 1)
|
||||||
|
self.set("cursorX", 1)
|
||||||
|
end
|
||||||
|
elseif key == keys.up and cursorY > 1 then
|
||||||
|
self.set("cursorY", cursorY - 1)
|
||||||
|
self.set("cursorX", math.min(cursorX, #lines[cursorY-1] + 1))
|
||||||
|
elseif key == keys.down and cursorY < #lines then
|
||||||
|
self.set("cursorY", cursorY + 1)
|
||||||
|
self.set("cursorX", math.min(cursorX, #lines[cursorY+1] + 1))
|
||||||
|
end
|
||||||
|
self:updateRender()
|
||||||
|
self:updateViewport()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:mouse_scroll(direction, x, y)
|
||||||
|
if self:isInBounds(x, y) then
|
||||||
|
local scrollY = self.get("scrollY")
|
||||||
|
self.set("scrollY", math.max(0, scrollY + direction))
|
||||||
|
self:updateRender()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:mouse_click(button, x, y)
|
||||||
|
if VisualElement.mouse_click(self, button, x, y) then
|
||||||
|
local relX, relY = self:getRelativePosition(x, y)
|
||||||
|
local scrollX = self.get("scrollX")
|
||||||
|
local scrollY = self.get("scrollY")
|
||||||
|
|
||||||
|
local targetY = relY + scrollY
|
||||||
|
local lines = self.get("lines")
|
||||||
|
|
||||||
|
if targetY <= #lines then
|
||||||
|
self.set("cursorY", targetY)
|
||||||
|
self.set("cursorX", math.min(relX + scrollX, #lines[targetY] + 1))
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:setText(text)
|
||||||
|
self.set("lines", {""})
|
||||||
|
for line in text:gmatch("[^\n]+") do
|
||||||
|
table.insert(self.get("lines"), line)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:getText()
|
||||||
|
return table.concat(self.get("lines"), "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
local s, e = text:find(syntax.pattern, start)
|
||||||
|
if not s then break end
|
||||||
|
colors = colors:sub(1, s-1) .. string.rep(tHex[syntax.color], e-s+1) .. colors:sub(e+1)
|
||||||
|
start = e + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return text, colors
|
||||||
|
end
|
||||||
|
|
||||||
|
function TextBox:render()
|
||||||
|
VisualElement.render(self)
|
||||||
|
|
||||||
|
local lines = self.get("lines")
|
||||||
|
local scrollX = self.get("scrollX")
|
||||||
|
local scrollY = self.get("scrollY")
|
||||||
|
local width = self.get("width")
|
||||||
|
local height = self.get("height")
|
||||||
|
local fg = tHex[self.get("foreground")]
|
||||||
|
local bg = tHex[self.get("background")]
|
||||||
|
|
||||||
|
for y = 1, height do
|
||||||
|
local lineNum = y + scrollY
|
||||||
|
local line = lines[lineNum] or ""
|
||||||
|
local visibleText = line:sub(scrollX + 1, scrollX + width)
|
||||||
|
if #visibleText < width then
|
||||||
|
visibleText = visibleText .. string.rep(" ", width - #visibleText)
|
||||||
|
end
|
||||||
|
|
||||||
|
local text, colors = applySyntaxHighlighting(self, visibleText)
|
||||||
|
self:blit(1, y, text, colors, string.rep(bg, #visibleText))
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.get("focused") then
|
||||||
|
local relativeX = self.get("cursorX") - scrollX
|
||||||
|
local relativeY = self.get("cursorY") - scrollY
|
||||||
|
if relativeX >= 1 and relativeX <= width and relativeY >= 1 and relativeY <= height then
|
||||||
|
self:setCursor(relativeX, relativeY, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return TextBox
|
||||||
@@ -1,20 +1,32 @@
|
|||||||
local VisualElement = require("elements/VisualElement")
|
local VisualElement = require("elements/VisualElement")
|
||||||
local tHex = require("libraries/colorHex")
|
local sub = string.sub
|
||||||
|
|
||||||
|
--- This is the tree class. It provides a hierarchical view of nodes that can be expanded and collapsed,
|
||||||
|
--- with support for selection and scrolling.
|
||||||
---@class Tree : VisualElement
|
---@class Tree : VisualElement
|
||||||
local Tree = setmetatable({}, VisualElement)
|
local Tree = setmetatable({}, VisualElement)
|
||||||
Tree.__index = Tree
|
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})
|
||||||
|
---@property selectedNode table? nil Currently selected node
|
||||||
Tree.defineProperty(Tree, "selectedNode", {default = nil, type = "table", canTriggerRender = true})
|
Tree.defineProperty(Tree, "selectedNode", {default = nil, type = "table", canTriggerRender = true})
|
||||||
|
---@property expandedNodes table {} Table of nodes that are currently expanded
|
||||||
Tree.defineProperty(Tree, "expandedNodes", {default = {}, type = "table", canTriggerRender = true})
|
Tree.defineProperty(Tree, "expandedNodes", {default = {}, type = "table", canTriggerRender = true})
|
||||||
|
---@property scrollOffset number 0 Current scroll position
|
||||||
Tree.defineProperty(Tree, "scrollOffset", {default = 0, type = "number", canTriggerRender = true})
|
Tree.defineProperty(Tree, "scrollOffset", {default = 0, type = "number", canTriggerRender = true})
|
||||||
|
---@property nodeColor color white Color of unselected nodes
|
||||||
Tree.defineProperty(Tree, "nodeColor", {default = colors.white, type = "number"})
|
Tree.defineProperty(Tree, "nodeColor", {default = colors.white, type = "number"})
|
||||||
|
---@property selectedColor color lightBlue Background color of selected node
|
||||||
Tree.defineProperty(Tree, "selectedColor", {default = colors.lightBlue, type = "number"})
|
Tree.defineProperty(Tree, "selectedColor", {default = colors.lightBlue, type = "number"})
|
||||||
|
|
||||||
Tree.listenTo(Tree, "mouse_click")
|
Tree.listenTo(Tree, "mouse_click")
|
||||||
Tree.listenTo(Tree, "mouse_scroll")
|
Tree.listenTo(Tree, "mouse_scroll")
|
||||||
|
|
||||||
|
--- Creates a new Tree instance
|
||||||
|
--- @shortDescription Creates a new Tree instance
|
||||||
|
--- @return Tree self The newly created Tree instance
|
||||||
|
--- @usage local tree = Tree.new()
|
||||||
function Tree.new()
|
function Tree.new()
|
||||||
local self = setmetatable({}, Tree):__init()
|
local self = setmetatable({}, Tree):__init()
|
||||||
self.set("width", 30)
|
self.set("width", 30)
|
||||||
@@ -23,12 +35,22 @@ function Tree.new()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the Tree instance
|
||||||
|
--- @shortDescription Initializes the Tree instance
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
|
--- @return Tree self The initialized instance
|
||||||
function Tree:init(props, basalt)
|
function Tree:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "Tree")
|
self.set("type", "Tree")
|
||||||
return self
|
return self
|
||||||
end
|
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)
|
function Tree:setNodes(nodes)
|
||||||
self.set("nodes", nodes)
|
self.set("nodes", nodes)
|
||||||
if #nodes > 0 then
|
if #nodes > 0 then
|
||||||
@@ -37,18 +59,30 @@ function Tree:setNodes(nodes)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Expands a node
|
||||||
|
--- @shortDescription Expands a node to show its children
|
||||||
|
--- @param node table The node to expand
|
||||||
|
--- @return Tree self The Tree instance
|
||||||
function Tree:expandNode(node)
|
function Tree:expandNode(node)
|
||||||
self.get("expandedNodes")[node] = true
|
self.get("expandedNodes")[node] = true
|
||||||
self:updateRender()
|
self:updateRender()
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Collapses a node
|
||||||
|
--- @shortDescription Collapses a node to hide its children
|
||||||
|
--- @param node table The node to collapse
|
||||||
|
--- @return Tree self The Tree instance
|
||||||
function Tree:collapseNode(node)
|
function Tree:collapseNode(node)
|
||||||
self.get("expandedNodes")[node] = nil
|
self.get("expandedNodes")[node] = nil
|
||||||
self:updateRender()
|
self:updateRender()
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Toggles a node's expanded state
|
||||||
|
--- @shortDescription Toggles between expanded and collapsed state
|
||||||
|
--- @param node table The node to toggle
|
||||||
|
--- @return Tree self The Tree instance
|
||||||
function Tree:toggleNode(node)
|
function Tree:toggleNode(node)
|
||||||
if self.get("expandedNodes")[node] then
|
if self.get("expandedNodes")[node] then
|
||||||
self:collapseNode(node)
|
self:collapseNode(node)
|
||||||
@@ -122,7 +156,6 @@ function Tree:render()
|
|||||||
local level = nodeInfo.level
|
local level = nodeInfo.level
|
||||||
local indent = string.rep(" ", level)
|
local indent = string.rep(" ", level)
|
||||||
|
|
||||||
-- Expand/Collapse Symbol
|
|
||||||
local symbol = " "
|
local symbol = " "
|
||||||
if node.children and #node.children > 0 then
|
if node.children and #node.children > 0 then
|
||||||
symbol = expandedNodes[node] and "\31" or "\16"
|
symbol = expandedNodes[node] and "\31" or "\16"
|
||||||
@@ -130,15 +163,12 @@ function Tree:render()
|
|||||||
|
|
||||||
local bg = node == selectedNode and self.get("selectedColor") or self.get("background")
|
local bg = node == selectedNode and self.get("selectedColor") or self.get("background")
|
||||||
local text = indent .. symbol .." " .. (node.text or "Node")
|
local text = indent .. symbol .." " .. (node.text or "Node")
|
||||||
|
text = sub(text, 1, self.get("width"))
|
||||||
|
|
||||||
|
self:textFg(1, y, text .. string.rep(" ", self.get("width") - #text), self.get("foreground"))
|
||||||
|
|
||||||
self:blit(1, y, text .. string.rep(" ", self.get("width") - #text),
|
|
||||||
string.rep(tHex[self.get("nodeColor")], self.get("width")),
|
|
||||||
string.rep(tHex[bg], self.get("width")))
|
|
||||||
else
|
else
|
||||||
-- Leere Zeile
|
self:textFg(1, y, string.rep(" ", self.get("width")), self.get("foreground"), self.get("background"))
|
||||||
self:blit(1, y, string.rep(" ", self.get("width")),
|
|
||||||
string.rep(tHex[self.get("foreground")], self.get("width")),
|
|
||||||
string.rep(tHex[self.get("background")], self.get("width")))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,15 +2,17 @@ local elementManager = require("elementManager")
|
|||||||
local BaseElement = elementManager.getElement("BaseElement")
|
local BaseElement = elementManager.getElement("BaseElement")
|
||||||
local tHex = require("libraries/colorHex")
|
local tHex = require("libraries/colorHex")
|
||||||
|
|
||||||
|
--- 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.
|
||||||
---@class VisualElement : BaseElement
|
---@class VisualElement : BaseElement
|
||||||
local VisualElement = setmetatable({}, BaseElement)
|
local VisualElement = setmetatable({}, BaseElement)
|
||||||
VisualElement.__index = VisualElement
|
VisualElement.__index = VisualElement
|
||||||
|
|
||||||
---@property x number 1 x position of the element
|
---@property x number 1 The horizontal position relative to parent
|
||||||
VisualElement.defineProperty(VisualElement, "x", {default = 1, type = "number", canTriggerRender = true})
|
VisualElement.defineProperty(VisualElement, "x", {default = 1, type = "number", canTriggerRender = true})
|
||||||
---@property y number 1 y position of the element
|
---@property y number 1 The vertical position relative to parent
|
||||||
VisualElement.defineProperty(VisualElement, "y", {default = 1, type = "number", canTriggerRender = true})
|
VisualElement.defineProperty(VisualElement, "y", {default = 1, type = "number", canTriggerRender = true})
|
||||||
---@property z number 1 z position of the element
|
---@property z number 1 The z-index for layering elements
|
||||||
VisualElement.defineProperty(VisualElement, "z", {default = 1, type = "number", canTriggerRender = true, setter = function(self, value)
|
VisualElement.defineProperty(VisualElement, "z", {default = 1, type = "number", canTriggerRender = true, setter = function(self, value)
|
||||||
if self.parent then
|
if self.parent then
|
||||||
self.parent:sortChildren()
|
self.parent:sortChildren()
|
||||||
@@ -18,19 +20,19 @@ VisualElement.defineProperty(VisualElement, "z", {default = 1, type = "number",
|
|||||||
return value
|
return value
|
||||||
end})
|
end})
|
||||||
|
|
||||||
---@property width number 1 width of the element
|
---@property width number 1 The width of the element
|
||||||
VisualElement.defineProperty(VisualElement, "width", {default = 1, type = "number", canTriggerRender = true})
|
VisualElement.defineProperty(VisualElement, "width", {default = 1, type = "number", canTriggerRender = true})
|
||||||
---@property height number 1 height of the element
|
---@property height number 1 The height of the element
|
||||||
VisualElement.defineProperty(VisualElement, "height", {default = 1, type = "number", canTriggerRender = true})
|
VisualElement.defineProperty(VisualElement, "height", {default = 1, type = "number", canTriggerRender = true})
|
||||||
---@property background color black background color of the element
|
---@property background color black The background color
|
||||||
VisualElement.defineProperty(VisualElement, "background", {default = colors.black, type = "number", canTriggerRender = true})
|
VisualElement.defineProperty(VisualElement, "background", {default = colors.black, type = "number", canTriggerRender = true})
|
||||||
---@property foreground color white foreground color of the element
|
---@property foreground color white The text/foreground color
|
||||||
VisualElement.defineProperty(VisualElement, "foreground", {default = colors.white, type = "number", canTriggerRender = true})
|
VisualElement.defineProperty(VisualElement, "foreground", {default = colors.white, type = "number", canTriggerRender = true})
|
||||||
---@property clicked boolean an false element is currently clicked
|
---@property clicked boolean false Whether the element is currently clicked
|
||||||
VisualElement.defineProperty(VisualElement, "clicked", {default = false, type = "boolean"})
|
VisualElement.defineProperty(VisualElement, "clicked", {default = false, type = "boolean"})
|
||||||
---@property backgroundEnabled boolean true whether the background is enabled
|
---@property backgroundEnabled boolean true Whether to render the background
|
||||||
VisualElement.defineProperty(VisualElement, "backgroundEnabled", {default = true, type = "boolean", canTriggerRender = true})
|
VisualElement.defineProperty(VisualElement, "backgroundEnabled", {default = true, type = "boolean", canTriggerRender = true})
|
||||||
---@property focused boolean false whether the element is focused
|
---@property focused boolean false Whether the element has input focus
|
||||||
VisualElement.defineProperty(VisualElement, "focused", {default = false, type = "boolean", setter = function(self, value, internal)
|
VisualElement.defineProperty(VisualElement, "focused", {default = false, type = "boolean", setter = function(self, value, internal)
|
||||||
local curValue = self.get("focused")
|
local curValue = self.get("focused")
|
||||||
if value == curValue then return value end
|
if value == curValue then return value end
|
||||||
@@ -51,7 +53,7 @@ VisualElement.defineProperty(VisualElement, "focused", {default = false, type =
|
|||||||
return value
|
return value
|
||||||
end})
|
end})
|
||||||
|
|
||||||
---@property visible boolean true whether the element is visible
|
---@property visible boolean true Whether the element is visible
|
||||||
VisualElement.defineProperty(VisualElement, "visible", {default = true, type = "boolean", canTriggerRender = true, setter=function(self, value)
|
VisualElement.defineProperty(VisualElement, "visible", {default = true, type = "boolean", canTriggerRender = true, setter=function(self, value)
|
||||||
if(self.parent~=nil)then
|
if(self.parent~=nil)then
|
||||||
self.parent.set("childrenSorted", false)
|
self.parent.set("childrenSorted", false)
|
||||||
@@ -60,23 +62,22 @@ VisualElement.defineProperty(VisualElement, "visible", {default = true, type = "
|
|||||||
return value
|
return value
|
||||||
end})
|
end})
|
||||||
|
|
||||||
---@combinedProperty position {x y} Position of the element
|
---@combinedProperty position {x y} Combined x, y position
|
||||||
VisualElement.combineProperties(VisualElement, "position", "x", "y")
|
VisualElement.combineProperties(VisualElement, "position", "x", "y")
|
||||||
---@combinedProperty size {width height} Size of the element
|
---@combinedProperty size {width height} Combined width, height
|
||||||
VisualElement.combineProperties(VisualElement, "size", "width", "height")
|
VisualElement.combineProperties(VisualElement, "size", "width", "height")
|
||||||
---@combinedProperty color {foreground background} Color of the element
|
---@combinedProperty color {foreground background} Combined foreground, background colors
|
||||||
VisualElement.combineProperties(VisualElement, "color", "foreground", "background")
|
VisualElement.combineProperties(VisualElement, "color", "foreground", "background")
|
||||||
|
|
||||||
---@event onMouseClick {button number, x number, y number} Fired when the element is clicked
|
---@event onMouseClick {button number, x number, y number} Fired on mouse click
|
||||||
---@event onMouseUp {button number, x number, y number} Fired when the mouse is released
|
---@event onMouseUp {button number, x number, y number} Fired on mouse button release
|
||||||
---@event onMouseRelease {button number, x number, y number} Fired when the mouse is released
|
---@event onMouseRelease {button number, x number, y number} Fired when mouse leaves while clicked
|
||||||
---@event onMouseDrag {button number, x number, y number} Fired when the mouse is dragged
|
---@event onMouseDrag {button number, x number, y number} Fired when mouse moves while clicked
|
||||||
---@event onFocus {-} Fired when the element is focused
|
---@event onFocus {-} Fired when element receives focus
|
||||||
---@event onBlur {-} Fired when the element is blurred
|
---@event onBlur {-} Fired when element loses focus
|
||||||
---@event onKey {key number, code number, isRepeat boolean} Fired when a key is pressed
|
---@event onKey {key number, code number, isRepeat boolean} Fired on key press
|
||||||
---@event onKeyUp {key number, code number} Fired when a key is released
|
---@event onKeyUp {key number, code number} Fired on key release
|
||||||
---@event onChar {char string} Fired when a key is pressed
|
---@event onChar {char string} Fired on character input
|
||||||
|
|
||||||
|
|
||||||
VisualElement.listenTo(VisualElement, "focus")
|
VisualElement.listenTo(VisualElement, "focus")
|
||||||
VisualElement.listenTo(VisualElement, "blur")
|
VisualElement.listenTo(VisualElement, "blur")
|
||||||
@@ -84,6 +85,7 @@ VisualElement.listenTo(VisualElement, "blur")
|
|||||||
local max, min = math.max, math.min
|
local max, min = math.max, math.min
|
||||||
|
|
||||||
--- Creates a new VisualElement instance
|
--- Creates a new VisualElement instance
|
||||||
|
--- @shortDescription Creates a new visual element
|
||||||
--- @param props table The properties to initialize the element with
|
--- @param props table The properties to initialize the element with
|
||||||
--- @param basalt table The basalt instance
|
--- @param basalt table The basalt instance
|
||||||
--- @return VisualElement object The newly created VisualElement instance
|
--- @return VisualElement object The newly created VisualElement instance
|
||||||
@@ -94,11 +96,16 @@ function VisualElement.new()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Initializes the VisualElement instance
|
--- Initializes the VisualElement instance
|
||||||
|
--- @shortDescription Initializes a new visual element with properties
|
||||||
|
--- @param props table The properties to initialize the element with
|
||||||
|
--- @param basalt table The basalt instance
|
||||||
function VisualElement:init(props, basalt)
|
function VisualElement:init(props, basalt)
|
||||||
BaseElement.init(self, props, basalt)
|
BaseElement.init(self, props, basalt)
|
||||||
self.set("type", "VisualElement")
|
self.set("type", "VisualElement")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Draws multiple characters at once with colors
|
||||||
|
--- @shortDescription Multi-character drawing with colors
|
||||||
---@protected
|
---@protected
|
||||||
function VisualElement:multiBlit(x, y, width, height, text, fg, bg)
|
function VisualElement:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
x = x + self.get("x") - 1
|
x = x + self.get("x") - 1
|
||||||
@@ -106,7 +113,8 @@ function VisualElement:multiBlit(x, y, width, height, text, fg, bg)
|
|||||||
self.parent:multiBlit(x, y, width, height, text, fg, bg)
|
self.parent:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Draws a text character at the specified position, used in the rendering system
|
--- Draws text with foreground color
|
||||||
|
--- @shortDescription Draws text with foreground color
|
||||||
--- @param x number The x position to draw
|
--- @param x number The x position to draw
|
||||||
--- @param y number The y position to draw
|
--- @param y number The y position to draw
|
||||||
--- @param text string The text char to draw
|
--- @param text string The text char to draw
|
||||||
@@ -117,7 +125,8 @@ function VisualElement:textFg(x, y, text, fg)
|
|||||||
self.parent:textFg(x, y, text, fg)
|
self.parent:textFg(x, y, text, fg)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Draws a text character with a background at the specified position, used in the rendering system
|
--- Draws text with background color
|
||||||
|
--- @shortDescription Draws text with background color
|
||||||
--- @param x number The x position to draw
|
--- @param x number The x position to draw
|
||||||
--- @param y number The y position to draw
|
--- @param y number The y position to draw
|
||||||
--- @param text string The text char to draw
|
--- @param text string The text char to draw
|
||||||
@@ -128,7 +137,8 @@ function VisualElement:textBg(x, y, text, bg)
|
|||||||
self.parent:textBg(x, y, text, bg)
|
self.parent:textBg(x, y, text, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Draws a text character with a foreground and background at the specified position, used in the rendering system
|
--- Draws text with both foreground and background colors
|
||||||
|
--- @shortDescription Draws text with both colors
|
||||||
--- @param x number The x position to draw
|
--- @param x number The x position to draw
|
||||||
--- @param y number The y position to draw
|
--- @param y number The y position to draw
|
||||||
--- @param text string The text char to draw
|
--- @param text string The text char to draw
|
||||||
@@ -141,6 +151,7 @@ function VisualElement:blit(x, y, text, fg, bg)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Checks if the specified coordinates are within the bounds of the element
|
--- Checks if the specified coordinates are within the bounds of the element
|
||||||
|
--- @shortDescription Checks if point is within bounds
|
||||||
--- @param x number The x position to check
|
--- @param x number The x position to check
|
||||||
--- @param y number The y position to check
|
--- @param y number The y position to check
|
||||||
--- @return boolean isInBounds Whether the coordinates are within the bounds of the element
|
--- @return boolean isInBounds Whether the coordinates are within the bounds of the element
|
||||||
@@ -153,6 +164,7 @@ function VisualElement:isInBounds(x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles a mouse click event
|
--- Handles a mouse click event
|
||||||
|
--- @shortDescription Handles a mouse click event
|
||||||
--- @param button number The button that was clicked
|
--- @param button number The button that was clicked
|
||||||
--- @param x number The x position of the click
|
--- @param x number The x position of the click
|
||||||
--- @param y number The y position of the click
|
--- @param y number The y position of the click
|
||||||
@@ -167,6 +179,7 @@ function VisualElement:mouse_click(button, x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles a mouse up event
|
--- Handles a mouse up event
|
||||||
|
--- @shortDescription Handles a mouse up event
|
||||||
--- @param button number The button that was released
|
--- @param button number The button that was released
|
||||||
--- @param x number The x position of the release
|
--- @param x number The x position of the release
|
||||||
--- @param y number The y position of the release
|
--- @param y number The y position of the release
|
||||||
@@ -181,6 +194,7 @@ function VisualElement:mouse_up(button, x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles a mouse release event
|
--- Handles a mouse release event
|
||||||
|
--- @shortDescription Handles a mouse release event
|
||||||
--- @param button number The button that was released
|
--- @param button number The button that was released
|
||||||
--- @param x number The x position of the release
|
--- @param x number The x position of the release
|
||||||
--- @param y number The y position of the release
|
--- @param y number The y position of the release
|
||||||
@@ -195,17 +209,20 @@ function VisualElement:mouse_release(button, x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Handles a focus event
|
--- Handles a focus event
|
||||||
|
--- @shortDescription Handles a focus event
|
||||||
function VisualElement:focus()
|
function VisualElement:focus()
|
||||||
self:fireEvent("focus")
|
self:fireEvent("focus")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Handles a blur event
|
--- Handles a blur event
|
||||||
|
--- @shortDescription Handles a blur event
|
||||||
function VisualElement:blur()
|
function VisualElement:blur()
|
||||||
self:fireEvent("blur")
|
self:fireEvent("blur")
|
||||||
self:setCursor(1,1, false)
|
self:setCursor(1,1, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the absolute position of the element or the given coordinates.
|
--- Returns the absolute position of the element or the given coordinates.
|
||||||
|
--- @shortDescription Returns the absolute position of the element
|
||||||
---@param x? number x position
|
---@param x? number x position
|
||||||
---@param y? number y position
|
---@param y? number y position
|
||||||
function VisualElement:getAbsolutePosition(x, y)
|
function VisualElement:getAbsolutePosition(x, y)
|
||||||
@@ -229,6 +246,7 @@ function VisualElement:getAbsolutePosition(x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the relative position of the element or the given coordinates.
|
--- Returns the relative position of the element or the given coordinates.
|
||||||
|
--- @shortDescription Returns the relative position of the element
|
||||||
---@param x? number x position
|
---@param x? number x position
|
||||||
---@param y? number y position
|
---@param y? number y position
|
||||||
---@return number, number
|
---@return number, number
|
||||||
@@ -250,6 +268,7 @@ function VisualElement:getRelativePosition(x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Sets the cursor position
|
--- Sets the cursor position
|
||||||
|
--- @shortDescription Sets the cursor position
|
||||||
--- @param x number The x position of the cursor
|
--- @param x number The x position of the cursor
|
||||||
--- @param y number The y position of the cursor
|
--- @param y number The y position of the cursor
|
||||||
--- @param blink boolean Whether the cursor should blink
|
--- @param blink boolean Whether the cursor should blink
|
||||||
@@ -262,6 +281,7 @@ function VisualElement:setCursor(x, y, blink)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Renders the element
|
--- Renders the element
|
||||||
|
--- @shortDescription Renders the element
|
||||||
function VisualElement:render()
|
function VisualElement:render()
|
||||||
if(not self.get("backgroundEnabled"))then
|
if(not self.get("backgroundEnabled"))then
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
local LOGGER = require("log")
|
local LOGGER = require("log")
|
||||||
|
|
||||||
|
--- This is Basalt's error handler. All the errors are handled by this module.
|
||||||
|
--- @class ErrorHandler
|
||||||
|
--- @field tracebackEnabled boolean If the error handler should print a stack trace
|
||||||
|
--- @field header string The header of the error message
|
||||||
local errorHandler = {
|
local errorHandler = {
|
||||||
tracebackEnabled = true,
|
tracebackEnabled = true,
|
||||||
header = "Basalt Error"
|
header = "Basalt Error"
|
||||||
@@ -11,6 +15,9 @@ local function coloredPrint(message, color)
|
|||||||
term.setTextColor(colors.white)
|
term.setTextColor(colors.white)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles an error
|
||||||
|
--- @param errMsg string The error message
|
||||||
|
--- @usage errorHandler.error("An error occurred")
|
||||||
function errorHandler.error(errMsg)
|
function errorHandler.error(errMsg)
|
||||||
if errorHandler.errorHandled then
|
if errorHandler.errorHandled then
|
||||||
error()
|
error()
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
--- Logger module for Basalt. Logs messages to the console and optionally to a file.
|
||||||
--- @class Log
|
--- @class Log
|
||||||
--- @field _logs table The complete log history
|
--- @field _logs table The complete log history
|
||||||
--- @field _enabled boolean If the logger is enabled
|
--- @field _enabled boolean If the logger is enabled
|
||||||
@@ -87,10 +88,9 @@ end
|
|||||||
|
|
||||||
--- Sends a debug message to the logger.
|
--- Sends a debug message to the logger.
|
||||||
--- @shortDescription Sends a debug message
|
--- @shortDescription Sends a debug message
|
||||||
|
--- @vararg string The message to log
|
||||||
--- @usage Log.debug("This is a debug message")
|
--- @usage Log.debug("This is a debug message")
|
||||||
function Log.debug(...)
|
function Log.debug(...) log(Log.LEVEL.DEBUG, ...) end
|
||||||
log(Log.LEVEL.DEBUG, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Sends an info message to the logger.
|
--- Sends an info message to the logger.
|
||||||
--- @shortDescription Sends an info message
|
--- @shortDescription Sends an info message
|
||||||
@@ -110,6 +110,4 @@ function Log.warn(...) log(Log.LEVEL.WARN, ...) end
|
|||||||
--- @usage Log.error("This is an error message")
|
--- @usage Log.error("This is an error message")
|
||||||
function Log.error(...) log(Log.LEVEL.ERROR, ...) end
|
function Log.error(...) log(Log.LEVEL.ERROR, ...) end
|
||||||
|
|
||||||
Log.info("Logger initialized")
|
|
||||||
|
|
||||||
return Log
|
return Log
|
||||||
@@ -8,7 +8,6 @@ local propertySystem = require("propertySystem")
|
|||||||
--- Before you can access Basalt, you need to add the following code on top of your file:
|
--- Before you can access Basalt, you need to add the following code on top of your file:
|
||||||
--- @usage local basalt = require("basalt")
|
--- @usage local basalt = require("basalt")
|
||||||
--- What this code does is it loads basalt into the project, and you can access it by using the variable defined as "basalt".
|
--- What this code does is it loads basalt into the project, and you can access it by using the variable defined as "basalt".
|
||||||
|
|
||||||
--- @class Basalt
|
--- @class Basalt
|
||||||
--- @field traceback boolean Whether to show a traceback on errors
|
--- @field traceback boolean Whether to show a traceback on errors
|
||||||
--- @field _events table A table of events and their callbacks
|
--- @field _events table A table of events and their callbacks
|
||||||
|
|||||||
@@ -1,22 +1,4 @@
|
|||||||
local Animation = {}
|
|
||||||
Animation.__index = Animation
|
|
||||||
|
|
||||||
local registeredAnimations = {}
|
local registeredAnimations = {}
|
||||||
|
|
||||||
function Animation.registerAnimation(name, handlers)
|
|
||||||
registeredAnimations[name] = handlers
|
|
||||||
|
|
||||||
Animation[name] = function(self, ...)
|
|
||||||
local args = {...}
|
|
||||||
local easing = "linear"
|
|
||||||
if(type(args[#args]) == "string") then
|
|
||||||
easing = table.remove(args, #args)
|
|
||||||
end
|
|
||||||
local duration = table.remove(args, #args)
|
|
||||||
return self:addAnimation(name, args, duration, easing)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local easings = {
|
local easings = {
|
||||||
linear = function(progress)
|
linear = function(progress)
|
||||||
return progress
|
return progress
|
||||||
@@ -38,13 +20,29 @@ local easings = {
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
function Animation.registerEasing(name, func)
|
---@splitClass
|
||||||
easings[name] = func
|
|
||||||
end
|
|
||||||
|
|
||||||
|
--- This is the AnimationInstance class. It represents a single animation instance
|
||||||
|
---@class AnimationInstance
|
||||||
|
---@field element VisualElement The element being animated
|
||||||
|
---@field type string The type of animation
|
||||||
|
---@field args table The animation arguments
|
||||||
|
---@field duration number The duration in seconds
|
||||||
|
---@field startTime number The animation start time
|
||||||
|
---@field isPaused boolean Whether the animation is paused
|
||||||
|
---@field handlers table The animation handlers
|
||||||
|
---@field easing string The easing function name
|
||||||
local AnimationInstance = {}
|
local AnimationInstance = {}
|
||||||
AnimationInstance.__index = AnimationInstance
|
AnimationInstance.__index = AnimationInstance
|
||||||
|
|
||||||
|
--- Creates a new AnimationInstance
|
||||||
|
--- @shortDescription Creates a new animation instance
|
||||||
|
--- @param element VisualElement The element to animate
|
||||||
|
--- @param animType string The type of animation
|
||||||
|
--- @param args table The animation arguments
|
||||||
|
--- @param duration number Duration in seconds
|
||||||
|
--- @param easing string The easing function name
|
||||||
|
--- @return AnimationInstance The new animation instance
|
||||||
function AnimationInstance.new(element, animType, args, duration, easing)
|
function AnimationInstance.new(element, animType, args, duration, easing)
|
||||||
local self = setmetatable({}, AnimationInstance)
|
local self = setmetatable({}, AnimationInstance)
|
||||||
self.element = element
|
self.element = element
|
||||||
@@ -58,25 +56,72 @@ function AnimationInstance.new(element, animType, args, duration, easing)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Starts the animation
|
||||||
|
--- @shortDescription Starts the animation
|
||||||
|
--- @return AnimationInstance self The animation instance
|
||||||
function AnimationInstance:start()
|
function AnimationInstance:start()
|
||||||
self.startTime = os.epoch("local") / 1000
|
self.startTime = os.epoch("local") / 1000
|
||||||
if self.handlers.start then
|
if self.handlers.start then
|
||||||
self.handlers.start(self)
|
self.handlers.start(self)
|
||||||
end
|
end
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Updates the animation
|
||||||
|
--- @shortDescription Updates the animation
|
||||||
|
--- @param elapsed number The elapsed time in seconds
|
||||||
|
--- @return boolean Whether the animation is finished
|
||||||
function AnimationInstance:update(elapsed)
|
function AnimationInstance:update(elapsed)
|
||||||
local rawProgress = math.min(1, elapsed / self.duration)
|
local rawProgress = math.min(1, elapsed / self.duration)
|
||||||
local progress = easings[self.easing](rawProgress)
|
local progress = easings[self.easing](rawProgress)
|
||||||
return self.handlers.update(self, progress)
|
return self.handlers.update(self, progress)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets called when the animation is completed
|
||||||
|
--- @shortDescription Called when the animation is completed
|
||||||
function AnimationInstance:complete()
|
function AnimationInstance:complete()
|
||||||
if self.handlers.complete then
|
if self.handlers.complete then
|
||||||
self.handlers.complete(self)
|
self.handlers.complete(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- This is the animation plugin. It provides a animation system for visual elements
|
||||||
|
--- with support for sequences, easing functions, and multiple animation types.
|
||||||
|
---@class Animation
|
||||||
|
local Animation = {}
|
||||||
|
Animation.__index = Animation
|
||||||
|
|
||||||
|
--- Registers a new animation type
|
||||||
|
--- @shortDescription Registers a custom animation type
|
||||||
|
--- @param name string The name of the animation
|
||||||
|
--- @param handlers table Table containing start, update and complete handlers
|
||||||
|
--- @usage Animation.registerAnimation("fade", {start=function(anim) end, update=function(anim,progress) end})
|
||||||
|
function Animation.registerAnimation(name, handlers)
|
||||||
|
registeredAnimations[name] = handlers
|
||||||
|
|
||||||
|
Animation[name] = function(self, ...)
|
||||||
|
local args = {...}
|
||||||
|
local easing = "linear"
|
||||||
|
if(type(args[#args]) == "string") then
|
||||||
|
easing = table.remove(args, #args)
|
||||||
|
end
|
||||||
|
local duration = table.remove(args, #args)
|
||||||
|
return self:addAnimation(name, args, duration, easing)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Registers a new easing function
|
||||||
|
--- @shortDescription Adds a custom easing function
|
||||||
|
--- @param name string The name of the easing function
|
||||||
|
--- @param func function The easing function (takes progress 0-1, returns modified progress)
|
||||||
|
function Animation.registerEasing(name, func)
|
||||||
|
easings[name] = func
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creates a new Animation
|
||||||
|
--- @shortDescription Creates a new animation
|
||||||
|
--- @param element VisualElement The element to animate
|
||||||
|
--- @return Animation The new animation
|
||||||
function Animation.new(element)
|
function Animation.new(element)
|
||||||
local self = {}
|
local self = {}
|
||||||
self.element = element
|
self.element = element
|
||||||
@@ -88,6 +133,9 @@ function Animation.new(element)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creates a new sequence
|
||||||
|
--- @shortDescription Creates a new sequence
|
||||||
|
--- @return Animation self The animation instance
|
||||||
function Animation:sequence()
|
function Animation:sequence()
|
||||||
table.insert(self.sequences, {})
|
table.insert(self.sequences, {})
|
||||||
self.currentSequence = #self.sequences
|
self.currentSequence = #self.sequences
|
||||||
@@ -99,6 +147,9 @@ function Animation:sequence()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Registers a callback for the start event
|
||||||
|
--- @shortDescription Registers a callback for the start event
|
||||||
|
--- @param callback function The callback function to register
|
||||||
function Animation:onStart(callback)
|
function Animation:onStart(callback)
|
||||||
if not self.sequenceCallbacks[self.currentSequence] then
|
if not self.sequenceCallbacks[self.currentSequence] then
|
||||||
self.sequenceCallbacks[self.currentSequence] = {}
|
self.sequenceCallbacks[self.currentSequence] = {}
|
||||||
@@ -107,6 +158,10 @@ function Animation:onStart(callback)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Registers a callback for the update event
|
||||||
|
--- @shortDescription Registers a callback for the update event
|
||||||
|
--- @param callback function The callback function to register
|
||||||
|
--- @return Animation self The animation instance
|
||||||
function Animation:onUpdate(callback)
|
function Animation:onUpdate(callback)
|
||||||
if not self.sequenceCallbacks[self.currentSequence] then
|
if not self.sequenceCallbacks[self.currentSequence] then
|
||||||
self.sequenceCallbacks[self.currentSequence] = {}
|
self.sequenceCallbacks[self.currentSequence] = {}
|
||||||
@@ -115,6 +170,10 @@ function Animation:onUpdate(callback)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Registers a callback for the complete event
|
||||||
|
--- @shortDescription Registers a callback for the complete event
|
||||||
|
--- @param callback function The callback function to register
|
||||||
|
--- @return Animation self The animation instance
|
||||||
function Animation:onComplete(callback)
|
function Animation:onComplete(callback)
|
||||||
if not self.sequenceCallbacks[self.currentSequence] then
|
if not self.sequenceCallbacks[self.currentSequence] then
|
||||||
self.sequenceCallbacks[self.currentSequence] = {}
|
self.sequenceCallbacks[self.currentSequence] = {}
|
||||||
@@ -123,14 +182,22 @@ function Animation:onComplete(callback)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Adds a new animation to the sequence
|
||||||
|
--- @shortDescription Adds a new animation to the sequence
|
||||||
|
--- @param type string The type of animation
|
||||||
|
--- @param args table The animation arguments
|
||||||
|
--- @param duration number The duration in seconds
|
||||||
|
--- @param easing string The easing function name
|
||||||
function Animation:addAnimation(type, args, duration, easing)
|
function Animation:addAnimation(type, args, duration, easing)
|
||||||
local anim = AnimationInstance.new(self.element, type, args, duration, easing)
|
local anim = AnimationInstance.new(self.element, type, args, duration, easing)
|
||||||
table.insert(self.sequences[self.currentSequence], anim)
|
table.insert(self.sequences[self.currentSequence], anim)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Starts the animation
|
||||||
|
--- @shortDescription Starts the animation
|
||||||
|
--- @return Animation self The animation instance
|
||||||
function Animation:start()
|
function Animation:start()
|
||||||
|
|
||||||
self.currentSequence = 1
|
self.currentSequence = 1
|
||||||
if(self.sequenceCallbacks[self.currentSequence])then
|
if(self.sequenceCallbacks[self.currentSequence])then
|
||||||
if(self.sequenceCallbacks[self.currentSequence].start) then
|
if(self.sequenceCallbacks[self.currentSequence].start) then
|
||||||
@@ -146,6 +213,10 @@ function Animation:start()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- The event handler for the animation (listens to timer events)
|
||||||
|
--- @shortDescription The event handler for the animation
|
||||||
|
--- @param event string The event type
|
||||||
|
--- @param timerId number The timer ID
|
||||||
function Animation:event(event, timerId)
|
function Animation:event(event, timerId)
|
||||||
if event == "timer" and timerId == self.timer then
|
if event == "timer" and timerId == self.timer then
|
||||||
local currentTime = os.epoch("local") / 1000
|
local currentTime = os.epoch("local") / 1000
|
||||||
@@ -300,8 +371,13 @@ Animation.registerAnimation("scrollText", {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
---@splitClass
|
||||||
|
|
||||||
|
--- Adds additional methods for VisualElement when adding animation plugin
|
||||||
|
--- @class VisualElement
|
||||||
local VisualElement = {hooks={}}
|
local VisualElement = {hooks={}}
|
||||||
|
|
||||||
|
---@private
|
||||||
function VisualElement.hooks.dispatchEvent(self, event, ...)
|
function VisualElement.hooks.dispatchEvent(self, event, ...)
|
||||||
if event == "timer" then
|
if event == "timer" then
|
||||||
local animation = self.get("animation")
|
local animation = self.get("animation")
|
||||||
@@ -311,12 +387,16 @@ function VisualElement.hooks.dispatchEvent(self, event, ...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@private
|
||||||
function VisualElement.setup(element)
|
function VisualElement.setup(element)
|
||||||
VisualElementBaseDispatchEvent = element.dispatchEvent
|
VisualElementBaseDispatchEvent = element.dispatchEvent
|
||||||
element.defineProperty(element, "animation", {default = nil, type = "table"})
|
element.defineProperty(element, "animation", {default = nil, type = "table"})
|
||||||
element.listenTo(element, "timer")
|
element.listenTo(element, "timer")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creates a new Animation Object
|
||||||
|
--- @shortDescription Creates a new animation
|
||||||
|
--- @return Animation animation The new animation
|
||||||
function VisualElement:animate()
|
function VisualElement:animate()
|
||||||
local animation = Animation.new(self)
|
local animation = Animation.new(self)
|
||||||
self.set("animation", animation)
|
self.set("animation", animation)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
local log = require("log")
|
local log = require("log")
|
||||||
|
|
||||||
|
|
||||||
local activeProfiles = setmetatable({}, {__mode = "k"})
|
local activeProfiles = setmetatable({}, {__mode = "k"})
|
||||||
|
|
||||||
local function createProfile()
|
local function createProfile()
|
||||||
@@ -36,8 +37,18 @@ local function wrapMethod(element, methodName)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@splitClass
|
||||||
|
|
||||||
|
--- This is the benchmark plugin. It provides performance measurement tools for elements and methods,
|
||||||
|
--- with support for hierarchical profiling and detailed statistics.
|
||||||
|
--- The following methods are available for BaseElement
|
||||||
|
---@class BaseElement
|
||||||
local BaseElement = {}
|
local BaseElement = {}
|
||||||
|
|
||||||
|
--- Starts profiling a method
|
||||||
|
--- @shortDescription Starts timing a method call
|
||||||
|
--- @param methodName string The name of the method to profile
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:startProfile(methodName)
|
function BaseElement:startProfile(methodName)
|
||||||
local profile = activeProfiles[self]
|
local profile = activeProfiles[self]
|
||||||
if not profile then
|
if not profile then
|
||||||
@@ -70,6 +81,10 @@ function BaseElement:startProfile(methodName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Ends profiling a method
|
||||||
|
--- @shortDescription Ends timing a method call and records statistics
|
||||||
|
--- @param methodName string The name of the method to stop profiling
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:endProfile(methodName)
|
function BaseElement:endProfile(methodName)
|
||||||
local profile = activeProfiles[self]
|
local profile = activeProfiles[self]
|
||||||
if not profile or not profile.methods[methodName] then return self end
|
if not profile or not profile.methods[methodName] then return self end
|
||||||
@@ -87,6 +102,11 @@ function BaseElement:endProfile(methodName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Enables benchmarking for a method
|
||||||
|
--- @shortDescription Enables performance measurement for a method
|
||||||
|
--- @param methodName string The name of the method to benchmark
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
|
--- @usage element:benchmark("render")
|
||||||
function BaseElement:benchmark(methodName)
|
function BaseElement:benchmark(methodName)
|
||||||
if not self[methodName] then
|
if not self[methodName] then
|
||||||
log.error("Method " .. methodName .. " does not exist")
|
log.error("Method " .. methodName .. " does not exist")
|
||||||
@@ -101,6 +121,10 @@ function BaseElement:benchmark(methodName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Logs benchmark statistics for a method
|
||||||
|
--- @shortDescription Logs benchmark statistics for a method
|
||||||
|
--- @param methodName string The name of the method to log
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:logBenchmark(methodName)
|
function BaseElement:logBenchmark(methodName)
|
||||||
local profile = activeProfiles[self]
|
local profile = activeProfiles[self]
|
||||||
if not profile or not profile.methods[methodName] then return self end
|
if not profile or not profile.methods[methodName] then return self end
|
||||||
@@ -131,6 +155,10 @@ function BaseElement:logBenchmark(methodName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Stops benchmarking for a method
|
||||||
|
--- @shortDescription Disables performance measurement for a method
|
||||||
|
--- @param methodName string The name of the method to stop benchmarking
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:stopBenchmark(methodName)
|
function BaseElement:stopBenchmark(methodName)
|
||||||
local profile = activeProfiles[self]
|
local profile = activeProfiles[self]
|
||||||
if not profile or not profile.methods[methodName] then return self end
|
if not profile or not profile.methods[methodName] then return self end
|
||||||
@@ -147,6 +175,10 @@ function BaseElement:stopBenchmark(methodName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets benchmark statistics for a method
|
||||||
|
--- @shortDescription Retrieves benchmark statistics for a method
|
||||||
|
--- @param methodName string The name of the method to get statistics for
|
||||||
|
--- @return table? stats The benchmark statistics or nil
|
||||||
function BaseElement:getBenchmarkStats(methodName)
|
function BaseElement:getBenchmarkStats(methodName)
|
||||||
local profile = activeProfiles[self]
|
local profile = activeProfiles[self]
|
||||||
if not profile or not profile.methods[methodName] then return nil end
|
if not profile or not profile.methods[methodName] then return nil end
|
||||||
@@ -162,8 +194,17 @@ function BaseElement:getBenchmarkStats(methodName)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@splitClass
|
||||||
|
|
||||||
|
--- Container benchmarking methods
|
||||||
|
---@class Container
|
||||||
local Container = {}
|
local Container = {}
|
||||||
|
|
||||||
|
--- Enables benchmarking for a container and all its children
|
||||||
|
--- @shortDescription Recursively enables benchmarking
|
||||||
|
--- @param methodName string The method to benchmark
|
||||||
|
--- @return Container self The container instance
|
||||||
|
--- @usage container:benchmarkContainer("render")
|
||||||
function Container:benchmarkContainer(methodName)
|
function Container:benchmarkContainer(methodName)
|
||||||
self:benchmark(methodName)
|
self:benchmark(methodName)
|
||||||
|
|
||||||
@@ -177,6 +218,10 @@ function Container:benchmarkContainer(methodName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Logs benchmark statistics for a container and all its children
|
||||||
|
--- @shortDescription Recursively logs benchmark statistics
|
||||||
|
--- @param methodName string The method to log
|
||||||
|
--- @return Container self The container instance
|
||||||
function Container:logContainerBenchmarks(methodName, depth)
|
function Container:logContainerBenchmarks(methodName, depth)
|
||||||
depth = depth or 0
|
depth = depth or 0
|
||||||
local indent = string.rep(" ", depth)
|
local indent = string.rep(" ", depth)
|
||||||
@@ -237,6 +282,10 @@ function Container:logContainerBenchmarks(methodName, depth)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Stops benchmarking for a container and all its children
|
||||||
|
--- @shortDescription Recursively stops benchmarking
|
||||||
|
--- @param methodName string The method to stop benchmarking
|
||||||
|
--- @return Container self The container instance
|
||||||
function Container:stopContainerBenchmark(methodName)
|
function Container:stopContainerBenchmark(methodName)
|
||||||
for _, child in pairs(self.get("children")) do
|
for _, child in pairs(self.get("children")) do
|
||||||
if child:isType("Container") then
|
if child:isType("Container") then
|
||||||
@@ -250,73 +299,91 @@ function Container:stopContainerBenchmark(methodName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
local API = {
|
--- Benchmark API methods
|
||||||
start = function(name, options)
|
---@class BenchmarkAPI
|
||||||
options = options or {}
|
local API = {}
|
||||||
local profile = createProfile()
|
|
||||||
profile.name = name
|
|
||||||
profile.startTime = os.clock() * 1000
|
|
||||||
profile.custom = true
|
|
||||||
activeProfiles[name] = profile
|
|
||||||
end,
|
|
||||||
|
|
||||||
stop = function(name)
|
--- Starts a custom benchmark
|
||||||
local profile = activeProfiles[name]
|
--- @shortDescription Starts timing a custom operation
|
||||||
if not profile or not profile.custom then return end
|
--- @param name string The name of the benchmark
|
||||||
|
--- @param options? table Optional configuration
|
||||||
|
function API.start(name, options)
|
||||||
|
options = options or {}
|
||||||
|
local profile = createProfile()
|
||||||
|
profile.name = name
|
||||||
|
profile.startTime = os.clock() * 1000
|
||||||
|
profile.custom = true
|
||||||
|
activeProfiles[name] = profile
|
||||||
|
end
|
||||||
|
|
||||||
local endTime = os.clock() * 1000
|
--- Stops a custom benchmark
|
||||||
local duration = endTime - profile.startTime
|
--- @shortDescription Stops timing and logs results
|
||||||
|
--- @param name string The name of the benchmark to stop
|
||||||
|
function API.stop(name)
|
||||||
|
local profile = activeProfiles[name]
|
||||||
|
if not profile or not profile.custom then return end
|
||||||
|
|
||||||
profile.calls = profile.calls + 1
|
local endTime = os.clock() * 1000
|
||||||
profile.totalTime = profile.totalTime + duration
|
local duration = endTime - profile.startTime
|
||||||
profile.minTime = math.min(profile.minTime, duration)
|
|
||||||
profile.maxTime = math.max(profile.maxTime, duration)
|
|
||||||
profile.lastTime = duration
|
|
||||||
|
|
||||||
log.info(string.format(
|
profile.calls = profile.calls + 1
|
||||||
"Custom Benchmark '%s': " ..
|
profile.totalTime = profile.totalTime + duration
|
||||||
"Calls: %d " ..
|
profile.minTime = math.min(profile.minTime, duration)
|
||||||
"Average time: %.2fms " ..
|
profile.maxTime = math.max(profile.maxTime, duration)
|
||||||
"Min time: %.2fms " ..
|
profile.lastTime = duration
|
||||||
"Max time: %.2fms " ..
|
|
||||||
"Last time: %.2fms " ..
|
|
||||||
"Total time: %.2fms",
|
|
||||||
name,
|
|
||||||
profile.calls,
|
|
||||||
profile.totalTime / profile.calls,
|
|
||||||
profile.minTime,
|
|
||||||
profile.maxTime,
|
|
||||||
profile.lastTime,
|
|
||||||
profile.totalTime
|
|
||||||
))
|
|
||||||
end,
|
|
||||||
|
|
||||||
getStats = function(name)
|
log.info(string.format(
|
||||||
local profile = activeProfiles[name]
|
"Custom Benchmark '%s': " ..
|
||||||
if not profile then return nil end
|
"Calls: %d " ..
|
||||||
|
"Average time: %.2fms " ..
|
||||||
|
"Min time: %.2fms " ..
|
||||||
|
"Max time: %.2fms " ..
|
||||||
|
"Last time: %.2fms " ..
|
||||||
|
"Total time: %.2fms",
|
||||||
|
name,
|
||||||
|
profile.calls,
|
||||||
|
profile.totalTime / profile.calls,
|
||||||
|
profile.minTime,
|
||||||
|
profile.maxTime,
|
||||||
|
profile.lastTime,
|
||||||
|
profile.totalTime
|
||||||
|
))
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
--- Gets statistics for a benchmark
|
||||||
averageTime = profile.totalTime / profile.calls,
|
--- @shortDescription Retrieves benchmark statistics
|
||||||
totalTime = profile.totalTime,
|
--- @param name string The name of the benchmark
|
||||||
calls = profile.calls,
|
--- @return table? stats The benchmark statistics or nil
|
||||||
minTime = profile.minTime,
|
function API.getStats(name)
|
||||||
maxTime = profile.maxTime,
|
local profile = activeProfiles[name]
|
||||||
lastTime = profile.lastTime
|
if not profile then return nil end
|
||||||
}
|
|
||||||
end,
|
|
||||||
|
|
||||||
clear = function(name)
|
return {
|
||||||
activeProfiles[name] = nil
|
averageTime = profile.totalTime / profile.calls,
|
||||||
end,
|
totalTime = profile.totalTime,
|
||||||
|
calls = profile.calls,
|
||||||
|
minTime = profile.minTime,
|
||||||
|
maxTime = profile.maxTime,
|
||||||
|
lastTime = profile.lastTime
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
clearAll = function()
|
--- Clears a specific benchmark
|
||||||
for k,v in pairs(activeProfiles) do
|
--- @shortDescription Removes a benchmark's data
|
||||||
if v.custom then
|
--- @param name string The name of the benchmark to clear
|
||||||
activeProfiles[k] = nil
|
function API.clear(name)
|
||||||
end
|
activeProfiles[name] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Clears all custom benchmarks
|
||||||
|
--- @shortDescription Removes all custom benchmark data
|
||||||
|
function API.clearAll()
|
||||||
|
for k,v in pairs(activeProfiles) do
|
||||||
|
if v.custom then
|
||||||
|
activeProfiles[k] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
BaseElement = BaseElement,
|
BaseElement = BaseElement,
|
||||||
|
|||||||
@@ -37,142 +37,165 @@ local function createDebugger(element)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local BaseElement = {
|
--- No Description
|
||||||
debug = function(self, level)
|
--- @class BaseElement
|
||||||
self._debugger = createDebugger(self)
|
local BaseElement = {}
|
||||||
self._debugLevel = level or DEBUG_LEVELS.INFO
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
|
|
||||||
dumpDebug = function(self)
|
--- Enables debugging for this element
|
||||||
if not self._debugger then return end
|
--- @shortDescription Enables debugging for this element
|
||||||
return self._debugger.dump()
|
--- @param self BaseElement The element to debug
|
||||||
end
|
--- @param level number The debug level
|
||||||
}
|
function BaseElement.debug(self, level)
|
||||||
|
self._debugger = createDebugger(self)
|
||||||
|
self._debugLevel = level or DEBUG_LEVELS.INFO
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
local BaseFrame = {
|
--- Dumps debug information for this element
|
||||||
showDebugLog = function(self)
|
--- @shortDescription Dumps debug information
|
||||||
if not self._debugFrame then
|
--- @param self BaseElement The element to dump debug info for
|
||||||
local width = self.get("width")
|
function BaseElement.dumpDebug(self)
|
||||||
local height = self.get("height")
|
if not self._debugger then return end
|
||||||
self._debugFrame = self:addFrame("basaltDebugLog")
|
return self._debugger.dump()
|
||||||
:setWidth(width)
|
end
|
||||||
:setHeight(height)
|
|
||||||
:setZ(999)
|
|
||||||
:listenEvent("mouse_scroll", true)
|
|
||||||
self.basalt.LOGGER.debug("Created debug log frame " .. self._debugFrame.get("name"))
|
|
||||||
|
|
||||||
self._debugFrame:addButton("basaltDebugLogClose")
|
---@class BaseFrame
|
||||||
:setWidth(9)
|
local BaseFrame = {}
|
||||||
:setHeight(1)
|
|
||||||
:setX(width - 8)
|
|
||||||
:setY(height)
|
|
||||||
:setText("Close")
|
|
||||||
:onMouseClick(function()
|
|
||||||
self:hideDebugLog()
|
|
||||||
end)
|
|
||||||
|
|
||||||
self._debugFrame._scrollOffset = 0
|
--- Shows the debug log frame
|
||||||
self._debugFrame._processedLogs = {}
|
--- @shortDescription Shows the debug log frame
|
||||||
|
--- @param self BaseFrame The frame to show debug log in
|
||||||
|
function BaseFrame.showDebugLog(self)
|
||||||
|
if not self._debugFrame then
|
||||||
|
local width = self.get("width")
|
||||||
|
local height = self.get("height")
|
||||||
|
self._debugFrame = self:addFrame("basaltDebugLog")
|
||||||
|
:setWidth(width)
|
||||||
|
:setHeight(height)
|
||||||
|
:setZ(999)
|
||||||
|
:listenEvent("mouse_scroll", true)
|
||||||
|
self.basalt.LOGGER.debug("Created debug log frame " .. self._debugFrame.get("name"))
|
||||||
|
|
||||||
local function wrapText(text, width)
|
self._debugFrame:addButton("basaltDebugLogClose")
|
||||||
local lines = {}
|
:setWidth(9)
|
||||||
while #text > 0 do
|
:setHeight(1)
|
||||||
local line = text:sub(1, width)
|
:setX(width - 8)
|
||||||
table.insert(lines, line)
|
:setY(height)
|
||||||
text = text:sub(width + 1)
|
:setText("Close")
|
||||||
end
|
:onMouseClick(function()
|
||||||
return lines
|
|
||||||
end
|
|
||||||
|
|
||||||
local function processLogs()
|
|
||||||
local processed = {}
|
|
||||||
local width = self._debugFrame.get("width")
|
|
||||||
|
|
||||||
for _, entry in ipairs(log._logs) do
|
|
||||||
local lines = wrapText(entry.message, width)
|
|
||||||
for _, line in ipairs(lines) do
|
|
||||||
table.insert(processed, {
|
|
||||||
text = line,
|
|
||||||
level = entry.level
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return processed
|
|
||||||
end
|
|
||||||
|
|
||||||
local totalLines = #processLogs() - self.get("height")
|
|
||||||
self._scrollOffset = totalLines
|
|
||||||
|
|
||||||
local originalRender = self._debugFrame.render
|
|
||||||
self._debugFrame.render = function(frame)
|
|
||||||
originalRender(frame)
|
|
||||||
frame._processedLogs = processLogs()
|
|
||||||
|
|
||||||
local height = frame.get("height")-2
|
|
||||||
local totalLines = #frame._processedLogs
|
|
||||||
local maxScroll = math.max(0, totalLines - height)
|
|
||||||
frame._scrollOffset = math.min(frame._scrollOffset, maxScroll)
|
|
||||||
|
|
||||||
for i = 1, height-2 do
|
|
||||||
local logIndex = i + frame._scrollOffset
|
|
||||||
local entry = frame._processedLogs[logIndex]
|
|
||||||
|
|
||||||
if entry then
|
|
||||||
local color = entry.level == log.LEVEL.ERROR and colors.red
|
|
||||||
or entry.level == log.LEVEL.WARN and colors.yellow
|
|
||||||
or entry.level == log.LEVEL.DEBUG and colors.lightGray
|
|
||||||
or colors.white
|
|
||||||
|
|
||||||
frame:textFg(2, i, entry.text, color)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local baseDispatchEvent = self._debugFrame.dispatchEvent
|
|
||||||
self._debugFrame.dispatchEvent = function(self, event, direction, ...)
|
|
||||||
if(event == "mouse_scroll") then
|
|
||||||
self._scrollOffset = math.max(0, self._scrollOffset + direction)
|
|
||||||
self:updateRender()
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
baseDispatchEvent(self, event, direction, ...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self._debugFrame.set("visible", true)
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
|
|
||||||
hideDebugLog = function(self)
|
|
||||||
if self._debugFrame then
|
|
||||||
self._debugFrame.set("visible", false)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end,
|
|
||||||
|
|
||||||
toggleDebugLog = function(self)
|
|
||||||
if self._debugFrame and self._debugFrame:isVisible() then
|
|
||||||
self:hideDebugLog()
|
self:hideDebugLog()
|
||||||
else
|
end)
|
||||||
self:showDebugLog()
|
|
||||||
|
self._debugFrame._scrollOffset = 0
|
||||||
|
self._debugFrame._processedLogs = {}
|
||||||
|
|
||||||
|
local function wrapText(text, width)
|
||||||
|
local lines = {}
|
||||||
|
while #text > 0 do
|
||||||
|
local line = text:sub(1, width)
|
||||||
|
table.insert(lines, line)
|
||||||
|
text = text:sub(width + 1)
|
||||||
|
end
|
||||||
|
return lines
|
||||||
end
|
end
|
||||||
return self
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
|
local function processLogs()
|
||||||
|
local processed = {}
|
||||||
|
local width = self._debugFrame.get("width")
|
||||||
|
|
||||||
local Container = {
|
for _, entry in ipairs(log._logs) do
|
||||||
debugChildren = function(self, level)
|
local lines = wrapText(entry.message, width)
|
||||||
self:debug(level)
|
for _, line in ipairs(lines) do
|
||||||
for _, child in pairs(self.get("children")) do
|
table.insert(processed, {
|
||||||
if child.debug then
|
text = line,
|
||||||
child:debug(level)
|
level = entry.level
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return processed
|
||||||
|
end
|
||||||
|
|
||||||
|
local totalLines = #processLogs() - self.get("height")
|
||||||
|
self._scrollOffset = totalLines
|
||||||
|
|
||||||
|
local originalRender = self._debugFrame.render
|
||||||
|
self._debugFrame.render = function(frame)
|
||||||
|
originalRender(frame)
|
||||||
|
frame._processedLogs = processLogs()
|
||||||
|
|
||||||
|
local height = frame.get("height")-2
|
||||||
|
local totalLines = #frame._processedLogs
|
||||||
|
local maxScroll = math.max(0, totalLines - height)
|
||||||
|
frame._scrollOffset = math.min(frame._scrollOffset, maxScroll)
|
||||||
|
|
||||||
|
for i = 1, height-2 do
|
||||||
|
local logIndex = i + frame._scrollOffset
|
||||||
|
local entry = frame._processedLogs[logIndex]
|
||||||
|
|
||||||
|
if entry then
|
||||||
|
local color = entry.level == log.LEVEL.ERROR and colors.red
|
||||||
|
or entry.level == log.LEVEL.WARN and colors.yellow
|
||||||
|
or entry.level == log.LEVEL.DEBUG and colors.lightGray
|
||||||
|
or colors.white
|
||||||
|
|
||||||
|
frame:textFg(2, i, entry.text, color)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local baseDispatchEvent = self._debugFrame.dispatchEvent
|
||||||
|
self._debugFrame.dispatchEvent = function(self, event, direction, ...)
|
||||||
|
if(event == "mouse_scroll") then
|
||||||
|
self._scrollOffset = math.max(0, self._scrollOffset + direction)
|
||||||
|
self:updateRender()
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
baseDispatchEvent(self, event, direction, ...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
}
|
self._debugFrame.set("visible", true)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Hides the debug log frame
|
||||||
|
--- @shortDescription Hides the debug log frame
|
||||||
|
--- @param self BaseFrame The frame to hide debug log for
|
||||||
|
function BaseFrame.hideDebugLog(self)
|
||||||
|
if self._debugFrame then
|
||||||
|
self._debugFrame.set("visible", false)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Toggles the debug log frame
|
||||||
|
--- @shortDescription Toggles the debug log frame
|
||||||
|
--- @param self BaseFrame The frame to toggle debug log for
|
||||||
|
function BaseFrame.toggleDebugLog(self)
|
||||||
|
if self._debugFrame and self._debugFrame:isVisible() then
|
||||||
|
self:hideDebugLog()
|
||||||
|
else
|
||||||
|
self:showDebugLog()
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class Container
|
||||||
|
local Container = {}
|
||||||
|
|
||||||
|
--- Enables debugging for this container and all its children
|
||||||
|
--- @shortDescription Debug container and children
|
||||||
|
--- @param self Container The container to debug
|
||||||
|
--- @param level number The debug level
|
||||||
|
function Container.debugChildren(self, level)
|
||||||
|
self:debug(level)
|
||||||
|
for _, child in pairs(self.get("children")) do
|
||||||
|
if child.debug then
|
||||||
|
child:debug(level)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
BaseElement = BaseElement,
|
BaseElement = BaseElement,
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
local PropertySystem = require("propertySystem")
|
local PropertySystem = require("propertySystem")
|
||||||
local errorManager = require("errorManager")
|
local errorManager = require("errorManager")
|
||||||
|
|
||||||
|
--- This is the state plugin. It provides a state management system for UI elements with support for
|
||||||
|
--- persistent states, computed states, and state sharing between elements.
|
||||||
|
---@class BaseElement
|
||||||
local BaseElement = {}
|
local BaseElement = {}
|
||||||
|
|
||||||
|
---@private
|
||||||
function BaseElement.setup(element)
|
function BaseElement.setup(element)
|
||||||
element.defineProperty(element, "states", {default = {}, type = "table"})
|
element.defineProperty(element, "states", {default = {}, type = "table"})
|
||||||
element.defineProperty(element, "computedStates", {default = {}, type = "table"})
|
element.defineProperty(element, "computedStates", {default = {}, type = "table"})
|
||||||
@@ -11,6 +16,15 @@ function BaseElement.setup(element)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes a new state for this element
|
||||||
|
--- @shortDescription Initializes a new state
|
||||||
|
--- @param self BaseElement The element to initialize state for
|
||||||
|
--- @param name string The name of the state
|
||||||
|
--- @param default any The default value of the state
|
||||||
|
--- @param canTriggerRender? boolean Whether state changes trigger a render
|
||||||
|
--- @param persist? boolean Whether to persist the state to disk
|
||||||
|
--- @param path? string Custom file path for persistence
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:initializeState(name, default, canTriggerRender, persist, path)
|
function BaseElement:initializeState(name, default, canTriggerRender, persist, path)
|
||||||
local states = self.get("states")
|
local states = self.get("states")
|
||||||
|
|
||||||
@@ -47,6 +61,12 @@ function BaseElement:initializeState(name, default, canTriggerRender, persist, p
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Sets the value of a state
|
||||||
|
--- @shortDescription Sets a state value
|
||||||
|
--- @param self BaseElement The element to set state for
|
||||||
|
--- @param name string The name of the state
|
||||||
|
--- @param value any The new value for the state
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:setState(name, value)
|
function BaseElement:setState(name, value)
|
||||||
local states = self.get("states")
|
local states = self.get("states")
|
||||||
if not states[name] then
|
if not states[name] then
|
||||||
@@ -78,6 +98,11 @@ function BaseElement:setState(name, value)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the value of a state
|
||||||
|
--- @shortDescription Gets a state value
|
||||||
|
--- @param self BaseElement The element to get state from
|
||||||
|
--- @param name string The name of the state
|
||||||
|
--- @return any value The current state value
|
||||||
function BaseElement:getState(name)
|
function BaseElement:getState(name)
|
||||||
local states = self.get("states")
|
local states = self.get("states")
|
||||||
if not states[name] then
|
if not states[name] then
|
||||||
@@ -86,6 +111,12 @@ function BaseElement:getState(name)
|
|||||||
return states[name].value
|
return states[name].value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creates a computed state that derives its value from other states
|
||||||
|
--- @shortDescription Creates a computed state
|
||||||
|
--- @param self BaseElement The element to create computed state for
|
||||||
|
--- @param key string The name of the computed state
|
||||||
|
--- @param computeFn function Function that computes the state value
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:computed(key, computeFn)
|
function BaseElement:computed(key, computeFn)
|
||||||
local computed = self.get("computedStates")
|
local computed = self.get("computedStates")
|
||||||
computed[key] = setmetatable({}, {
|
computed[key] = setmetatable({}, {
|
||||||
@@ -96,6 +127,12 @@ function BaseElement:computed(key, computeFn)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Shares a state with other elements, keeping them in sync
|
||||||
|
--- @shortDescription Shares state between elements
|
||||||
|
--- @param self BaseElement The source element
|
||||||
|
--- @param stateKey string The state to share
|
||||||
|
--- @vararg BaseElement The target elements to share with
|
||||||
|
--- @return BaseElement self The source element
|
||||||
function BaseElement:shareState(stateKey, ...)
|
function BaseElement:shareState(stateKey, ...)
|
||||||
local value = self:getState(stateKey)
|
local value = self:getState(stateKey)
|
||||||
|
|
||||||
@@ -116,6 +153,12 @@ function BaseElement:shareState(stateKey, ...)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Registers a callback for state changes
|
||||||
|
--- @shortDescription Watches for state changes
|
||||||
|
--- @param self BaseElement The element to watch
|
||||||
|
--- @param stateName string The state to watch
|
||||||
|
--- @param callback function Called with (element, newValue, oldValue)
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:onStateChange(stateName, callback)
|
function BaseElement:onStateChange(stateName, callback)
|
||||||
if not self.get("states")[stateName] then
|
if not self.get("states")[stateName] then
|
||||||
errorManager.error("Cannot observe state '" .. stateName .. "': State not initialized")
|
errorManager.error("Cannot observe state '" .. stateName .. "': State not initialized")
|
||||||
|
|||||||
@@ -40,15 +40,20 @@ local themes = {
|
|||||||
|
|
||||||
local currentTheme = "default"
|
local currentTheme = "default"
|
||||||
|
|
||||||
|
--- This is the theme plugin. It provides a theming system that allows for consistent styling across elements
|
||||||
|
--- with support for inheritance, named styles, and dynamic theme switching.
|
||||||
|
---@class BaseElement
|
||||||
local BaseElement = {
|
local BaseElement = {
|
||||||
hooks = {
|
hooks = {
|
||||||
postInit = {
|
postInit = {
|
||||||
pre = function(self)
|
pre = function(self)
|
||||||
self:applyTheme()
|
self:applyTheme()
|
||||||
end}
|
end
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@private
|
||||||
function BaseElement.____getElementPath(self, types)
|
function BaseElement.____getElementPath(self, types)
|
||||||
if types then
|
if types then
|
||||||
table.insert(types, 1, self._values.type)
|
table.insert(types, 1, self._values.type)
|
||||||
@@ -147,7 +152,11 @@ local function collectThemeProps(theme, path, elementType, elementName)
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
function BaseElement:applyTheme()
|
--- Applies the current theme to this element
|
||||||
|
--- @shortDescription Applies theme styles to the element
|
||||||
|
--- @param self BaseElement The element to apply theme to
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
|
function BaseElement:applyTheme()
|
||||||
local styles = self:getTheme()
|
local styles = self:getTheme()
|
||||||
if(styles ~= nil) then
|
if(styles ~= nil) then
|
||||||
for prop, value in pairs(styles) do
|
for prop, value in pairs(styles) do
|
||||||
@@ -156,6 +165,10 @@ end
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the theme properties for this element
|
||||||
|
--- @shortDescription Gets theme properties for the element
|
||||||
|
--- @param self BaseElement The element to get theme for
|
||||||
|
--- @return table styles The theme properties
|
||||||
function BaseElement:getTheme()
|
function BaseElement:getTheme()
|
||||||
local path = self:____getElementPath()
|
local path = self:____getElementPath()
|
||||||
local elementType = self.get("type")
|
local elementType = self.get("type")
|
||||||
@@ -164,28 +177,37 @@ function BaseElement:getTheme()
|
|||||||
return collectThemeProps(themes[currentTheme], path, elementType, elementName)
|
return collectThemeProps(themes[currentTheme], path, elementType, elementName)
|
||||||
end
|
end
|
||||||
|
|
||||||
local themeAPI = {
|
--- The Theme API provides methods for managing themes globally
|
||||||
setTheme = function(newTheme)
|
---@class ThemeAPI
|
||||||
defaultTheme = newTheme
|
local themeAPI = {}
|
||||||
end,
|
|
||||||
|
|
||||||
getTheme = function()
|
--- Sets the current theme
|
||||||
return defaultTheme
|
--- @shortDescription Sets a new theme
|
||||||
end,
|
--- @param newTheme table The theme configuration to set
|
||||||
|
function themeAPI.setTheme(newTheme)
|
||||||
|
defaultTheme = newTheme
|
||||||
|
end
|
||||||
|
|
||||||
loadTheme = function(path)
|
--- Gets the current theme configuration
|
||||||
local file = fs.open(path, "r")
|
--- @shortDescription Gets the current theme
|
||||||
if file then
|
--- @return table theme The current theme configuration
|
||||||
local content = file.readAll()
|
function themeAPI.getTheme()
|
||||||
file.close()
|
return defaultTheme
|
||||||
defaultTheme = textutils.unserializeJSON(content)
|
end
|
||||||
end
|
|
||||||
|
--- Loads a theme from a JSON file
|
||||||
|
--- @shortDescription Loads theme from JSON file
|
||||||
|
--- @param path string Path to the theme JSON file
|
||||||
|
function themeAPI.loadTheme(path)
|
||||||
|
local file = fs.open(path, "r")
|
||||||
|
if file then
|
||||||
|
local content = file.readAll()
|
||||||
|
file.close()
|
||||||
|
defaultTheme = textutils.unserializeJSON(content)
|
||||||
end
|
end
|
||||||
}
|
end
|
||||||
|
|
||||||
local Theme = {
|
return {
|
||||||
BaseElement = BaseElement,
|
BaseElement = BaseElement,
|
||||||
API = themeAPI
|
API = themeAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
return Theme
|
|
||||||
|
|||||||
@@ -132,8 +132,15 @@ local function handleEvent(node, element, scope)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- The XML plugin provides XML parsing and UI creation from XML markup
|
||||||
|
---@class BaseElement
|
||||||
local BaseElement = {}
|
local BaseElement = {}
|
||||||
|
|
||||||
|
--- Creates an element from an XML node
|
||||||
|
--- @shortDescription Creates element from XML node
|
||||||
|
--- @param self BaseElement The element instance
|
||||||
|
--- @param node table The XML node to create from
|
||||||
|
--- @return BaseElement self The element instance
|
||||||
function BaseElement:fromXML(node)
|
function BaseElement:fromXML(node)
|
||||||
for attr, value in pairs(node.attributes) do
|
for attr, value in pairs(node.attributes) do
|
||||||
local config = self:getPropertyConfig(attr)
|
local config = self:getPropertyConfig(attr)
|
||||||
@@ -145,8 +152,22 @@ function BaseElement:fromXML(node)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@class Container
|
||||||
local Container = {}
|
local Container = {}
|
||||||
|
|
||||||
|
--- Loads and creates UI elements from XML content
|
||||||
|
--- @shortDescription Loads UI from XML string
|
||||||
|
--- @param self Container The container to load into
|
||||||
|
--- @param content string The XML content to parse
|
||||||
|
--- @param scope? table Optional scope for variable resolution
|
||||||
|
--- @return Container self The container instance
|
||||||
|
--- @usage
|
||||||
|
--- local xml = [[
|
||||||
|
--- <Frame>
|
||||||
|
--- <Button name="myButton" x="5" y="5"/>
|
||||||
|
--- </Frame>
|
||||||
|
--- ]]
|
||||||
|
--- container:loadXML(xml)
|
||||||
function Container:loadXML(content, scope)
|
function Container:loadXML(content, scope)
|
||||||
local tree = parseXML(self, content)
|
local tree = parseXML(self, content)
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
local deepCopy = require("libraries/utils").deepCopy
|
local deepCopy = require("libraries/utils").deepCopy
|
||||||
local expect = require("libraries/expect")
|
local expect = require("libraries/expect")
|
||||||
local errorManager = require("errorManager")
|
local errorManager = require("errorManager")
|
||||||
local log = require("log")
|
|
||||||
|
|
||||||
|
--- PropertySystem is a class that allows Elements to have properties that can be observed and updated.
|
||||||
|
--- It also allows for properties to have custom getters and setters. This is the base system for all Elements.
|
||||||
--- @class PropertySystem
|
--- @class PropertySystem
|
||||||
|
--- @field _properties table A table containing all property configurations
|
||||||
|
--- @field _values table A table containing all property values
|
||||||
|
--- @field _observers table A table containing all property observers
|
||||||
|
--- @field set function A function to set a property value
|
||||||
|
--- @field get function A function to get a property value
|
||||||
local PropertySystem = {}
|
local PropertySystem = {}
|
||||||
PropertySystem.__index = PropertySystem
|
PropertySystem.__index = PropertySystem
|
||||||
|
|
||||||
@@ -12,6 +18,9 @@ local blueprintTemplates = {}
|
|||||||
|
|
||||||
PropertySystem._setterHooks = {}
|
PropertySystem._setterHooks = {}
|
||||||
|
|
||||||
|
--- Adds a setter hook to the PropertySystem. Setter hooks are functions that are called before a property is set.
|
||||||
|
--- @shortDescription Adds a setter hook to the PropertySystem
|
||||||
|
--- @param hook function The hook function to add
|
||||||
function PropertySystem.addSetterHook(hook)
|
function PropertySystem.addSetterHook(hook)
|
||||||
table.insert(PropertySystem._setterHooks, hook)
|
table.insert(PropertySystem._setterHooks, hook)
|
||||||
end
|
end
|
||||||
@@ -26,6 +35,11 @@ local function applyHooks(element, propertyName, value, config)
|
|||||||
return value
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Defines a property for an element class
|
||||||
|
--- @shortDescription Defines a property for an element class
|
||||||
|
--- @param class table The element class to define the property for
|
||||||
|
--- @param name string The name of the property
|
||||||
|
--- @param config table The configuration of the property
|
||||||
function PropertySystem.defineProperty(class, name, config)
|
function PropertySystem.defineProperty(class, name, config)
|
||||||
if not rawget(class, '_properties') then
|
if not rawget(class, '_properties') then
|
||||||
class._properties = {}
|
class._properties = {}
|
||||||
@@ -67,6 +81,11 @@ function PropertySystem.defineProperty(class, name, config)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Combines multiple properties into a single getter and setter
|
||||||
|
--- @shortDescription Combines multiple properties
|
||||||
|
--- @param class table The element class to combine the properties for
|
||||||
|
--- @param name string The name of the combined property
|
||||||
|
--- @vararg string The names of the properties to combine
|
||||||
function PropertySystem.combineProperties(class, name, ...)
|
function PropertySystem.combineProperties(class, name, ...)
|
||||||
local properties = {...}
|
local properties = {...}
|
||||||
for k,v in pairs(properties)do
|
for k,v in pairs(properties)do
|
||||||
@@ -94,6 +113,7 @@ function PropertySystem.combineProperties(class, name, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a blueprint of an element class with all its properties
|
--- Creates a blueprint of an element class with all its properties
|
||||||
|
--- @shortDescription Creates a blueprint of an element class
|
||||||
--- @param elementClass table The element class to create a blueprint from
|
--- @param elementClass table The element class to create a blueprint from
|
||||||
--- @return table blueprint A table containing all property definitions
|
--- @return table blueprint A table containing all property definitions
|
||||||
function PropertySystem.blueprint(elementClass, properties, basalt, parent)
|
function PropertySystem.blueprint(elementClass, properties, basalt, parent)
|
||||||
@@ -198,6 +218,11 @@ function PropertySystem.blueprint(elementClass, properties, basalt, parent)
|
|||||||
return blueprint
|
return blueprint
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creates an element from a blueprint
|
||||||
|
--- @shortDescription Creates an element from a blueprint
|
||||||
|
--- @param elementClass table The element class to create from the blueprint
|
||||||
|
--- @param blueprint table The blueprint to create the element from
|
||||||
|
--- @return table element The created element
|
||||||
function PropertySystem.createFromBlueprint(elementClass, blueprint, basalt)
|
function PropertySystem.createFromBlueprint(elementClass, blueprint, basalt)
|
||||||
local element = elementClass.new({}, basalt)
|
local element = elementClass.new({}, basalt)
|
||||||
for name, value in pairs(blueprint._values) do
|
for name, value in pairs(blueprint._values) do
|
||||||
@@ -211,6 +236,9 @@ function PropertySystem.createFromBlueprint(elementClass, blueprint, basalt)
|
|||||||
return element
|
return element
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initializes the PropertySystem IS USED INTERNALLY
|
||||||
|
--- @shortDescription Initializes the PropertySystem
|
||||||
|
--- @return table self The PropertySystem
|
||||||
function PropertySystem:__init()
|
function PropertySystem:__init()
|
||||||
self._values = {}
|
self._values = {}
|
||||||
self._observers = {}
|
self._observers = {}
|
||||||
@@ -308,6 +336,11 @@ function PropertySystem:__init()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Update call for a property IS USED INTERNALLY
|
||||||
|
--- @shortDescription Update call for a property
|
||||||
|
--- @param name string The name of the property
|
||||||
|
--- @param value any The value of the property
|
||||||
|
--- @return table self The PropertySystem
|
||||||
function PropertySystem:_updateProperty(name, value)
|
function PropertySystem:_updateProperty(name, value)
|
||||||
local oldValue = self._values[name]
|
local oldValue = self._values[name]
|
||||||
if type(oldValue) == "function" then
|
if type(oldValue) == "function" then
|
||||||
@@ -327,14 +360,25 @@ function PropertySystem:_updateProperty(name, value)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Observers a property
|
||||||
|
--- @shortDescription Observers a property
|
||||||
|
--- @param name string The name of the property
|
||||||
|
--- @param callback function The callback function to call when the property changes
|
||||||
|
--- @return table self The PropertySystem
|
||||||
function PropertySystem:observe(name, callback)
|
function PropertySystem:observe(name, callback)
|
||||||
self._observers[name] = self._observers[name] or {}
|
self._observers[name] = self._observers[name] or {}
|
||||||
table.insert(self._observers[name], callback)
|
table.insert(self._observers[name], callback)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Removes an observer from a property
|
||||||
|
--- @NshortDescription Removes an observer from a property
|
||||||
|
--- @param name string The name of the property
|
||||||
|
--- @param callback function The callback function to remove
|
||||||
|
--- @return table self The PropertySystem
|
||||||
function PropertySystem:removeObserver(name, callback)
|
function PropertySystem:removeObserver(name, callback)
|
||||||
if self._observers[name] then
|
if self._observers[name] then
|
||||||
for i, cb in ipairs(self._observers[name]) do
|
for i, cb in ipairs(self._observers[name]) do
|
||||||
@@ -350,6 +394,10 @@ function PropertySystem:removeObserver(name, callback)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Removes all observers from a property
|
||||||
|
--- @shortDescription Removes all observers from a property
|
||||||
|
--- @param name string The name of the property
|
||||||
|
--- @return table self The PropertySystem
|
||||||
function PropertySystem:removeAllObservers(name)
|
function PropertySystem:removeAllObservers(name)
|
||||||
if name then
|
if name then
|
||||||
self._observers[name] = nil
|
self._observers[name] = nil
|
||||||
@@ -359,12 +407,21 @@ function PropertySystem:removeAllObservers(name)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Adds a property to the PropertySystem on instance level
|
||||||
|
--- @shortDescription Adds a property to the PropertySystem on instance level
|
||||||
|
--- @param name string The name of the property
|
||||||
|
--- @param config table The configuration of the property
|
||||||
|
--- @return table self The PropertySystem
|
||||||
function PropertySystem:instanceProperty(name, config)
|
function PropertySystem:instanceProperty(name, config)
|
||||||
PropertySystem.defineProperty(self, name, config)
|
PropertySystem.defineProperty(self, name, config)
|
||||||
self._values[name] = config.default
|
self._values[name] = config.default
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Removes a property from the PropertySystem on instance level
|
||||||
|
--- @shortDescription Removes a property from the PropertySystem
|
||||||
|
--- @param name string The name of the property
|
||||||
|
--- @return table self The PropertySystem
|
||||||
function PropertySystem:removeProperty(name)
|
function PropertySystem:removeProperty(name)
|
||||||
self._values[name] = nil
|
self._values[name] = nil
|
||||||
self._properties[name] = nil
|
self._properties[name] = nil
|
||||||
@@ -376,6 +433,10 @@ function PropertySystem:removeProperty(name)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets a property configuration
|
||||||
|
--- @shortDescription Gets a property configuration
|
||||||
|
--- @param name string The name of the property
|
||||||
|
--- @return table config The configuration of the property
|
||||||
function PropertySystem:getPropertyConfig(name)
|
function PropertySystem:getPropertyConfig(name)
|
||||||
return self._properties[name]
|
return self._properties[name]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
local colorChars = require("libraries/colorHex")
|
||||||
|
|
||||||
|
--- This is the render module for Basalt. It tries to mimic the functionality of the `term` API. but with additional
|
||||||
|
--- functionality. It also has a buffer system to reduce the number of calls
|
||||||
--- @class Render
|
--- @class Render
|
||||||
--- @field terminal table The terminal object to render to
|
--- @field terminal table The terminal object to render to
|
||||||
--- @field width number The width of the render
|
--- @field width number The width of the render
|
||||||
@@ -8,7 +12,6 @@
|
|||||||
--- @field blink boolean Whether the cursor should blink
|
--- @field blink boolean Whether the cursor should blink
|
||||||
local Render = {}
|
local Render = {}
|
||||||
Render.__index = Render
|
Render.__index = Render
|
||||||
local colorChars = require("libraries/colorHex")
|
|
||||||
|
|
||||||
--- Creates a new Render object
|
--- Creates a new Render object
|
||||||
--- @param terminal table The terminal object to render to
|
--- @param terminal table The terminal object to render to
|
||||||
@@ -39,7 +42,7 @@ end
|
|||||||
--- @param y number The y position of the rectangle
|
--- @param y number The y position of the rectangle
|
||||||
--- @param width number The width of the rectangle
|
--- @param width number The width of the rectangle
|
||||||
--- @param height number The height of the rectangle
|
--- @param height number The height of the rectangle
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:addDirtyRect(x, y, width, height)
|
function Render:addDirtyRect(x, y, width, height)
|
||||||
table.insert(self.buffer.dirtyRects, {
|
table.insert(self.buffer.dirtyRects, {
|
||||||
x = x,
|
x = x,
|
||||||
@@ -56,7 +59,7 @@ end
|
|||||||
--- @param text string The text to blit
|
--- @param text string The text to blit
|
||||||
--- @param fg string The foreground color of the text
|
--- @param fg string The foreground color of the text
|
||||||
--- @param bg string The background color of the text
|
--- @param bg string The background color of the text
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:blit(x, y, text, fg, bg)
|
function Render:blit(x, y, text, fg, bg)
|
||||||
if y < 1 or y > self.height then return self end
|
if y < 1 or y > self.height then return self end
|
||||||
if(#text ~= #fg or #text ~= #bg)then
|
if(#text ~= #fg or #text ~= #bg)then
|
||||||
@@ -79,7 +82,7 @@ end
|
|||||||
--- @param text string The text to blit
|
--- @param text string The text to blit
|
||||||
--- @param fg colors The foreground color of the text
|
--- @param fg colors The foreground color of the text
|
||||||
--- @param bg colors The background color of the text
|
--- @param bg colors The background color of the text
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:multiBlit(x, y, width, height, text, fg, bg)
|
function Render:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
if y < 1 or y > self.height then return self end
|
if y < 1 or y > self.height then return self end
|
||||||
if(#text ~= #fg or #text ~= #bg)then
|
if(#text ~= #fg or #text ~= #bg)then
|
||||||
@@ -108,6 +111,7 @@ end
|
|||||||
--- @param y number The y position to blit to
|
--- @param y number The y position to blit to
|
||||||
--- @param text string The text to blit
|
--- @param text string The text to blit
|
||||||
--- @param fg colors The foreground color of the text
|
--- @param fg colors The foreground color of the text
|
||||||
|
--- @return Render
|
||||||
function Render:textFg(x, y, text, fg)
|
function Render:textFg(x, y, text, fg)
|
||||||
if y < 1 or y > self.height then return self end
|
if y < 1 or y > self.height then return self end
|
||||||
fg = colorChars[fg] or "0"
|
fg = colorChars[fg] or "0"
|
||||||
@@ -124,7 +128,7 @@ end
|
|||||||
--- @param y number The y position to blit to
|
--- @param y number The y position to blit to
|
||||||
--- @param text string The text to blit
|
--- @param text string The text to blit
|
||||||
--- @param bg colors The background color of the text
|
--- @param bg colors The background color of the text
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:textBg(x, y, text, bg)
|
function Render:textBg(x, y, text, bg)
|
||||||
if y < 1 or y > self.height then return self end
|
if y < 1 or y > self.height then return self end
|
||||||
bg = colorChars[bg] or "f"
|
bg = colorChars[bg] or "f"
|
||||||
@@ -140,7 +144,7 @@ end
|
|||||||
--- @param x number The x position to blit to
|
--- @param x number The x position to blit to
|
||||||
--- @param y number The y position to blit to
|
--- @param y number The y position to blit to
|
||||||
--- @param text string The text to blit
|
--- @param text string The text to blit
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:text(x, y, text)
|
function Render:text(x, y, text)
|
||||||
if y < 1 or y > self.height then return self end
|
if y < 1 or y > self.height then return self end
|
||||||
|
|
||||||
@@ -154,7 +158,7 @@ end
|
|||||||
--- @param x number The x position
|
--- @param x number The x position
|
||||||
--- @param y number The y position
|
--- @param y number The y position
|
||||||
--- @param fg string The foreground color to blit
|
--- @param fg string The foreground color to blit
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:fg(x, y, fg)
|
function Render:fg(x, y, fg)
|
||||||
if y < 1 or y > self.height then return self end
|
if y < 1 or y > self.height then return self end
|
||||||
|
|
||||||
@@ -168,7 +172,7 @@ end
|
|||||||
--- @param x number The x position
|
--- @param x number The x position
|
||||||
--- @param y number The y position
|
--- @param y number The y position
|
||||||
--- @param bg string The background color to blit
|
--- @param bg string The background color to blit
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:bg(x, y, bg)
|
function Render:bg(x, y, bg)
|
||||||
if y < 1 or y > self.height then return self end
|
if y < 1 or y > self.height then return self end
|
||||||
|
|
||||||
@@ -180,7 +184,7 @@ end
|
|||||||
|
|
||||||
--- Clears the screen
|
--- Clears the screen
|
||||||
--- @param bg colors The background color to clear the screen with
|
--- @param bg colors The background color to clear the screen with
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:clear(bg)
|
function Render:clear(bg)
|
||||||
local bgChar = colorChars[bg] or "f"
|
local bgChar = colorChars[bg] or "f"
|
||||||
for y=1, self.height do
|
for y=1, self.height do
|
||||||
@@ -193,7 +197,7 @@ function Render:clear(bg)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Renders the buffer to the screen
|
--- Renders the buffer to the screen
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:render()
|
function Render:render()
|
||||||
local mergedRects = {}
|
local mergedRects = {}
|
||||||
for _, rect in ipairs(self.buffer.dirtyRects) do
|
for _, rect in ipairs(self.buffer.dirtyRects) do
|
||||||
@@ -238,7 +242,7 @@ end
|
|||||||
--- Checks if two rectangles overlap
|
--- Checks if two rectangles overlap
|
||||||
--- @param r1 table The first rectangle
|
--- @param r1 table The first rectangle
|
||||||
--- @param r2 table The second rectangle
|
--- @param r2 table The second rectangle
|
||||||
--- @returns boolean
|
--- @return boolean
|
||||||
function Render:rectOverlaps(r1, r2)
|
function Render:rectOverlaps(r1, r2)
|
||||||
return not (r1.x + r1.width <= r2.x or
|
return not (r1.x + r1.width <= r2.x or
|
||||||
r2.x + r2.width <= r1.x or
|
r2.x + r2.width <= r1.x or
|
||||||
@@ -249,7 +253,7 @@ end
|
|||||||
--- Merges two rectangles
|
--- Merges two rectangles
|
||||||
--- @param target table The target rectangle
|
--- @param target table The target rectangle
|
||||||
--- @param source table The source rectangle
|
--- @param source table The source rectangle
|
||||||
--- @returns Render
|
--- @return Render
|
||||||
function Render:mergeRects(target, source)
|
function Render:mergeRects(target, source)
|
||||||
local x1 = math.min(target.x, source.x)
|
local x1 = math.min(target.x, source.x)
|
||||||
local y1 = math.min(target.y, source.y)
|
local y1 = math.min(target.y, source.y)
|
||||||
@@ -266,6 +270,7 @@ end
|
|||||||
--- @param x number The x position of the cursor
|
--- @param x number The x position of the cursor
|
||||||
--- @param y number The y position of the cursor
|
--- @param y number The y position of the cursor
|
||||||
--- @param blink boolean Whether the cursor should blink
|
--- @param blink boolean Whether the cursor should blink
|
||||||
|
--- @return Render
|
||||||
function Render:setCursor(x, y, blink)
|
function Render:setCursor(x, y, blink)
|
||||||
self.terminal.setCursorPos(x, y)
|
self.terminal.setCursorPos(x, y)
|
||||||
self.terminal.setCursorBlink(blink)
|
self.terminal.setCursorBlink(blink)
|
||||||
@@ -281,6 +286,7 @@ end
|
|||||||
--- @param width number The width of the area
|
--- @param width number The width of the area
|
||||||
--- @param height number The height of the area
|
--- @param height number The height of the area
|
||||||
--- @param bg colors The background color to clear the area with
|
--- @param bg colors The background color to clear the area with
|
||||||
|
--- @return Render
|
||||||
function Render:clearArea(x, y, width, height, bg)
|
function Render:clearArea(x, y, width, height, bg)
|
||||||
local bgChar = colorChars[bg] or "f"
|
local bgChar = colorChars[bg] or "f"
|
||||||
for dy=0, height-1 do
|
for dy=0, height-1 do
|
||||||
@@ -295,7 +301,7 @@ function Render:clearArea(x, y, width, height, bg)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Gets the size of the render
|
--- Gets the size of the render
|
||||||
--- @returns number, number
|
--- @return number, number
|
||||||
function Render:getSize()
|
function Render:getSize()
|
||||||
return self.width, self.height
|
return self.width, self.height
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,15 +11,10 @@ local function processFile(inputFile)
|
|||||||
local parsed = markdown.parseFile(inputFile)
|
local parsed = markdown.parseFile(inputFile)
|
||||||
local md = markdown.makeMarkdown(parsed)
|
local md = markdown.makeMarkdown(parsed)
|
||||||
|
|
||||||
local outputFile
|
local outputFile = "build_docs/docs/references/" .. inputFile:match("^src/(.+)"):gsub("%.lua$", "")
|
||||||
if inputFile:match("^src/[^/]+%.lua$") then
|
|
||||||
outputFile = "build_docs/docs/references/" .. inputFile:match("^src/(.+)"):gsub("%.lua$", ".md")
|
|
||||||
else
|
|
||||||
outputFile = "build_docs/docs/references/" .. inputFile:match("^src/(.+)"):gsub("%.lua$", ".md")
|
|
||||||
end
|
|
||||||
|
|
||||||
ensureDirectory(outputFile)
|
ensureDirectory(outputFile)
|
||||||
print(string.format("Processing: %s -> %s", inputFile, outputFile))
|
--print(string.format("Processing: %s -> %s", inputFile, outputFile))
|
||||||
|
|
||||||
markdown.saveToFile(outputFile, md)
|
markdown.saveToFile(outputFile, md)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ local commentTypes = {
|
|||||||
"private",
|
"private",
|
||||||
"protected",
|
"protected",
|
||||||
"field",
|
"field",
|
||||||
"vararg"
|
"vararg",
|
||||||
|
"splitClass"
|
||||||
}
|
}
|
||||||
|
|
||||||
local function extractComment(line)
|
local function extractComment(line)
|
||||||
@@ -71,6 +72,8 @@ function markdown.parse(content)
|
|||||||
local fields = {}
|
local fields = {}
|
||||||
local currentBlock = {type = "comment", desc = {}}
|
local currentBlock = {type = "comment", desc = {}}
|
||||||
local skipNextFunction = false
|
local skipNextFunction = false
|
||||||
|
local currentClass = "None"
|
||||||
|
local splitNextClass = false
|
||||||
|
|
||||||
for line in content:gsub("\r\n", "\n"):gmatch("([^\n]*)\n?") do
|
for line in content:gsub("\r\n", "\n"):gmatch("([^\n]*)\n?") do
|
||||||
if line:match("^%s*$") or line == "" then
|
if line:match("^%s*$") or line == "" then
|
||||||
@@ -87,6 +90,8 @@ function markdown.parse(content)
|
|||||||
table.insert(currentBlock.desc, value)
|
table.insert(currentBlock.desc, value)
|
||||||
elseif(commentType == "private")or(commentType == "protected")then
|
elseif(commentType == "private")or(commentType == "protected")then
|
||||||
skipNextFunction = true
|
skipNextFunction = true
|
||||||
|
elseif(commentType == "splitClass")then
|
||||||
|
splitNextClass = true
|
||||||
else
|
else
|
||||||
if(commentType == "module")then
|
if(commentType == "module")then
|
||||||
currentBlock.usageIsActive = false
|
currentBlock.usageIsActive = false
|
||||||
@@ -96,6 +101,13 @@ function markdown.parse(content)
|
|||||||
currentBlock.usageIsActive = false
|
currentBlock.usageIsActive = false
|
||||||
currentBlock.type = "class"
|
currentBlock.type = "class"
|
||||||
currentBlock.className = value
|
currentBlock.className = value
|
||||||
|
currentBlock.splitClass = splitNextClass
|
||||||
|
splitNextClass = false
|
||||||
|
currentClass = value
|
||||||
|
fields[currentClass] = {}
|
||||||
|
properties[currentClass] = {}
|
||||||
|
combinedProperties[currentClass] = {}
|
||||||
|
events[currentClass] = {}
|
||||||
end
|
end
|
||||||
if(commentType == "usage")then
|
if(commentType == "usage")then
|
||||||
currentBlock.usage = currentBlock.usage or {}
|
currentBlock.usage = currentBlock.usage or {}
|
||||||
@@ -110,15 +122,17 @@ function markdown.parse(content)
|
|||||||
currentBlock.shortDescription = value
|
currentBlock.shortDescription = value
|
||||||
elseif(commentType == "property")then
|
elseif(commentType == "property")then
|
||||||
currentBlock = {type = "comment", desc = {}}
|
currentBlock = {type = "comment", desc = {}}
|
||||||
table.insert(properties, value)
|
table.insert(properties[currentClass], value)
|
||||||
elseif(commentType == "combinedProperty")then
|
elseif(commentType == "combinedProperty")then
|
||||||
currentBlock = {type = "comment", desc = {}}
|
currentBlock = {type = "comment", desc = {}}
|
||||||
table.insert(combinedProperties, value)
|
table.insert(combinedProperties[currentClass], value)
|
||||||
elseif(commentType == "field")then
|
elseif(commentType == "field")then
|
||||||
table.insert(fields, value)
|
if currentClass then
|
||||||
|
table.insert(fields[currentClass], value)
|
||||||
|
end
|
||||||
elseif(commentType == "event")then
|
elseif(commentType == "event")then
|
||||||
currentBlock = {type = "comment", desc = {}}
|
currentBlock = {type = "comment", desc = {}}
|
||||||
table.insert(events, value)
|
table.insert(events[currentClass], value)
|
||||||
else
|
else
|
||||||
currentBlock.usageIsActive = false
|
currentBlock.usageIsActive = false
|
||||||
currentBlock[commentType] = currentBlock[commentType] or {}
|
currentBlock[commentType] = currentBlock[commentType] or {}
|
||||||
@@ -136,6 +150,7 @@ function markdown.parse(content)
|
|||||||
if funcName then
|
if funcName then
|
||||||
currentBlock.func = funcName
|
currentBlock.func = funcName
|
||||||
currentBlock.type = "function"
|
currentBlock.type = "function"
|
||||||
|
currentBlock.className = currentClass
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -168,6 +183,7 @@ function markdown.parse(content)
|
|||||||
for _, block in ipairs(functionBlocks) do
|
for _, block in ipairs(functionBlocks) do
|
||||||
table.insert(markdown.blocks, block)
|
table.insert(markdown.blocks, block)
|
||||||
end
|
end
|
||||||
|
return markdown.blocks
|
||||||
end
|
end
|
||||||
|
|
||||||
local function markdownFunction(block)
|
local function markdownFunction(block)
|
||||||
@@ -221,12 +237,12 @@ local function markdownFunction(block)
|
|||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
local function markdownFields()
|
local function markdownFields(className)
|
||||||
if(#markdown.blocks.fields<=0)then
|
if(#markdown.blocks.fields[className]<=0)then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
local output = "\n## Fields\n\n|Field|Type|Description|\n|---|---|---|\n"
|
local output = "\n## Fields\n\n|Field|Type|Description|\n|---|---|---|\n"
|
||||||
for _, block in pairs(markdown.blocks.fields) do
|
for _, block in pairs(markdown.blocks.fields[className]) do
|
||||||
local name, rest = block:match("([%w_]+)%s+(.+)")
|
local name, rest = block:match("([%w_]+)%s+(.+)")
|
||||||
if name and rest then
|
if name and rest then
|
||||||
local fieldType, desc = rest:match("([^%s].-)%s+([^%s].*)")
|
local fieldType, desc = rest:match("([^%s].-)%s+([^%s].*)")
|
||||||
@@ -242,40 +258,47 @@ local function markdownFields()
|
|||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
local function markdownProperties()
|
local function markdownProperties(className)
|
||||||
if(#markdown.blocks.properties<=0)then
|
if(#markdown.blocks.properties[className]<=0)then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
local output = "\n## Properties\n\n|Property|Type|Default|Description|\n|---|---|---|---|\n"
|
local output = "\n## Properties\n\n|Property|Type|Default|Description|\n|---|---|---|---|\n"
|
||||||
for _, block in pairs(markdown.blocks.properties) do
|
for _, block in pairs(markdown.blocks.properties[className]) do
|
||||||
local name, paramType, defaultValue, desc = block:match("([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+(.*)")
|
local name, paramType, defaultValue, desc = block:match("([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+(.*)")
|
||||||
output = output .. string.format("|%s|%s|%s|%s\n", name, paramType, defaultValue, desc)
|
output = output .. string.format("|%s|%s|%s|%s\n", name, paramType, defaultValue, desc)
|
||||||
end
|
end
|
||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
local function markdownCombinedProperties()
|
local function markdownCombinedProperties(className)
|
||||||
if(markdown.blocks.combinedProperties==nil)then
|
if(markdown.blocks.combinedProperties[className]==nil)then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
if(#markdown.blocks.combinedProperties<=0)then
|
if(#markdown.blocks.combinedProperties[className]<=0)then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
local output = "\n## Combined Properties\n\n|Name|Properties|Description|\n|---|---|---|\n"
|
local output = "\n## Combined Properties\n\n|Name|Properties|Description|\n|---|---|---|\n"
|
||||||
for _, block in pairs(markdown.blocks.combinedProperties) do
|
for _, block in pairs(markdown.blocks.combinedProperties[className]) do
|
||||||
local name, paramType, defaultValue, desc = block:match("([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+(.*)")
|
local name, params, desc = block:match("([%w_]+)%s+{([^}]+)}%s*(.*)")
|
||||||
output = output .. string.format("|%s|%s|%s|%s\n", name, paramType, defaultValue, desc)
|
if name and params then
|
||||||
|
local formattedParams = params:gsub("%s*,%s*", ", ")
|
||||||
|
output = output .. string.format("|%s|`%s`|%s|\n",
|
||||||
|
name,
|
||||||
|
formattedParams,
|
||||||
|
desc or ""
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
local function markdownEvents()
|
local function markdownEvents(className)
|
||||||
if(#markdown.blocks.events<=0)then
|
if(#markdown.blocks.events[className]<=0)then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
local output = "\n## Events\n\n|Event|Parameters|Description|\n|---|---|---|\n"
|
local output = "\n## Events\n\n|Event|Parameters|Description|\n|---|---|---|\n"
|
||||||
|
|
||||||
for _, event in pairs(markdown.blocks.events) do
|
for _, event in pairs(markdown.blocks.events[className]) do
|
||||||
local name, params, desc = event:match("([%w_]+)%s+{([^}]+)}%s*(.*)")
|
local name, params, desc = event:match("([%w_]+)%s+{([^}]+)}%s*(.*)")
|
||||||
if name and params then
|
if name and params then
|
||||||
local formattedParams = params:gsub("%s*,%s*", ", ")
|
local formattedParams = params:gsub("%s*,%s*", ", ")
|
||||||
@@ -289,12 +312,21 @@ local function markdownEvents()
|
|||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
local function markdownModuleOrClassFunctions()
|
local function markdownClassFunctionList(className)
|
||||||
if(#markdown.blocks<=0)then
|
if(#markdown.blocks<=0)then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
local fList = {}
|
||||||
|
for _, v in pairs(markdown.blocks) do
|
||||||
|
if(v.type=="function")then
|
||||||
|
if(v.className==className)then
|
||||||
|
table.insert(fList, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local output = "\n## Functions\n\n|Method|Returns|Description|\n|---|---|---|\n"
|
local output = "\n## Functions\n\n|Method|Returns|Description|\n|---|---|---|\n"
|
||||||
for _, block in pairs(markdown.blocks) do
|
for _, block in pairs(fList) do
|
||||||
if block.type == "function" then
|
if block.type == "function" then
|
||||||
output = output .. "|[" .. block.func .. "](#" .. block.func .. ")|"
|
output = output .. "|[" .. block.func .. "](#" .. block.func .. ")|"
|
||||||
if(block["return"]~=nil)then
|
if(block["return"]~=nil)then
|
||||||
@@ -313,33 +345,6 @@ local function markdownModuleOrClassFunctions()
|
|||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
local function markdownModule(block)
|
|
||||||
local output = "# ".. block.moduleName.."\n"
|
|
||||||
if(block.usage~=nil)then
|
|
||||||
if(#block.usage > 0)then
|
|
||||||
for k,v in pairs(block.usage) do
|
|
||||||
local _output = "\n### Usage\n ```lua\n"
|
|
||||||
for _, line in pairs(v.content) do
|
|
||||||
_output = _output .. line .. "\n"
|
|
||||||
end
|
|
||||||
_output = _output .. "```\n"
|
|
||||||
table.insert(block.desc, v.line, _output)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for _, line in pairs(block.desc) do
|
|
||||||
output = output .. line .. "\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
output = output .. markdownFields()
|
|
||||||
output = output .. markdownProperties()
|
|
||||||
output = output .. markdownCombinedProperties()
|
|
||||||
output = output .. markdownEvents()
|
|
||||||
output = output .. markdownModuleOrClassFunctions(block)
|
|
||||||
output = output .. "\n"
|
|
||||||
return output
|
|
||||||
end
|
|
||||||
|
|
||||||
local function markdownClass(block)
|
local function markdownClass(block)
|
||||||
local output = "# ".. block.className.."\n"
|
local output = "# ".. block.className.."\n"
|
||||||
if(block.usage~=nil)then
|
if(block.usage~=nil)then
|
||||||
@@ -358,32 +363,38 @@ local function markdownClass(block)
|
|||||||
output = output .. line .. "\n"
|
output = output .. line .. "\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
output = output .. markdownFields()
|
output = output .. markdownFields(block.className)
|
||||||
output = output .. markdownProperties()
|
output = output .. markdownProperties(block.className)
|
||||||
output = output .. markdownCombinedProperties()
|
output = output .. markdownCombinedProperties(block.className)
|
||||||
output = output .. markdownEvents()
|
output = output .. markdownEvents(block.className)
|
||||||
output = output .. markdownModuleOrClassFunctions(block)
|
output = output .. markdownClassFunctionList(block.className) .. "\n"
|
||||||
|
for k,v in pairs(markdown.blocks) do
|
||||||
|
if(v.type=="function")then
|
||||||
|
if(v.className==block.className)then
|
||||||
|
output = output .. markdownFunction(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
output = output .. "\n"
|
output = output .. "\n"
|
||||||
return output
|
return output
|
||||||
end
|
end
|
||||||
|
|
||||||
function markdown.makeMarkdown()
|
function markdown.makeMarkdown()
|
||||||
|
local classes = {}
|
||||||
local output = ""
|
local output = ""
|
||||||
for _, block in pairs(markdown.blocks) do
|
for _, block in pairs(markdown.blocks) do
|
||||||
if block.type == "function" then
|
if block.type == "comment" then
|
||||||
output = output .. markdownFunction(block)
|
|
||||||
elseif block.type == "comment" then
|
|
||||||
for _, line in pairs(block.desc) do
|
for _, line in pairs(block.desc) do
|
||||||
output = output .. line .. "\n"
|
output = output .. line .. "\n"
|
||||||
end
|
end
|
||||||
elseif block.type == "module" then
|
--[[elseif block.type == "module" then
|
||||||
output = output .. markdownModule(block)
|
output = output .. markdownModule(block)]]
|
||||||
elseif block.type == "class" then
|
elseif block.type == "class" then
|
||||||
output = output .. markdownClass(block)
|
classes[block.className] = {content=markdownClass(block), data=block}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return output
|
return classes
|
||||||
end
|
end
|
||||||
|
|
||||||
function markdown.parseFile(source)
|
function markdown.parseFile(source)
|
||||||
@@ -399,13 +410,56 @@ function markdown.parseFile(source)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function markdown.saveToFile(source, output)
|
function markdown.saveToFile(source, output)
|
||||||
local file = io.open(source, "w")
|
local mainFile
|
||||||
if not file then
|
local mainFileCount = 0
|
||||||
error("Could not open file for writing: " .. source)
|
|
||||||
|
local sortedOutput = {}
|
||||||
|
for _, v in pairs(output) do
|
||||||
|
table.insert(sortedOutput, v)
|
||||||
end
|
end
|
||||||
|
|
||||||
file:write(output)
|
table.sort(sortedOutput, function(a, b)
|
||||||
file:close()
|
return a.data.className < b.data.className
|
||||||
|
end)
|
||||||
|
|
||||||
|
for k,v in pairs(sortedOutput) do
|
||||||
|
if(v.data.splitClass)then
|
||||||
|
local subFile = io.open(source.."_"..v.data.className..".md", "w")
|
||||||
|
if not subFile then
|
||||||
|
error("Could not open file for writing: " .. source.."_"..v.data.className..".md")
|
||||||
|
end
|
||||||
|
subFile:write(v.content)
|
||||||
|
subFile:close()
|
||||||
|
else
|
||||||
|
if(mainFile==nil)then
|
||||||
|
mainFile = io.open(source..".md", "w")
|
||||||
|
end
|
||||||
|
if(mainFileCount>0)then
|
||||||
|
mainFile:write("---\n<br>\n\n")
|
||||||
|
end
|
||||||
|
if not mainFile then
|
||||||
|
error("Could not open file for writing: " .. source..".md")
|
||||||
|
end
|
||||||
|
mainFile:write(v.content)
|
||||||
|
mainFileCount = mainFileCount + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
if(mainFile~=nil)then
|
||||||
|
mainFile:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--[[local file = io.open(source..".md", "w")
|
||||||
|
if not file then
|
||||||
|
error("Could not open file for writing: " .. source..".md")
|
||||||
|
end
|
||||||
|
for _, content in pairs(output) do
|
||||||
|
file:write(content)
|
||||||
|
end
|
||||||
|
file:close()]]
|
||||||
end
|
end
|
||||||
|
|
||||||
return markdown
|
return markdown
|
||||||
Reference in New Issue
Block a user