Files
Basalt2/src/elements/LineChart.lua
Robert Jelic b91031afbc Fixed animation
Fixed eventsystem not registering its parent events
2025-04-14 02:39:54 +02:00

93 lines
3.2 KiB
Lua

local elementManager = require("elementManager")
local VisualElement = elementManager.getElement("VisualElement")
local Graph = elementManager.getElement("Graph")
local tHex = require("libraries/colorHex")
--- @configDescription A line chart element based on the graph element
---@configDefault false
--- 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
--- Creates a new LineChart instance
--- @shortDescription Creates a new LineChart instance
--- @return LineChart self The newly created LineChart instance
--- @private
function LineChart.new()
local self = setmetatable({}, LineChart):__init()
self.class = LineChart
return self
end
--- @shortDescription Initializes the LineChart instance
--- @param props table The properties to initialize the element with
--- @param basalt table The basalt instance
--- @return LineChart self The initialized instance
--- @protected
function LineChart:init(props, basalt)
Graph.init(self, props, basalt)
self.set("type", "LineChart")
return self
end
local function drawLine(self, x1, y1, x2, y2, symbol, bgColor, fgColor)
local dx = x2 - x1
local dy = y2 - y1
local steps = math.max(math.abs(dx), math.abs(dy))
for i = 0, steps do
local t = steps == 0 and 0 or i / steps
local x = math.floor(x1 + dx * t)
local y = math.floor(y1 + dy * t)
if x >= 1 and x <= self.get("width") and y >= 1 and y <= self.get("height") then
self:blit(x, y, symbol, tHex[bgColor], tHex[fgColor])
end
end
end
--- @shortDescription Renders the LineChart
--- @protected
function LineChart:render()
VisualElement.render(self)
local width = self.get("width")
local height = self.get("height")
local minVal = self.get("minValue")
local maxVal = self.get("maxValue")
local series = self.get("series")
for _, s in pairs(series) do
if(s.visible)then
local lastX, lastY
local dataCount = #s.data
local spacing = (width - 1) / math.max((dataCount - 1), 1)
for i, value in ipairs(s.data) do
local x = math.floor(((i-1) * spacing) + 1)
local normalizedValue = (value - minVal) / (maxVal - minVal)
local y = math.floor(height - (normalizedValue * (height-1)))
y = math.max(1, math.min(y, height))
if lastX then
drawLine(self, lastX, lastY, x, y, s.symbol, s.bgColor, s.fgColor)
end
lastX, lastY = x, y
end
end
end
end
return LineChart