local DF = _G["DetailsFramework"] if (not DF or not DetailsFrameworkCanLoad) then return end local _ local ChartFrameMixin = { ChartFrameConstructor = function(self) self.nextLine = 1 self.minValue = 0 self.maxValue = 1 self.lineThickness = 1 self.data = {} self.lines = {} --OnSizeChanged self:SetScript("OnSizeChanged", self.OnSizeChanged) end, --internally handle next line GetLine = function(self) local line = self.lines[self.nextLine] if (not line) then line = self:CreateLine(nil, "overlay") self.lines[self.nextLine] = line end self.nextLine = self.nextLine + 1 line:Show() return line end, GetLines = function(self) return self.lines end, GetAmountLines = function(self) return self.nextLine - 1 end, HideLines = function(self) local allLines = self:GetLines() for i = 1, #allLines do local line = allLines[i] line:Hide() end end, Reset = function(self) self:HideLines() self.nextLine = 1 end, SetLineThickness = function(self, value) assert(type(value) == "number", "number expected on :SetLineThickness(number)") self.lineThickness = value end, --calculate the width of each drawn line GetLineWidth = function(self) --self:SetLineWidth(nil) to erase the fixed value if (self.fixedLineWidth) then return self.fixedLineWidth else local amountData = self:GetDataSize() local frameWidth = self:GetWidth() return frameWidth / amountData end end, SetLineWidth = function(self, width) assert(type(width) == "number", "number expected on :SetLineWidth(number)") self.fixedLineWidth = width end, CalcYAxisPointForValue = function(self, value) return value / self.maxValue * self.height end, UpdateFrameSizeCache = function(self) self.width = self:GetWidth() self.height = self:GetHeight() end, OnSizeChanged = function(self) self:UpdateFrameSizeCache() end, Plot = function(self) --debug --self:SetData({38, 26, 12, 63, 100, 96, 42, 94, 25, 75, 61, 54, 71, 40, 34, 100, 66, 90, 39, 13, 99, 18, 72, 18, 83, 45, 56, 24, 33, 85, 95, 71, 15, 66, 19, 58, 52, 9, 83, 99, 100, 4, 3, 56, 6, 80, 94, 7, 40, 55, 98, 92, 20, 9, 35, 89, 72, 7, 13, 81, 29, 78, 55, 70, 12, 33, 39, 3, 84, 31, 10, 53, 51, 69, 66, 58, 71, 60, 31, 71, 27, 76, 21, 75, 15, 89, 2, 81, 72, 78, 74, 80, 97, 10, 59, 0, 31, 5, 1, 82, 71, 89, 78, 94, 74, 20, 65, 72, 56, 40, 92, 91, 40, 79, 4, 56, 18, 88, 88, 20, 20, 10, 47, 26, 80, 26, 75, 21, 57, 10, 67, 66, 84, 83, 14, 47, 83, 9, 7, 73, 63, 32, 64, 20, 40, 3, 46, 54, 17, 37, 82, 66, 65, 22, 12, 1, 100, 41, 1, 72, 38, 41, 71, 69, 88, 34, 10, 50, 9, 25, 19, 27, 3, 13, 40, 75, 3, 11, 93, 58, 81, 80, 93, 25, 74, 68, 91, 87, 79, 48, 66, 53, 64, 18, 51, 19, 32, 4, 21, 43}) local currentXPoint = 0 local currentYPoint = 0 self:UpdateFrameSizeCache() --max amount of data is the max amount of point the chart will have local maxLines = self:GetDataSize() --calculate where the first point height will be local firstValue = self:GetDataFirstValue() assert(firstValue, "Can't Plot(), chart has no data, use Chart:SetData(table)") currentYPoint = self:CalcYAxisPointForValue(firstValue) --calculate the width space which line should have local eachLineWidth = self:GetLineWidth() self:ResetDataIndex() for i = 1, maxLines do local line = self:GetLine() line:SetColorTexture(1, 1, 1, 1) line:SetThickness(1) --the start point starts where the latest point finished line:SetStartPoint("bottomleft", currentXPoint, currentYPoint) --move x currentXPoint = currentXPoint + eachLineWidth --end point local value = self:GetDataNextValue() currentYPoint = self:CalcYAxisPointForValue(value) line:SetEndPoint("bottomleft", currentXPoint, currentYPoint) end end, } local createChartFrame = function(parent, name) local f = CreateFrame("frame", name, parent, "BackdropTemplate") DF:Mixin(f, DF.DataMixin) DF:Mixin(f, DF.ValueMixin) DF:Mixin(f, ChartFrameMixin) f:DataConstructor() f:ValueConstructor() f:ChartFrameConstructor() --when a new data is set, update the min and max values local onSetDataCallback = function() local minValue, maxValue = f:GetDataMinMaxValues() f:SetMinMaxValues(minValue, maxValue) --clear the lines f:HideLines() end f:AddDataChangeCallback(onSetDataCallback) return f end function DF:CreateGraphicLineFrame(parent, name) local newGraphicFrame = createChartFrame(parent, name) return newGraphicFrame end local MultiChartFrameMixin = { MultiChartFrameConstructor = function(self) self.nextChartselframe = 1 self.biggestDataValue = 0 self.chartFrames = {} end, AddData = function(self, data) assert(type(data) == "table", "MultiChartFrame:AddData() usage: AddData(table)") local chartFrame = self:GetChart() chartFrame:SetData(data) self:SetMaxValueIfBigger(chartFrame:GetMaxValue()) self:SetMinValueIfLower(chartFrame:GetMinValue()) local dataAmount = chartFrame:GetDataSize() self:SetMaxDataSize(dataAmount) end, --internally handle next line GetChart = function(self) local chartFrame = self.chartFrames[self.nextChartFrame] if (not chartFrame) then chartFrame = createChartFrame(self, "$parentChartFrame" .. self.nextChartFrame) chartFrame:SetAllPoints() chartFrame:UpdateFrameSizeCache() self.chartFrames[self.nextChartFrame] = chartFrame end self.nextChartFrame = self.nextChartFrame + 1 chartFrame:Show() return chartFrame end, GetCharts = function(self) return self.chartFrames end, GetAmountCharts = function(self) return self.nextChartFrame - 1 end, HideCharts = function(self) local charts = self:GetCharts() for i = 1, #charts do local chartFrame = charts[i] chartFrame:Hide() end end, Reset = function(self) self:HideCharts() self.nextChartFrame = 1 end, SetChartsMinMaxValues = function(self, minValue, maxValue) local allCharts = self:GetCharts() for i = 1, self:GetAmountCharts() do local chartFrame = allCharts[i] chartFrame:SetMinMaxValues(minValue, maxValue) end end, SetMaxDataSize = function(self, dataSize) self.biggestDataValue = max(self.biggestDataValue, dataSize) end, GetMaxDataSize = function(self) return self.biggestDataValue end, Plot = function(self) local minValue, maxValue = self:GetMinMaxValues() self:SetChartsMinMaxValues(minValue, maxValue) local plotAreaWidth = self:GetWidth() local maxDataSize = self:GetMaxDataSize() local eachLineWidth = plotAreaWidth / maxDataSize local allCharts = self:GetCharts() for i = 1, self:GetAmountCharts() do local chartFrame = allCharts[i] chartFrame:SetLineWidth(eachLineWidth) chartFrame:Plot() end end, } function DF:CreateGraphicMultiLineFrame(parent, name) name = name or ("DetailsMultiChartFrameID" .. math.random(1, 10000000)) local f = CreateFrame("frame", name, parent, "BackdropTemplate") DF:Mixin(f, DF.ValueMixin) DF:Mixin(f, MultiChartFrameMixin) f:ValueConstructor() f:MultiChartFrameConstructor() return f end