From f911e9bce83b710480d0d90c91e840f6ca57dece Mon Sep 17 00:00:00 2001 From: Robert Jelic <36573031+NoryiE@users.noreply.github.com> Date: Sun, 6 Apr 2025 00:57:19 +0200 Subject: [PATCH] Docs update + some element updates --- src/elements/BarChart.lua | 13 ++++++- src/elements/BigFont.lua | 7 ++-- src/elements/Container.lua | 5 +-- src/elements/Display.lua | 5 ++- src/elements/Dropdown.lua | 6 ++++ src/elements/Flexbox.lua | 10 +++++- src/elements/Graph.lua | 32 +++++++++++++++++ src/elements/Input.lua | 10 ++++++ src/elements/LineChart.lua | 13 ++++++- src/elements/ProgressBar.lua | 27 ++++++++++++--- src/elements/Table.lua | 67 +++++++++++++++++++++++------------- 11 files changed, 159 insertions(+), 36 deletions(-) diff --git a/src/elements/BarChart.lua b/src/elements/BarChart.lua index 493923d..19d475a 100644 --- a/src/elements/BarChart.lua +++ b/src/elements/BarChart.lua @@ -5,7 +5,18 @@ local tHex = require("libraries/colorHex") --- @configDescription A bar chart element based on the graph element. ---@configDefault false ---- This is the bar chart class. It is based on the graph element. It draws bar based points. +--- The Bar Chart element is designed for visualizing data series as vertical bars. It displays multiple values as side-by-side bars where each bar's height represents its value. +--- @usage local chart = main:addBarChart() +--- @usage :addSeries("input", " ", colors.green, colors.green, 5) +--- @usage :addSeries("output", " ", colors.red, colors.red, 5) +--- @usage +--- @usage basalt.schedule(function() +--- @usage while true do +--- @usage chart:addPoint("input", math.random(1,100)) +--- @usage chart:addPoint("output", math.random(1,100)) +--- @usage sleep(2) +--- @usage end +--- @usage end) --- @class BarChart : Graph local BarChart = setmetatable({}, BaseGraph) BarChart.__index = BarChart diff --git a/src/elements/BigFont.lua b/src/elements/BigFont.lua index 687110d..afdaea9 100644 --- a/src/elements/BigFont.lua +++ b/src/elements/BigFont.lua @@ -11,7 +11,7 @@ -- 5. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. -- NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. YOU ACKNOWLEDGE THAT THIS SOFTWARE IS NOT DESIGNED, LICENSED OR INTENDED FOR USE IN THE DESIGN, CONSTRUCTION, OPERATION OR MAINTENANCE OF ANY NUCLEAR FACILITY. --- Basalt - Nyorie: Please don't copy paste this code to your projects, this code is slightly changed (to fit the way basalt draws stuff), if you want the original code, checkout this: +-- Basalt - Nyorie: Please don't copy paste this code to your projects, this code is slightly changed (to fit the way basalt draws elements), if you want the original code, checkout this: -- http://www.computercraft.info/forums2/index.php?/topic/25367-bigfont-api-write-bigger-letters-v10/ ---@class BigFontText local tHex = require("libraries/colorHex") @@ -137,13 +137,16 @@ local function makeText(nSize, sString, nFC, nBC, bBlit) return {tText, tFront, tBack} end +--- This part has nothing to do with Wojbie's BigFont API: local elementManager = require("elementManager") local VisualElement = elementManager.getElement("VisualElement") ---@cofnigDescription The BigFont is a text element that displays large text. ---@configDefault false ---- The BigFont element is a text element that displays large text. +--- The BigFont element is a text element that displays larger text. It uses Wojbie's BigFont API to render the text in a larger font size. Credits to Wojbie for the original API. +--- @usage local font = main:addBigFont() +--- @usage font:setText("Hello World!") ---@class BigFont : VisualElement local BigFont = setmetatable({}, VisualElement) BigFont.__index = BigFont diff --git a/src/elements/Container.lua b/src/elements/Container.lua index 23678af..006d13a 100644 --- a/src/elements/Container.lua +++ b/src/elements/Container.lua @@ -6,8 +6,9 @@ local split = require("libraries/utils").split ---@configDescription The container class. It is a visual element that can contain other elements. It is the base class for all containers ---@configDefault true ---- 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. +--- The Container class serves as a fundamental building block for organizing UI elements. It acts as a parent element that can hold and manage child elements, providing layout management, event propagation, and rendering capabilities. Used as base class for Frames, Windows, and other container-like elements. +--- @usage local container = basalt.getMainFrame() +--- @usage container:addButton() -- Add a child element ---@class Container : VisualElement local Container = setmetatable({}, VisualElement) Container.__index = Container diff --git a/src/elements/Display.lua b/src/elements/Display.lua index 8312b0f..38053d2 100644 --- a/src/elements/Display.lua +++ b/src/elements/Display.lua @@ -6,7 +6,10 @@ local colorHex = require("libraries/colorHex") ---@configDescription The Display is a special element which uses the cc window API which you can use. ---@configDefault false ---- The Display is a special element where you can use the window (term) API to draw on a element, useful when you need to use external APIs. +--- The Display is a special element where you can use the window (term) API to draw on the display, useful when you need to use external APIs. +--- @usage local display = main:addDisplay() -- Create a display element +--- @usage local displayWindow = display:getWindow() -- Get the window object of the display +--- @usage displayWindow.write("Hello World!") -- Write "Hello World!" to the display ---@class Display : VisualElement local Display = setmetatable({}, VisualElement) Display.__index = Display diff --git a/src/elements/Dropdown.lua b/src/elements/Dropdown.lua index 43ca119..f13e229 100644 --- a/src/elements/Dropdown.lua +++ b/src/elements/Dropdown.lua @@ -6,6 +6,12 @@ local tHex = require("libraries/colorHex") ---@configDefault false --- This is the dropdown class. It is a visual element that can show a list of selectable items in a dropdown menu. +--- @usage local dropdown = main:addDropdown() +--- @usage dropdown:setItems({ +--- @usage {text = "Item 1", callback = function() basalt.LOGGER.debug("Item 1 selected") end}, +--- @usage {text = "Item 2", callback = function() basalt.LOGGER.debug("Item 2 selected") end}, +--- @usage {text = "Item 3", callback = function() basalt.LOGGER.debug("Item 3 selected") end}, +--- @usage }) ---@class Dropdown : List local Dropdown = setmetatable({}, List) Dropdown.__index = Dropdown diff --git a/src/elements/Flexbox.lua b/src/elements/Flexbox.lua index a33691c..b03c89b 100644 --- a/src/elements/Flexbox.lua +++ b/src/elements/Flexbox.lua @@ -3,6 +3,15 @@ local Container = elementManager.getElement("Container") ---@configDescription A flexbox container that arranges its children in a flexible layout. --- This is the Flexbox class. It is a container that arranges its children in a flexible layout. +--- @usage local flex = main:addFlexbox({background=colors.black, width=30, height=10}) +--- @usage flex:addButton():setFlexGrow(1) +--- @usage flex:addButton():setFlexGrow(1) +--- @usage flex:addButton():setFlexGrow(1) +--- The flexbox element adds the following properties to its children: +--- +--- @usage flex:addButton():setFlexGrow(1) -- The flex-grow property defines the ability for a flex item to grow if necessary. +--- @usage flex:addButton():setFlexShrink(1) -- The flex-shrink property defines the ability for a flex item to shrink if necessary. +--- @usage flex:addButton():setFlexBasis(1) -- The flex-basis property defines the default size of an element before the remaining space is distributed. ---@class Flexbox : Container local Flexbox = setmetatable({}, Container) Flexbox.__index = Flexbox @@ -307,7 +316,6 @@ function Flexbox:addLineBreak() end --- @shortDescription Renders the flexbox and its children ---- @return Flexbox self The flexbox instance --- @protected function Flexbox:render() if(self.get("flexUpdateLayout"))then diff --git a/src/elements/Graph.lua b/src/elements/Graph.lua index e7ef09c..2b23583 100644 --- a/src/elements/Graph.lua +++ b/src/elements/Graph.lua @@ -5,6 +5,17 @@ local tHex = require("libraries/colorHex") ---@configDefault false --- This is the base class for all graph elements. It is a point based graph. +--- @usage local graph = main:addGraph() +--- @usage :addSeries("input", " ", colors.green, colors.green, 10) +--- @usage :addSeries("output", " ", colors.red, colors.red, 10) +--- @usage +--- @usage basalt.schedule(function() +--- @usage while true do +--- @usage graph:addPoint("input", math.random(1,100)) +--- @usage graph:addPoint("output", math.random(1,100)) +--- @usage sleep(2) +--- @usage end +--- @usage end) --- @class Graph : VisualElement local Graph = setmetatable({}, VisualElement) Graph.__index = Graph @@ -158,6 +169,27 @@ function Graph:setSeriesPointCount(name, count) return self end +--- Clears all points from a series +--- @shortDescription Clears all points from a series +--- @param name? string The name of the series +--- @return Graph self The graph instance +function Graph:clear(seriesName) + local series = self.get("series") + if seriesName then + for _, s in ipairs(series) do + if s.name == seriesName then + s.data = {} + break + end + end + else + for _, s in ipairs(series) do + s.data = {} + end + end + return self +end + --- @shortDescription Renders the graph --- @protected function Graph:render() diff --git a/src/elements/Input.lua b/src/elements/Input.lua index fc87024..9efea63 100644 --- a/src/elements/Input.lua +++ b/src/elements/Input.lua @@ -56,6 +56,12 @@ function Input:init(props, basalt) return self end +--- Sets the cursor position and color +--- @shortDescription Sets the cursor position and color +--- @param x number The x position of the cursor +--- @param y number The y position of the cursor +--- @param blink boolean Whether the cursor should blink +--- @param color number The color of the cursor function Input:setCursor(x, y, blink, color) x = math.min(self.get("width"), math.max(1, x)) return VisualElement.setCursor(self, x, y, blink, color) @@ -168,12 +174,16 @@ function Input:updateViewport() return self end +--- @shortDescription Handles a focus event +--- @protected function Input:focus() VisualElement.focus(self) self:setCursor(self.get("cursorPos") - self.get("viewOffset"), 1, true, self.get("cursorColor") or self.get("foreground")) self:updateRender() end +--- @shortDescription Handles a blur event +--- @protected function Input:blur() VisualElement.blur(self) self:setCursor(1, 1, false, self.get("cursorColor") or self.get("foreground")) diff --git a/src/elements/LineChart.lua b/src/elements/LineChart.lua index c1d9d86..d7f7eea 100644 --- a/src/elements/LineChart.lua +++ b/src/elements/LineChart.lua @@ -5,7 +5,18 @@ local tHex = require("libraries/colorHex") --- @configDescription A line chart element based on the graph element ---@configDefault false ---- This is the line chart class. It is based on the graph element. It draws lines between points. +--- The Line Chart element visualizes data series as connected line graphs. It plots points on a coordinate system and connects them with lines. +--- @usage local chart = main:addLineChart() +--- @usage :addSeries("input", " ", colors.green, colors.green, 10) +--- @usage :addSeries("output", " ", colors.red, colors.red, 10) +--- @usage +--- @usage basalt.schedule(function() +--- @usage while true do +--- @usage chart:addPoint("input", math.random(1,100)) +--- @usage chart:addPoint("output", math.random(1,100)) +--- @usage sleep(2) +--- @usage end +--- @usage end) --- @class LineChart : Graph local LineChart = setmetatable({}, Graph) LineChart.__index = LineChart diff --git a/src/elements/ProgressBar.lua b/src/elements/ProgressBar.lua index 9609927..2df7d7b 100644 --- a/src/elements/ProgressBar.lua +++ b/src/elements/ProgressBar.lua @@ -1,7 +1,11 @@ local VisualElement = require("elements/VisualElement") +local tHex = require("libraries/colorHex") --- This is the progress bar class. It provides a visual representation of progress --- with optional percentage display and customizable colors. +--- @usage local progressBar = main:addProgressBar() +--- @usage progressBar:setDirection("up") +--- @usage progressBar:setProgress(50) ---@class ProgressBar : VisualElement local ProgressBar = setmetatable({}, VisualElement) ProgressBar.__index = ProgressBar @@ -12,6 +16,8 @@ ProgressBar.defineProperty(ProgressBar, "progress", {default = 0, type = "number ProgressBar.defineProperty(ProgressBar, "showPercentage", {default = false, type = "boolean"}) ---@property progressColor color lime The color used for the filled portion of the progress bar ProgressBar.defineProperty(ProgressBar, "progressColor", {default = colors.black, type = "color"}) +---@property direction string right The direction of the progress bar ("up", "down", "left", "right") +ProgressBar.defineProperty(ProgressBar, "direction", {default = "right", type = "string"}) --- Creates a new ProgressBar instance --- @shortDescription Creates a new ProgressBar instance @@ -19,8 +25,8 @@ ProgressBar.defineProperty(ProgressBar, "progressColor", {default = colors.black --- @private function ProgressBar.new() local self = setmetatable({}, ProgressBar):__init() - self.set("width", 10) - self.set("height", 1) + self.set("width", 25) + self.set("height", 3) return self end @@ -39,17 +45,28 @@ end function ProgressBar:render() VisualElement.render(self) local width = self.get("width") + local height = self.get("height") local progress = math.min(100, math.max(0, self.get("progress"))) local fillWidth = math.floor((width * progress) / 100) + local fillHeight = math.floor((height * progress) / 100) + local direction = self.get("direction") + local progressColor = self.get("progressColor") - for i = 1, self.get("height") do - self:textBg(1, i, string.rep(" ", fillWidth), self.get("progressColor")) + if direction == "right" then + self:multiBlit(1, 1, fillWidth, height, " ", tHex[self.get("foreground")], tHex[progressColor]) + elseif direction == "left" then + self:multiBlit(width - fillWidth + 1, 1, fillWidth, height, " ", tHex[self.get("foreground")], tHex[progressColor]) + elseif direction == "up" then + self:multiBlit(1, height - fillHeight + 1, width, fillHeight, " ", tHex[self.get("foreground")], tHex[progressColor]) + elseif direction == "down" then + self:multiBlit(1, 1, width, fillHeight, " ", tHex[self.get("foreground")], tHex[progressColor]) end if self.get("showPercentage") then local text = tostring(progress).."%" local x = math.floor((width - #text) / 2) + 1 - self:textFg(x, 1, text, self.get("foreground")) + local y = math.floor((height - 1) / 2) + 1 + self:textFg(x, y, text, self.get("foreground")) end end diff --git a/src/elements/Table.lua b/src/elements/Table.lua index 3c5b641..3fe1b84 100644 --- a/src/elements/Table.lua +++ b/src/elements/Table.lua @@ -3,12 +3,25 @@ local tHex = require("libraries/colorHex") --- This is the table class. It provides a sortable data grid with customizable columns, --- row selection, and scrolling capabilities. +--- @usage local people = container:addTable():setWidth(40) +--- @usage people:setColumns({{name="Name",width=12}, {name="Age",width=10}, {name="Country",width=15}}) +--- @usage people:setData({{"Alice", 30, "USA"}, {"Bob", 25, "UK"}}) ---@class Table : VisualElement local Table = setmetatable({}, VisualElement) 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", canTriggerRender = true, setter=function(self, value) + local t = {} + for i, col in ipairs(value) do + if type(col) == "string" then + t[i] = {name = col, width = #col+1} + elseif type(col) == "table" then + t[i] = {name = col.name or "", width = col.width or #col.name+1} + end + end + return t +end}) ---@property data table {} The table data as array of row arrays Table.defineProperty(Table, "data", {default = {}, type = "table", canTriggerRender = true}) ---@property selectedRow number? nil Currently selected row index @@ -55,19 +68,24 @@ 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 +--- @param fn function? Optional custom sorting function --- @return Table self The Table instance -function Table:sortData(columnIndex) +function Table:sortData(columnIndex, fn) local data = self.get("data") local direction = self.get("sortDirection") - - table.sort(data, function(a, b) - if direction == "asc" then - return a[columnIndex] < b[columnIndex] - else - return a[columnIndex] > b[columnIndex] - end - end) - + if not fn then + table.sort(data, function(a, b) + if direction == "asc" then + return a[columnIndex] < b[columnIndex] + else + return a[columnIndex] > b[columnIndex] + end + end) + else + table.sort(data, function(a, b) + return fn(a[columnIndex], b[columnIndex]) + end) + end self.set("data", data) return self end @@ -117,27 +135,30 @@ end --- @return boolean handled Whether the event was handled --- @protected function Table:mouse_scroll(direction, x, y) - local data = self.get("data") - local height = self.get("height") - local visibleRows = height - 2 - local maxScroll = math.max(0, #data - visibleRows + 1) - local newOffset = math.min(maxScroll, math.max(0, self.get("scrollOffset") + direction)) + if(VisualElement.mouse_scroll(self, direction, x, y))then + local data = self.get("data") + local height = self.get("height") + local visibleRows = height - 2 + local maxScroll = math.max(0, #data - visibleRows + 1) + local newOffset = math.min(maxScroll, math.max(0, self.get("scrollOffset") + direction)) - self.set("scrollOffset", newOffset) - return true + self.set("scrollOffset", newOffset) + return true + end + return false end --- @shortDescription Renders the table with headers, data and scrollbar --- @protected function Table:render() VisualElement.render(self) - local columns = self.get("columns") local data = self.get("data") local selected = self.get("selectedRow") local sortCol = self.get("sortColumn") local scrollOffset = self.get("scrollOffset") local height = self.get("height") + local width = self.get("width") local currentX = 1 for i, col in ipairs(columns) do @@ -159,11 +180,11 @@ function Table:render() local bg = (rowIndex + 1) == selected and self.get("selectedColor") or self.get("background") for i, col in ipairs(columns) do - local cellText = rowData[i] or "" + local cellText = tostring(rowData[i] or "") local paddedText = cellText .. string.rep(" ", col.width - #cellText) - self:blit(currentX, y, paddedText, - string.rep(tHex[self.get("foreground")], col.width), - string.rep(tHex[bg], col.width)) + self:blit(currentX, y, string.sub(paddedText, 1, width-currentX+1), + string.sub(string.rep(tHex[self.get("foreground")], col.width), 1, width-currentX+1), + string.sub(string.rep(tHex[bg], col.width), 1, width-currentX+1)) currentX = currentX + col.width end else