Finished Graph Elements
- Added Graph - Added BarChart - Added LineChart
This commit is contained in:
@@ -1,62 +1,188 @@
|
||||
local elementManager = require("elementManager")
|
||||
local VisualElement = elementManager.getElement("elements/VisualElement")
|
||||
---@configDescription
|
||||
local VisualElement = elementManager.getElement("VisualElement")
|
||||
local tHex = require("libraries/colorHex")
|
||||
---@configDescription A point based graph element
|
||||
---@configDefault false
|
||||
|
||||
---@class Graph : VisualElement
|
||||
--- This is the base class for all graph elements. It is a point based graph.
|
||||
--- @class Graph : VisualElement
|
||||
local Graph = setmetatable({}, VisualElement)
|
||||
Graph.__index = Graph
|
||||
|
||||
Graph.defineProperty(Graph, "data", {default = {}, type = "table", canTriggerRender = true})
|
||||
---@property minValue number 0 The minimum value of the graph
|
||||
Graph.defineProperty(Graph, "minValue", {default = 0, type = "number", canTriggerRender = true})
|
||||
---@property maxValue number 100 The maximum value of the graph
|
||||
Graph.defineProperty(Graph, "maxValue", {default = 100, type = "number", canTriggerRender = true})
|
||||
Graph.defineProperty(Graph, "graphColor", {default = colors.yellow, type = "color", canTriggerRender = true})
|
||||
Graph.defineProperty(Graph, "graphSymbol", {default = "\127", type = "string", canTriggerRender = true}) -- Default: "|"
|
||||
---@property series table {} The series of the graph
|
||||
Graph.defineProperty(Graph, "series", {default = {}, type = "table", canTriggerRender = true})
|
||||
|
||||
--- Creates a new Graph instance
|
||||
--- @shortDescription Creates a new Graph instance
|
||||
--- @return Graph self The newly created Graph instance
|
||||
--- @private
|
||||
function Graph.new()
|
||||
local self = setmetatable({}, Graph):__init()
|
||||
return self
|
||||
end
|
||||
|
||||
--- @shortDescription Initializes the Graph instance
|
||||
--- @param props table The properties to initialize the element with
|
||||
--- @param basalt table The basalt instance
|
||||
--- @return Graph self The initialized instance
|
||||
--- @protected
|
||||
function Graph:init(props, basalt)
|
||||
VisualElement.init(self, props, basalt)
|
||||
self.set("type", "Graph")
|
||||
self.set("width", 20)
|
||||
self.set("height", 10)
|
||||
return self
|
||||
end
|
||||
|
||||
function Graph:setPoint(index, value)
|
||||
local data = self.get("data")
|
||||
data[index] = value
|
||||
--- @shortDescription Adds a series to the graph
|
||||
--- @param name string The name of the series
|
||||
--- @param symbol string The symbol of the series
|
||||
--- @param bgCol number The background color of the series
|
||||
--- @param fgCol number The foreground color of the series
|
||||
--- @param pointCount number The number of points in the series
|
||||
function Graph:addSeries(name, symbol, bgCol, fgCol, pointCount)
|
||||
local series = self.get("series")
|
||||
table.insert(series, {
|
||||
name = name,
|
||||
symbol = symbol or " ",
|
||||
bgColor = bgCol or colors.white,
|
||||
fgColor = fgCol or colors.black,
|
||||
pointCount = pointCount or self.get("width"),
|
||||
data = {},
|
||||
visible = true
|
||||
})
|
||||
self:updateRender()
|
||||
return self
|
||||
end
|
||||
|
||||
function Graph:addPoint(value)
|
||||
local data = self.get("data")
|
||||
table.insert(data, value)
|
||||
while #data > self.get("width") do
|
||||
table.remove(data, 1)
|
||||
--- @shortDescription Removes a series from the graph
|
||||
--- @param name string The name of the series
|
||||
--- @return Graph self The graph instance
|
||||
function Graph:removeSeries(name)
|
||||
local series = self.get("series")
|
||||
for i, s in ipairs(series) do
|
||||
if s.name == name then
|
||||
table.remove(series, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
self:updateRender()
|
||||
return self
|
||||
end
|
||||
|
||||
--- @shortDescription Gets a series from the graph
|
||||
--- @param name string The name of the series
|
||||
--- @return table? series The series
|
||||
function Graph:getSeries(name)
|
||||
local series = self.get("series")
|
||||
for _, s in ipairs(series) do
|
||||
if s.name == name then
|
||||
return s
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- @shortDescription Changes the visibility of a series
|
||||
--- @param name string The name of the series
|
||||
--- @param visible boolean Whether the series should be visible
|
||||
--- @return Graph self The graph instance
|
||||
function Graph:changeSeriesVisibility(name, visible)
|
||||
local series = self.get("series")
|
||||
for _, s in ipairs(series) do
|
||||
if s.name == name then
|
||||
s.visible = visible
|
||||
break
|
||||
end
|
||||
end
|
||||
self:updateRender()
|
||||
return self
|
||||
end
|
||||
|
||||
--- @shortDescription Adds a point to a series
|
||||
--- @param name string The name of the series
|
||||
--- @param value number The value of the point
|
||||
--- @return Graph self The graph instance
|
||||
function Graph:addPoint(name, value)
|
||||
local series = self.get("series")
|
||||
|
||||
for _, s in ipairs(series) do
|
||||
if s.name == name then
|
||||
table.insert(s.data, value)
|
||||
while #s.data > s.pointCount do
|
||||
table.remove(s.data, 1)
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
self:updateRender()
|
||||
return self
|
||||
end
|
||||
|
||||
--- @shortDescription Focuses a series
|
||||
--- @param name string The name of the series
|
||||
--- @return Graph self The graph instance
|
||||
function Graph:focusSeries(name)
|
||||
local series = self.get("series")
|
||||
for index, s in ipairs(series) do
|
||||
if s.name == name then
|
||||
table.remove(series, index)
|
||||
table.insert(series, s)
|
||||
break
|
||||
end
|
||||
end
|
||||
self:updateRender()
|
||||
return self
|
||||
end
|
||||
|
||||
--- @shortDescription Sets the point count of a series
|
||||
--- @param name string The name of the series
|
||||
--- @param count number The number of points in the series
|
||||
--- @return Graph self The graph instance
|
||||
function Graph:setSeriesPointCount(name, count)
|
||||
local series = self.get("series")
|
||||
for _, s in ipairs(series) do
|
||||
if s.name == name then
|
||||
s.pointCount = count
|
||||
while #s.data > count do
|
||||
table.remove(s.data, 1)
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
self:updateRender()
|
||||
return self
|
||||
end
|
||||
|
||||
--- @shortDescription Renders the graph
|
||||
--- @protected
|
||||
function Graph:render()
|
||||
VisualElement.render(self)
|
||||
|
||||
local data = self.get("data")
|
||||
|
||||
local width = self.get("width")
|
||||
local height = self.get("height")
|
||||
local minVal = self.get("minValue")
|
||||
local maxVal = self.get("maxValue")
|
||||
local symbol = self.get("graphSymbol")
|
||||
local graphColor = self.get("graphColor")
|
||||
local series = self.get("series")
|
||||
|
||||
for x = 1, width do
|
||||
if data[x] then
|
||||
local normalizedValue = (data[x] - minVal) / (maxVal - minVal)
|
||||
local y = math.floor(height - (normalizedValue * (height-1)))
|
||||
y = math.max(1, math.min(y, height))
|
||||
for _, s in pairs(series) do
|
||||
if(s.visible)then
|
||||
local dataCount = #s.data
|
||||
local spacing = (width - 1) / math.max((dataCount - 1), 1)
|
||||
|
||||
self:textFg(x, y, symbol, graphColor)
|
||||
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))
|
||||
|
||||
self:blit(x, y, s.symbol, tHex[s.bgColor], tHex[s.fgColor])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user