diff --git a/Libs/DF/containers.lua b/Libs/DF/containers.lua
index 3864d216..336e0b88 100644
--- a/Libs/DF/containers.lua
+++ b/Libs/DF/containers.lua
@@ -11,7 +11,7 @@ local CreateFrame = CreateFrame
local wipe = wipe
local unpack = unpack
----@class dfframecontainer : frame, dfframecontainermixin, dfoptionsmixin
+---@class dfframecontainer : frame, dfframecontainermixin, df_optionsmixin
---@field bIsSizing boolean
---@field options table
---@field currentWidth number
diff --git a/Libs/DF/fw.lua b/Libs/DF/fw.lua
index 4adfe77a..09da295f 100644
--- a/Libs/DF/fw.lua
+++ b/Libs/DF/fw.lua
@@ -827,35 +827,34 @@ end
---@param value number
---@return string
function DF:IntegerToTimer(value) --~formattime
- return "" .. floor(value/60) .. ":" .. format("%02.f", value%60)
+ return "" .. math.floor(value/60) .. ":" .. string.format("%02.f", value%60)
end
---remove the realm name from a name
---@param name string
----@return string
+---@return string, number
function DF:RemoveRealmName(name)
return name:gsub(("%-.*"), "")
end
---remove the realm name from a name
---@param name string
----@return string
+---@return string, number
function DF:RemoveRealName(name)
return name:gsub(("%-.*"), "")
end
---get the UIObject of type 'FontString' named fontString and set the font size to the maximum value of the arguments
----@param fontString FontString
+---@param fontString fontstring
---@vararg number
function DF:SetFontSize(fontString, ...)
local font, _, flags = fontString:GetFont()
- fontString:SetFont(font, max(...), flags)
+ fontString:SetFont(font, math.max(...), flags)
end
---get the UIObject of type 'FontString' named fontString and set the font to the argument fontface
----@param fontString FontString
+---@param fontString fontstring
---@param fontface string
----@return nil
function DF:SetFontFace(fontString, fontface)
local font = SharedMedia:Fetch("font", fontface, true)
if (font) then
@@ -867,26 +866,24 @@ function DF:SetFontFace(fontString, fontface)
end
---get the FontString passed and set the font color
----@param fontString FontString
+---@param fontString fontstring
---@param r any
---@param g number|nil
---@param b number|nil
---@param a number|nil
----@return nil
function DF:SetFontColor(fontString, r, g, b, a)
r, g, b, a = DF:ParseColors(r, g, b, a)
fontString:SetTextColor(r, g, b, a)
end
---get the FontString passed and set the font shadow color and offset
----@param fontString FontString
+---@param fontString fontstring
---@param r number
---@param g number
---@param b number
---@param a number
---@param x number
---@param y number
----@return nil
function DF:SetFontShadow(fontString, r, g, b, a, x, y)
r, g, b, a = DF:ParseColors(r, g, b, a)
fontString:SetShadowColor(r, g, b, a)
@@ -899,9 +896,8 @@ function DF:SetFontShadow(fontString, r, g, b, a, x, y)
end
---get the FontString object passed and set the rotation of the text shown
----@param fontString FontString
+---@param fontString fontstring
---@param degrees number
----@return nil
function DF:SetFontRotation(fontString, degrees)
if (type(degrees) == "number") then
if (not fontString.__rotationAnimation) then
diff --git a/Libs/DF/header.lua b/Libs/DF/header.lua
new file mode 100644
index 00000000..6e8e41ef
--- /dev/null
+++ b/Libs/DF/header.lua
@@ -0,0 +1,631 @@
+
+local detailsFramework = DetailsFramework
+
+if (not detailsFramework or not DetailsFrameworkCanLoad) then
+ return
+end
+
+local unpack = unpack
+local CreateFrame = CreateFrame
+local geterrorhandler = geterrorhandler
+
+--definitions
+---@class df_headerchild : uiobject
+---@field FramesToAlign table
+
+---@class df_headerframe : frame, df_headermixin, df_optionsmixin
+---@field columnHeadersCreated df_headercolumnframe[]
+---@field options table
+---@field HeaderTable table
+---@field columnSelected number
+
+---@class df_headermixin : table
+---@field NextHeader number
+---@field HeaderWidth number
+---@field HeaderHeight number
+---@field OnColumnSettingChangeCallback function
+---@field GetColumnWidth fun(self: df_headerframe, columnId: number)
+---@field SetHeaderTable fun(self: df_headerframe, newTable)
+---@field GetSelectedColumn fun(self: df_headerframe) : number, string, string
+---@field Refresh fun(self: df_headerframe)
+---@field UpdateSortArrow fun(self: df_headerframe, columnHeader: df_headercolumnframe, defaultShown: boolean|nil, defaultOrder: string|nil)
+---@field UpdateColumnHeader fun(self: df_headerframe, columnHeader: df_headercolumnframe, headerIndex)
+---@field ResetColumnHeaderBackdrop fun(self: df_headerframe, columnHeader: df_headercolumnframe)
+---@field SetBackdropColorForSelectedColumnHeader fun(self: df_headerframe, columnHeader: df_headercolumnframe)
+---@field ClearColumnHeader fun(self: df_headerframe, columnHeader: df_headercolumnframe)
+---@field GetNextHeader fun(self: df_headerframe) : df_headercolumnframe
+---@field SetColumnSettingChangedCallback fun(self: df_headerframe, func: function) : boolean
+
+---@class df_headercolumnframe : frame
+---@field Icon texture
+---@field Text fontstring
+---@field Arrow texture
+---@field Separator texture
+---@field resizerButton df_headerresizer
+---@field bIsRezising boolean
+---@field bInUse boolean
+---@field columnData table
+---@field order string
+---@field columnIndex number
+---@field columnAlign string
+---@field XPosition number
+---@field columnOffset number
+---@field key string used to sort the values
+
+---@class df_headerresizer : button
+---@field texture texture
+
+--mixed functions
+detailsFramework.HeaderFunctions = {
+ ---comment
+ ---@param self df_headerchild
+ ---@param frame uiobject
+ AddFrameToHeaderAlignment = function(self, frame)
+ self.FramesToAlign = self.FramesToAlign or {}
+ table.insert(self.FramesToAlign, frame)
+ end,
+
+ ---comment
+ ---@param self df_headerchild
+ ResetFramesToHeaderAlignment = function(self)
+ table.wipe(self.FramesToAlign)
+ end,
+
+ SetFramesToHeaderAlignment = function(self, ...)
+ ---@cast self df_headerchild
+ table.wipe(self.FramesToAlign)
+ self.FramesToAlign = {...}
+ end,
+
+ GetFramesFromHeaderAlignment = function(self, frame)
+ return self.FramesToAlign or {}
+ end,
+
+ ---@param self uiobject
+ ---@param headerFrame df_headerframe
+ ---@param anchor string
+ AlignWithHeader = function(self, headerFrame, anchor)
+ local columnHeaderFrames = headerFrame.columnHeadersCreated
+ anchor = anchor or "topleft"
+
+ ---@cast self df_headerchild
+
+ for i = 1, #self.FramesToAlign do
+ local frame = self.FramesToAlign[i]
+ frame:ClearAllPoints()
+
+ ---@type df_headercolumnframe
+ local columnHeader = columnHeaderFrames[i]
+ if (columnHeader) then
+ local offset = 0
+
+ if (columnHeader.columnAlign == "right") then
+ offset = columnHeader:GetWidth()
+ if (frame:GetObjectType() == "FontString") then
+ frame:SetJustifyH("right")
+ end
+ end
+
+ frame:SetPoint(columnHeader.columnAlign, self, anchor, columnHeader.XPosition + columnHeader.columnOffset + offset, 0)
+ end
+ end
+ end,
+
+ ---comment
+ ---@param columnHeader df_headercolumnframe
+ ---@param buttonClicked string
+ OnClick = function(columnHeader, buttonClicked)
+ --get the header main frame
+ ---@type df_headerframe
+ local headerFrame = columnHeader:GetParent()
+
+ --if this header does not have a clickable header, just ignore
+ if (not headerFrame.columnSelected) then
+ return
+ end
+
+ --check if this column has 'canSort' key, otherwise ignore the click
+ if (not columnHeader.columnData.canSort) then
+ return
+ end
+
+ --get the latest column header selected
+ ---@type df_headercolumnframe
+ local previousColumnHeader = headerFrame.columnHeadersCreated[headerFrame.columnSelected]
+ previousColumnHeader.Arrow:Hide()
+ headerFrame:ResetColumnHeaderBackdrop(previousColumnHeader)
+ headerFrame:SetBackdropColorForSelectedColumnHeader(columnHeader)
+
+ if (headerFrame.columnSelected == columnHeader.columnIndex) then
+ columnHeader.order = columnHeader.order ~= "ASC" and "ASC" or "DESC"
+ end
+ headerFrame.columnOrder = columnHeader.order
+
+ --set the new column header selected
+ headerFrame.columnSelected = columnHeader.columnIndex
+
+ headerFrame:UpdateSortArrow(columnHeader)
+
+ if (headerFrame.options.header_click_callback) then
+ --callback with the main header frame, column header, column index and column order as payload
+ local okay, errortext = pcall(headerFrame.options.header_click_callback, headerFrame, columnHeader, columnHeader.columnIndex, columnHeader.order)
+ if (not okay) then
+ print("DF: Header onClick callback error:", errortext)
+ end
+ end
+ end,
+
+ ---comment
+ ---@param self button
+ ---@param buttonClicked string
+ OnMouseDown = function(self, buttonClicked)
+ if (buttonClicked == "LeftButton") then
+
+ end
+ end,
+
+ ---comment
+ ---@param self button
+ ---@param buttonClicked string
+ OnMouseUp = function(self, buttonClicked)
+ if (buttonClicked == "LeftButton") then
+
+ end
+ end,
+}
+
+---@class df_headermixin : table
+detailsFramework.HeaderMixin = {
+ ---@param self df_headerframe
+ ---@param columnId number
+ ---@return number
+ GetColumnWidth = function(self, columnId)
+ return self.HeaderTable[columnId].width
+ end,
+
+ ---@param self df_headerframe
+ ---@param newTable table
+ SetHeaderTable = function(self, newTable)
+ self.columnHeadersCreated = self.columnHeadersCreated or {}
+ self.HeaderTable = newTable
+ self.NextHeader = 1
+ self.HeaderWidth = 0
+ self.HeaderHeight = 0
+ self:Refresh()
+ end,
+
+ ---@param self df_headerframe
+ ---@param func function
+ ---@return boolean
+ SetColumnSettingChangedCallback = function(self, func)
+ if (type(func) ~= "function") then
+ self.OnColumnSettingChangeCallback = nil
+ return false
+ end
+ self.OnColumnSettingChangeCallback = func
+ return true
+ end,
+
+ --return which header is current selected and the the order ASC DESC
+ ---@param self df_headerframe
+ ---@return number, string
+ GetSelectedColumn = function(self)
+ ---@type number
+ local columnSelected = self.columnSelected
+ ---@type df_headercolumnframe
+ local columnHeader = self.columnHeadersCreated[columnSelected or 1]
+
+ return columnSelected, columnHeader.order, columnHeader.key
+ end,
+
+ --clean up and rebuild the header following the header options
+ --@self: main header frame
+ ---@param self df_headerframe
+ Refresh = function(self)
+ --refresh background frame
+ self:SetBackdrop(self.options.backdrop)
+ self:SetBackdropColor(unpack(self.options.backdrop_color))
+ self:SetBackdropBorderColor(unpack(self.options.backdrop_border_color))
+
+ --reset all header frames
+ for i = 1, #self.columnHeadersCreated do
+ local columnHeader = self.columnHeadersCreated[i]
+ columnHeader.bInUse = false
+ columnHeader:Hide()
+ end
+
+ local previousColumnHeader
+ local growDirection = string.lower(self.options.grow_direction)
+
+ --amount of headers to be updated
+ local headerSize = #self.HeaderTable
+
+ --update header frames
+ for i = 1, headerSize do
+ --get the header button, a new one is created if it doesn't exists yet
+ local columnHeader = self:GetNextHeader()
+ self:UpdateColumnHeader(columnHeader, i)
+
+ --grow direction
+ if (not previousColumnHeader) then
+ columnHeader:SetPoint("topleft", self, "topleft", 0, 0)
+
+ if (growDirection == "right") then
+ if (self.options.use_line_separators) then
+ columnHeader.Separator:Show()
+ columnHeader.Separator:SetWidth(self.options.line_separator_width)
+ columnHeader.Separator:SetColorTexture(unpack(self.options.line_separator_color))
+
+ columnHeader.Separator:ClearAllPoints()
+ if (self.options.line_separator_gap_align) then
+ columnHeader.Separator:SetPoint("topleft", columnHeader, "topright", 0, 0)
+ else
+ columnHeader.Separator:SetPoint("topright", columnHeader, "topright", 0, 0)
+ end
+ columnHeader.Separator:SetHeight(self.options.line_separator_height)
+ end
+ end
+ else
+ if (growDirection == "right") then
+ columnHeader:SetPoint("topleft", previousColumnHeader, "topright", self.options.padding, 0)
+
+ if (self.options.use_line_separators) then
+ columnHeader.Separator:Show()
+ columnHeader.Separator:SetWidth(self.options.line_separator_width)
+ columnHeader.Separator:SetColorTexture(unpack(self.options.line_separator_color))
+
+ columnHeader.Separator:ClearAllPoints()
+ if (self.options.line_separator_gap_align) then
+ columnHeader.Separator:SetPoint("topleft", columnHeader, "topright", 0, 0)
+ else
+ columnHeader.Separator:SetPoint("topleft", columnHeader, "topright", 0, 0)
+ end
+ columnHeader.Separator:SetHeight(self.options.line_separator_height)
+
+ if (headerSize == i) then
+ columnHeader.Separator:Hide()
+ end
+ end
+
+ elseif (growDirection == "left") then
+ columnHeader:SetPoint("topright", previousColumnHeader, "topleft", -self.options.padding, 0)
+
+ elseif (growDirection == "bottom") then
+ columnHeader:SetPoint("topleft", previousColumnHeader, "bottomleft", 0, -self.options.padding)
+
+ elseif (growDirection == "top") then
+ columnHeader:SetPoint("bottomleft", previousColumnHeader, "topleft", 0, self.options.padding)
+ end
+ end
+
+ previousColumnHeader = columnHeader
+ end
+
+ self:SetSize(self.HeaderWidth, self.HeaderHeight)
+ end,
+
+ ---@param self df_headerframe
+ ---@param columnHeader df_headercolumnframe
+ ---@param defaultShown boolean
+ ---@param defaultOrder string
+ UpdateSortArrow = function(self, columnHeader, defaultShown, defaultOrder)
+ local options = self.options
+ local order = defaultOrder or columnHeader.order
+ local arrowIcon = columnHeader.Arrow
+
+ if (type(defaultShown) ~= "boolean") then
+ arrowIcon:Show()
+ else
+ arrowIcon:SetShown(defaultShown)
+ if (defaultShown) then
+ self:SetBackdropColorForSelectedColumnHeader(columnHeader)
+ end
+ end
+
+ arrowIcon:SetAlpha(options.arrow_alpha)
+
+ if (order == "ASC") then
+ arrowIcon:SetTexture(options.arrow_up_texture)
+ arrowIcon:SetTexCoord(unpack(options.arrow_up_texture_coords))
+ arrowIcon:SetSize(unpack(options.arrow_up_size))
+
+ elseif (order == "DESC") then
+ arrowIcon:SetTexture(options.arrow_down_texture)
+ arrowIcon:SetTexCoord(unpack(options.arrow_down_texture_coords))
+ arrowIcon:SetSize(unpack(options.arrow_down_size))
+ end
+ end,
+
+ ---@param self df_headerframe
+ ---@param columnHeader df_headercolumnframe
+ ---@param headerIndex number
+ UpdateColumnHeader = function(self, columnHeader, headerIndex)
+ --this is the data to update the columnHeader
+ local columnData = self.HeaderTable[headerIndex]
+
+ columnHeader.key = columnData.key or "total"
+
+ if (columnData.icon) then
+ columnHeader.Icon:SetTexture(columnData.icon)
+
+ if (columnData.texcoord) then
+ columnHeader.Icon:SetTexCoord(unpack(columnData.texcoord))
+ else
+ columnHeader.Icon:SetTexCoord(0, 1, 0, 1)
+ end
+
+ columnHeader.Icon:SetPoint("left", columnHeader, "left", self.options.padding, 0)
+ columnHeader.Icon:Show()
+ end
+
+ if (columnData.text) then
+ columnHeader.Text:SetText(columnData.text)
+
+ --text options
+ detailsFramework:SetFontColor(columnHeader.Text, self.options.text_color)
+ detailsFramework:SetFontSize(columnHeader.Text, self.options.text_size)
+ detailsFramework:SetFontOutline(columnHeader.Text, self.options.text_shadow)
+
+ --point
+ if (not columnData.icon) then
+ columnHeader.Text:SetPoint("left", columnHeader, "left", self.options.padding, 0)
+ else
+ columnHeader.Text:SetPoint("left", columnHeader.Icon, "right", self.options.padding, 0)
+ end
+
+ columnHeader.Text:Show()
+ end
+
+ --column header index
+ columnHeader.columnIndex = headerIndex
+
+ if (columnData.canSort) then
+ columnHeader.order = "DESC"
+ columnHeader.Arrow:SetTexture(self.options.arrow_up_texture)
+ else
+ columnHeader.Arrow:Hide()
+ end
+
+ if (columnData.selected) then
+ columnHeader.Arrow:Show()
+ columnHeader.Arrow:SetAlpha(.843)
+ self:UpdateSortArrow(columnHeader, true, columnHeader.order)
+ self.columnSelected = headerIndex
+ else
+ if (columnData.canSort) then
+ self:UpdateSortArrow(columnHeader, false, columnHeader.order)
+ end
+ end
+
+ --size
+ if (columnData.width) then
+ columnHeader:SetWidth(columnData.width)
+ end
+ if (columnData.height) then
+ columnHeader:SetHeight(columnData.height)
+ end
+
+ columnHeader.XPosition = self.HeaderWidth -- + self.options.padding
+ columnHeader.YPosition = self.HeaderHeight -- + self.options.padding
+
+ columnHeader.columnAlign = columnData.align or "left"
+ columnHeader.columnOffset = columnData.offset or 0
+
+ --add the header piece size to the total header size
+ local growDirection = string.lower(self.options.grow_direction)
+
+ if (growDirection == "right" or growDirection == "left") then
+ self.HeaderWidth = self.HeaderWidth + columnHeader:GetWidth() + self.options.padding
+ self.HeaderHeight = math.max(self.HeaderHeight, columnHeader:GetHeight())
+
+ elseif (growDirection == "top" or growDirection == "bottom") then
+ self.HeaderWidth = math.max(self.HeaderWidth, columnHeader:GetWidth())
+ self.HeaderHeight = self.HeaderHeight + columnHeader:GetHeight() + self.options.padding
+ end
+
+ local bShowColumnHeaderReziser = self.options.reziser_shown
+ if (bShowColumnHeaderReziser) then
+ local resizerButton = columnHeader.resizerButton
+ resizerButton:Show()
+ resizerButton.texture:SetVertexColor(unpack(self.options.reziser_color))
+ resizerButton:SetWidth(self.options.reziser_width)
+ resizerButton:SetHeight(columnHeader:GetHeight())
+ else
+ columnHeader.resizerButton:Hide()
+ end
+
+ columnHeader:Show()
+ columnHeader.bInUse = true
+ columnHeader.columnData = columnData
+ end,
+
+ ---reset column header backdrop
+ ---@param self df_headerframe
+ ---@param columnHeader df_headercolumnframe
+ ResetColumnHeaderBackdrop = function(self, columnHeader)
+ columnHeader:SetBackdrop(self.options.header_backdrop)
+ columnHeader:SetBackdropColor(unpack(self.options.header_backdrop_color))
+ columnHeader:SetBackdropBorderColor(unpack(self.options.header_backdrop_border_color))
+ end,
+
+ ---@param self df_headerframe
+ ---@param columnHeader df_headercolumnframe
+ SetBackdropColorForSelectedColumnHeader = function(self, columnHeader)
+ columnHeader:SetBackdropColor(unpack(self.options.header_backdrop_color_selected))
+ end,
+
+ ---clear the column header
+ ---@param self df_headerframe
+ ---@param columnHeader df_headercolumnframe
+ ClearColumnHeader = function(self, columnHeader)
+ columnHeader:SetSize(self.options.header_width, self.options.header_height)
+ self:ResetColumnHeaderBackdrop(columnHeader)
+
+ columnHeader:ClearAllPoints()
+
+ columnHeader.Icon:SetTexture("")
+ columnHeader.Icon:Hide()
+ columnHeader.Text:SetText("")
+ columnHeader.Text:Hide()
+ end,
+
+ ---get the next column header, create one if doesn't exists
+ ---@param self df_headerframe
+ GetNextHeader = function(self)
+ local nextHeader = self.NextHeader
+ local columnHeader = self.columnHeadersCreated[nextHeader]
+
+ if (not columnHeader) then
+ --create a new column header
+ ---@type df_headercolumnframe
+ columnHeader = CreateFrame("button", "$parentHeaderIndex" .. nextHeader, self, "BackdropTemplate")
+ columnHeader:SetScript("OnClick", detailsFramework.HeaderFunctions.OnClick)
+ columnHeader:SetMovable(true)
+ columnHeader:SetResizable(true)
+
+ --header icon
+ detailsFramework:CreateImage(columnHeader, "", self.options.header_height, self.options.header_height, "ARTWORK", nil, "Icon", "$parentIcon")
+ --header separator
+ detailsFramework:CreateImage(columnHeader, "", 1, 1, "ARTWORK", nil, "Separator", "$parentSeparator")
+ --header name text
+ detailsFramework:CreateLabel(columnHeader, "", self.options.text_size, self.options.text_color, "GameFontNormal", "Text", "$parentText", "ARTWORK")
+ --header selected and order icon
+ detailsFramework:CreateImage(columnHeader, self.options.arrow_up_texture, 12, 12, "ARTWORK", nil, "Arrow", "$parentArrow")
+
+ ---rezise button
+ ---@type df_headerresizer
+ local resizerButton = CreateFrame("button", "$parentResizer", columnHeader)
+ resizerButton:SetWidth(4)
+ resizerButton:SetFrameLevel(columnHeader:GetFrameLevel()+2)
+ resizerButton:SetPoint("topright", columnHeader, "topright", -1, -1)
+ resizerButton:SetPoint("bottomright", columnHeader, "bottomright", -1, 1)
+ resizerButton:EnableMouse(true)
+ resizerButton:RegisterForClicks("LeftButtonDown", "LeftButtonUp")
+ columnHeader.resizerButton = resizerButton
+
+ resizerButton:SetScript("OnEnter", function()
+ resizerButton.texture:SetVertexColor(1, 1, 1, 0.9)
+ end)
+
+ resizerButton:SetScript("OnLeave", function()
+ resizerButton.texture:SetVertexColor(unpack(self.options.reziser_color))
+ end)
+
+ resizerButton:SetScript("OnMouseDown", function() --move this to a single function
+ if (not columnHeader.bIsRezising) then
+ --get the string length to know the min size
+ local textLength = columnHeader.Text:GetStringWidth() + 6
+ columnHeader:SetResizeBounds(math.max(textLength, self.options.reziser_min_width), columnHeader:GetHeight(), self.options.reziser_max_width, columnHeader:GetHeight())
+ columnHeader.bIsRezising = true
+ columnHeader:StartSizing("right")
+ end
+ end)
+
+ resizerButton:SetScript("OnMouseUp", function()
+ if (columnHeader.bIsRezising) then
+ columnHeader.bIsRezising = false
+ columnHeader:StopMovingOrSizing()
+
+ --callback or modify into a passed by table?
+ if (self.OnColumnSettingChangeCallback) then --need to get the header name
+ local columnName = columnHeader.columnData.name
+ xpcall(self.OnColumnSettingChangeCallback, geterrorhandler(), self, "width", columnName, columnHeader:GetWidth())
+ end
+ end
+ end)
+
+ resizerButton:SetScript("OnHide", function()
+ if (columnHeader.bIsRezising) then
+ columnHeader:StopMovingOrSizing()
+ columnHeader.bIsRezising = false
+ end
+ end)
+
+ resizerButton.texture = resizerButton:CreateTexture(nil, "overlay")
+ resizerButton.texture:SetAllPoints()
+ resizerButton.texture:SetColorTexture(1, 1, 1, 1)
+
+ columnHeader.Arrow:SetPoint("right", columnHeader, "right", -1, 0)
+
+ columnHeader.Separator:Hide()
+ columnHeader.Arrow:Hide()
+
+ self:UpdateSortArrow(columnHeader, false, "DESC")
+
+ table.insert(self.columnHeadersCreated, columnHeader)
+ columnHeader = columnHeader
+ end
+
+ self:ClearColumnHeader(columnHeader)
+ self.NextHeader = self.NextHeader + 1
+ return columnHeader
+ end,
+
+ NextHeader = 1,
+ HeaderWidth = 0,
+ HeaderHeight = 0,
+}
+
+local default_header_options = {
+ backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
+ backdrop_color = {0, 0, 0, 0.2},
+ backdrop_border_color = {0.1, 0.1, 0.1, .2},
+
+ text_color = {1, 1, 1, 1},
+ text_size = 10,
+ text_shadow = false,
+ grow_direction = "RIGHT",
+ padding = 2,
+
+ reziser_shown = false, --make sure to set the callback function with: header:SetOnColumnResizeScript(callbackFunction)
+ reziser_width = 2,
+ reziser_color = {1, 0.6, 0, 0.6},
+ reziser_min_width = 16,
+ reziser_max_width = 200,
+
+ --each piece of the header
+ header_backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
+ header_backdrop_color = {0, 0, 0, 0.5},
+ header_backdrop_color_selected = {0.3, 0.3, 0.3, 0.5},
+ header_backdrop_border_color = {0, 0, 0, 0},
+ header_width = 120,
+ header_height = 20,
+
+ arrow_up_texture = [[Interface\Buttons\Arrow-Up-Down]],
+ arrow_up_texture_coords = {0, 1, 6/16, 1},
+ arrow_up_size = {12, 11},
+ arrow_down_texture = [[Interface\Buttons\Arrow-Down-Down]],
+ arrow_down_texture_coords = {0, 1, 0, 11/16},
+ arrow_down_size = {12, 11},
+ arrow_alpha = 0.659,
+
+ use_line_separators = false,
+ line_separator_color = {.1, .1, .1, .6},
+ line_separator_width = 1,
+ line_separator_height = 200,
+ line_separator_gap_align = false,
+}
+
+---create a header frame
+---@param parent frame
+---@param headerTable table
+---@param options table|nil
+---@param frameName string|nil
+---@return df_headerframe
+function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
+ ---@type df_headerframe
+ local newHeader = CreateFrame("frame", frameName or "$parentHeaderLine", parent, "BackdropTemplate")
+
+ detailsFramework:Mixin(newHeader, detailsFramework.OptionsFunctions)
+ detailsFramework:Mixin(newHeader, detailsFramework.HeaderMixin)
+
+ newHeader:BuildOptionsTable(default_header_options, options)
+
+ newHeader:SetBackdrop(newHeader.options.backdrop)
+ newHeader:SetBackdropColor(unpack(newHeader.options.backdrop_color))
+ newHeader:SetBackdropBorderColor(unpack(newHeader.options.backdrop_border_color))
+
+ newHeader:SetHeaderTable(headerTable)
+
+ return newHeader
+end
\ No newline at end of file
diff --git a/Libs/DF/load.xml b/Libs/DF/load.xml
index 66e96f2c..fa46ad83 100644
--- a/Libs/DF/load.xml
+++ b/Libs/DF/load.xml
@@ -4,6 +4,7 @@
+
diff --git a/Libs/DF/mixins.lua b/Libs/DF/mixins.lua
index c8389196..d9a840dc 100644
--- a/Libs/DF/mixins.lua
+++ b/Libs/DF/mixins.lua
@@ -268,7 +268,7 @@ detailsFramework.SetPointMixin = {
}
---mixin for options
----@class dfoptionsmixin
+---@class df_optionsmixin
detailsFramework.OptionsFunctions = {
SetOption = function(self, optionName, optionValue)
if (self.options) then
diff --git a/Libs/DF/panel.lua b/Libs/DF/panel.lua
index ce6e3bbe..f518e838 100644
--- a/Libs/DF/panel.lua
+++ b/Libs/DF/panel.lua
@@ -5096,605 +5096,6 @@ function detailsFramework:CreateIconRow (parent, name, options)
return f
end
-
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---~header
-
---definitions
----@class headerframe: frame
----@field GetColumnWidth fun(self: headerframe, columnId: number)
----@field SetHeaderTable fun(self: headerframe, newTable)
----@field GetSelectedColumn fun(self: headerframe)
----@field Refresh fun(self: headerframe)
----@field UpdateSortArrow fun(self: headerframe, columnHeader: headercolumnframe, defaultShown: boolean, defaultOrder: string)
----@field UpdateColumnHeader fun(self: headerframe, columnHeader: headercolumnframe, headerIndex)
----@field ResetColumnHeaderBackdrop fun(self: headerframe, columnHeader: headercolumnframe)
----@field SetBackdropColorForSelectedColumnHeader fun(self: headerframe, columnHeader: headercolumnframe)
----@field ClearColumnHeader fun(self: headerframe, columnHeader: headercolumnframe)
----@field GetNextHeader fun(self: headerframe) : headercolumnframe
----@field SetColumnSettingChangedCallback fun(self: headerframe, func: function) : boolean
----@field columnHeadersCreated headercolumnframe[]
----@field HeaderTable table
----@field NextHeader number
----@field HeaderWidth number
----@field HeaderHeight number
----@field columnSelected number
----@field OnColumnSettingChangeCallback function
-
----@class headercolumnframe: frame
----@field Icon texture
----@field Text fontstring
----@field Arrow texture
----@field Separator texture
----@field resizerButton button
----@field bIsRezising boolean
----@field bInUse boolean
----@field columnData table
----@field order string
----@field key string used to sort the values
-
---mixed functions
-detailsFramework.HeaderFunctions = {
- AddFrameToHeaderAlignment = function(self, frame)
- self.FramesToAlign = self.FramesToAlign or {}
- _G.tinsert(self.FramesToAlign, frame)
- end,
-
- ResetFramesToHeaderAlignment = function(self)
- _G.wipe(self.FramesToAlign)
- end,
-
- SetFramesToHeaderAlignment = function(self, ...)
- _G.wipe(self.FramesToAlign)
- self.FramesToAlign = {...}
- end,
-
- GetFramesFromHeaderAlignment = function(self, frame)
- return self.FramesToAlign or {}
- end,
-
- ---@param self uiobject
- ---@param headerFrame headerframe
- ---@param anchor string
- AlignWithHeader = function(self, headerFrame, anchor)
- local columnHeaderFrames = headerFrame.columnHeadersCreated
- anchor = anchor or "topleft"
-
- for i = 1, #self.FramesToAlign do
- local frame = self.FramesToAlign[i]
- frame:ClearAllPoints()
-
- ---@type headercolumnframe
- local columnHeader = columnHeaderFrames[i]
- if (columnHeader) then
- local offset = 0
-
- if (columnHeader.columnAlign == "right") then
- offset = columnHeader:GetWidth()
- if (frame:GetObjectType() == "FontString") then
- frame:SetJustifyH("right")
- end
- end
-
- frame:SetPoint(columnHeader.columnAlign, self, anchor, columnHeader.XPosition + columnHeader.columnOffset + offset, 0)
- end
- end
- end,
-
- ---comment
- ---@param columnHeader headercolumnframe
- ---@param buttonClicked string
- OnClick = function(columnHeader, buttonClicked)
- --get the header main frame
- ---@type headerframe
- local headerFrame = columnHeader:GetParent()
-
- --if this header does not have a clickable header, just ignore
- if (not headerFrame.columnSelected) then
- return
- end
-
- --check if this column has 'canSort' key, otherwise ignore the click
- if (not columnHeader.columnData.canSort) then
- return
- end
-
- --get the latest column header selected
- ---@type headercolumnframe
- local previousColumnHeader = headerFrame.columnHeadersCreated[headerFrame.columnSelected]
- previousColumnHeader.Arrow:Hide()
- headerFrame:ResetColumnHeaderBackdrop(previousColumnHeader)
- headerFrame:SetBackdropColorForSelectedColumnHeader(columnHeader)
-
- if (headerFrame.columnSelected == columnHeader.columnIndex) then
- columnHeader.order = columnHeader.order ~= "ASC" and "ASC" or "DESC"
- end
- headerFrame.columnOrder = columnHeader.order
-
- --set the new column header selected
- headerFrame.columnSelected = columnHeader.columnIndex
-
- headerFrame:UpdateSortArrow(columnHeader)
-
- if (headerFrame.options.header_click_callback) then
- --callback with the main header frame, column header, column index and column order as payload
- local okay, errortext = pcall(headerFrame.options.header_click_callback, headerFrame, columnHeader, columnHeader.columnIndex, columnHeader.order)
- if (not okay) then
- print("DF: Header onClick callback error:", errortext)
- end
- end
- end,
-
- ---comment
- ---@param self button
- ---@param buttonClicked string
- OnMouseDown = function(self, buttonClicked)
- if (buttonClicked == "LeftButton") then
-
- end
- end,
-
- ---comment
- ---@param self button
- ---@param buttonClicked string
- OnMouseUp = function(self, buttonClicked)
- if (buttonClicked == "LeftButton") then
-
- end
- end,
-}
-
-
-detailsFramework.HeaderCoreFunctions = {
- ---@param self headerframe
- ---@param columnId number
- ---@return number
- GetColumnWidth = function(self, columnId)
- return self.HeaderTable[columnId].width
- end,
-
- ---@param self headerframe
- ---@param newTable table
- SetHeaderTable = function(self, newTable)
- self.columnHeadersCreated = self.columnHeadersCreated or {}
- self.HeaderTable = newTable
- self.NextHeader = 1
- self.HeaderWidth = 0
- self.HeaderHeight = 0
- self:Refresh()
- end,
-
- ---@param self headerframe
- ---@param func function
- ---@return boolean
- SetColumnSettingChangedCallback = function(self, func)
- if (type(func) ~= "function") then
- self.OnColumnSettingChangeCallback = nil
- return false
- end
- self.OnColumnSettingChangeCallback = func
- return true
- end,
-
- --return which header is current selected and the the order ASC DESC
- ---@param self headerframe
- ---@return number, string
- GetSelectedColumn = function(self)
- ---@type number
- local columnSelected = self.columnSelected
- ---@type headercolumnframe
- local columnHeader = self.columnHeadersCreated[columnSelected or 1]
-
- return columnSelected, columnHeader.order, columnHeader.key
- end,
-
- --clean up and rebuild the header following the header options
- --@self: main header frame
- ---@param self headerframe
- Refresh = function(self)
- --refresh background frame
- self:SetBackdrop(self.options.backdrop)
- self:SetBackdropColor(unpack(self.options.backdrop_color))
- self:SetBackdropBorderColor(unpack(self.options.backdrop_border_color))
-
- --reset all header frames
- for i = 1, #self.columnHeadersCreated do
- local columnHeader = self.columnHeadersCreated[i]
- columnHeader.bInUse = false
- columnHeader:Hide()
- end
-
- local previousColumnHeader
- local growDirection = string.lower(self.options.grow_direction)
-
- --amount of headers to be updated
- local headerSize = #self.HeaderTable
-
- --update header frames
- for i = 1, headerSize do
- --get the header button, a new one is created if it doesn't exists yet
- local columnHeader = self:GetNextHeader()
- self:UpdateColumnHeader(columnHeader, i)
-
- --grow direction
- if (not previousColumnHeader) then
- columnHeader:SetPoint("topleft", self, "topleft", 0, 0)
-
- if (growDirection == "right") then
- if (self.options.use_line_separators) then
- columnHeader.Separator:Show()
- columnHeader.Separator:SetWidth(self.options.line_separator_width)
- columnHeader.Separator:SetColorTexture(unpack(self.options.line_separator_color))
-
- columnHeader.Separator:ClearAllPoints()
- if (self.options.line_separator_gap_align) then
- columnHeader.Separator:SetPoint("topleft", columnHeader, "topright", 0, 0)
- else
- columnHeader.Separator:SetPoint("topright", columnHeader, "topright", 0, 0)
- end
- columnHeader.Separator:SetHeight(self.options.line_separator_height)
- end
- end
- else
- if (growDirection == "right") then
- columnHeader:SetPoint("topleft", previousColumnHeader, "topright", self.options.padding, 0)
-
- if (self.options.use_line_separators) then
- columnHeader.Separator:Show()
- columnHeader.Separator:SetWidth(self.options.line_separator_width)
- columnHeader.Separator:SetColorTexture(unpack(self.options.line_separator_color))
-
- columnHeader.Separator:ClearAllPoints()
- if (self.options.line_separator_gap_align) then
- columnHeader.Separator:SetPoint("topleft", columnHeader, "topright", 0, 0)
- else
- columnHeader.Separator:SetPoint("topleft", columnHeader, "topright", 0, 0)
- end
- columnHeader.Separator:SetHeight(self.options.line_separator_height)
-
- if (headerSize == i) then
- columnHeader.Separator:Hide()
- end
- end
-
- elseif (growDirection == "left") then
- columnHeader:SetPoint("topright", previousColumnHeader, "topleft", -self.options.padding, 0)
-
- elseif (growDirection == "bottom") then
- columnHeader:SetPoint("topleft", previousColumnHeader, "bottomleft", 0, -self.options.padding)
-
- elseif (growDirection == "top") then
- columnHeader:SetPoint("bottomleft", previousColumnHeader, "topleft", 0, self.options.padding)
- end
- end
-
- previousColumnHeader = columnHeader
- end
-
- self:SetSize(self.HeaderWidth, self.HeaderHeight)
- end,
-
- ---@param self headerframe
- ---@param columnHeader headercolumnframe
- ---@param defaultShown boolean
- ---@param defaultOrder string
- UpdateSortArrow = function(self, columnHeader, defaultShown, defaultOrder)
- local options = self.options
- local order = defaultOrder or columnHeader.order
- local arrowIcon = columnHeader.Arrow
-
- if (type(defaultShown) ~= "boolean") then
- arrowIcon:Show()
- else
- arrowIcon:SetShown(defaultShown)
- if (defaultShown) then
- self:SetBackdropColorForSelectedColumnHeader(columnHeader)
- end
- end
-
- arrowIcon:SetAlpha(options.arrow_alpha)
-
- if (order == "ASC") then
- arrowIcon:SetTexture(options.arrow_up_texture)
- arrowIcon:SetTexCoord(unpack(options.arrow_up_texture_coords))
- arrowIcon:SetSize(unpack(options.arrow_up_size))
-
- elseif (order == "DESC") then
- arrowIcon:SetTexture(options.arrow_down_texture)
- arrowIcon:SetTexCoord(unpack(options.arrow_down_texture_coords))
- arrowIcon:SetSize(unpack(options.arrow_down_size))
- end
- end,
-
- ---@param self headerframe
- ---@param columnHeader headercolumnframe
- ---@param headerIndex number
- UpdateColumnHeader = function(self, columnHeader, headerIndex)
- --this is the data to update the columnHeader
- local columnData = self.HeaderTable[headerIndex]
-
- columnHeader.key = columnData.key or "total"
-
- if (columnData.icon) then
- columnHeader.Icon:SetTexture(columnData.icon)
-
- if (columnData.texcoord) then
- columnHeader.Icon:SetTexCoord(unpack(columnData.texcoord))
- else
- columnHeader.Icon:SetTexCoord(0, 1, 0, 1)
- end
-
- columnHeader.Icon:SetPoint("left", columnHeader, "left", self.options.padding, 0)
- columnHeader.Icon:Show()
- end
-
- if (columnData.text) then
- columnHeader.Text:SetText(columnData.text)
-
- --text options
- detailsFramework:SetFontColor(columnHeader.Text, self.options.text_color)
- detailsFramework:SetFontSize(columnHeader.Text, self.options.text_size)
- detailsFramework:SetFontOutline(columnHeader.Text, self.options.text_shadow)
-
- --point
- if (not columnData.icon) then
- columnHeader.Text:SetPoint("left", columnHeader, "left", self.options.padding, 0)
- else
- columnHeader.Text:SetPoint("left", columnHeader.Icon, "right", self.options.padding, 0)
- end
-
- columnHeader.Text:Show()
- end
-
- --column header index
- columnHeader.columnIndex = headerIndex
-
- if (columnData.canSort) then
- columnHeader.order = "DESC"
- columnHeader.Arrow:SetTexture(self.options.arrow_up_texture)
- else
- columnHeader.Arrow:Hide()
- end
-
- if (columnData.selected) then
- columnHeader.Arrow:Show()
- columnHeader.Arrow:SetAlpha(.843)
- self:UpdateSortArrow(columnHeader, true, columnHeader.order)
- self.columnSelected = headerIndex
- else
- if (columnData.canSort) then
- self:UpdateSortArrow(columnHeader, false, columnHeader.order)
- end
- end
-
- --size
- if (columnData.width) then
- columnHeader:SetWidth(columnData.width)
- end
- if (columnData.height) then
- columnHeader:SetHeight(columnData.height)
- end
-
- columnHeader.XPosition = self.HeaderWidth -- + self.options.padding
- columnHeader.YPosition = self.HeaderHeight -- + self.options.padding
-
- columnHeader.columnAlign = columnData.align or "left"
- columnHeader.columnOffset = columnData.offset or 0
-
- --add the header piece size to the total header size
- local growDirection = string.lower(self.options.grow_direction)
-
- if (growDirection == "right" or growDirection == "left") then
- self.HeaderWidth = self.HeaderWidth + columnHeader:GetWidth() + self.options.padding
- self.HeaderHeight = math.max(self.HeaderHeight, columnHeader:GetHeight())
-
- elseif (growDirection == "top" or growDirection == "bottom") then
- self.HeaderWidth = math.max(self.HeaderWidth, columnHeader:GetWidth())
- self.HeaderHeight = self.HeaderHeight + columnHeader:GetHeight() + self.options.padding
- end
-
- local bShowColumnHeaderReziser = self.options.reziser_shown
- if (bShowColumnHeaderReziser) then
- local resizerButton = columnHeader.resizerButton
- resizerButton:Show()
- resizerButton.texture:SetVertexColor(unpack(self.options.reziser_color))
- resizerButton:SetWidth(self.options.reziser_width)
- resizerButton:SetHeight(columnHeader:GetHeight())
- else
- columnHeader.resizerButton:Hide()
- end
-
- columnHeader:Show()
- columnHeader.bInUse = true
- columnHeader.columnData = columnData
- end,
-
- ---reset column header backdrop
- ---@param self headerframe
- ---@param columnHeader headercolumnframe
- ResetColumnHeaderBackdrop = function(self, columnHeader)
- columnHeader:SetBackdrop(self.options.header_backdrop)
- columnHeader:SetBackdropColor(unpack(self.options.header_backdrop_color))
- columnHeader:SetBackdropBorderColor(unpack(self.options.header_backdrop_border_color))
- end,
-
- ---@param self headerframe
- ---@param columnHeader headercolumnframe
- SetBackdropColorForSelectedColumnHeader = function(self, columnHeader)
- columnHeader:SetBackdropColor(unpack(self.options.header_backdrop_color_selected))
- end,
-
- ---clear the column header
- ---@param self headerframe
- ---@param columnHeader headercolumnframe
- ClearColumnHeader = function(self, columnHeader)
- columnHeader:SetSize(self.options.header_width, self.options.header_height)
- self:ResetColumnHeaderBackdrop(columnHeader)
-
- columnHeader:ClearAllPoints()
-
- columnHeader.Icon:SetTexture("")
- columnHeader.Icon:Hide()
- columnHeader.Text:SetText("")
- columnHeader.Text:Hide()
- end,
-
- ---get the next column header, create one if doesn't exists
- ---@param self headerframe
- GetNextHeader = function(self)
- local nextHeader = self.NextHeader
- local columnHeader = self.columnHeadersCreated[nextHeader]
-
- if (not columnHeader) then
- --create a new column header
- ---@type headercolumnframe
- columnHeader = CreateFrame("button", "$parentHeaderIndex" .. nextHeader, self, "BackdropTemplate")
- columnHeader:SetScript("OnClick", detailsFramework.HeaderFunctions.OnClick)
- columnHeader:SetMovable(true)
- columnHeader:SetResizable(true)
-
- --header icon
- detailsFramework:CreateImage(columnHeader, "", self.options.header_height, self.options.header_height, "ARTWORK", nil, "Icon", "$parentIcon")
- --header separator
- detailsFramework:CreateImage(columnHeader, "", 1, 1, "ARTWORK", nil, "Separator", "$parentSeparator")
- --header name text
- detailsFramework:CreateLabel(columnHeader, "", self.options.text_size, self.options.text_color, "GameFontNormal", "Text", "$parentText", "ARTWORK")
- --header selected and order icon
- detailsFramework:CreateImage(columnHeader, self.options.arrow_up_texture, 12, 12, "ARTWORK", nil, "Arrow", "$parentArrow")
-
- ---rezise button
- ---@type button
- local resizerButton = _G.CreateFrame("button", "$parentResizer", columnHeader)
- resizerButton:SetWidth(4)
- resizerButton:SetFrameLevel(columnHeader:GetFrameLevel()+2)
- resizerButton:SetPoint("topright", columnHeader, "topright", -1, -1)
- resizerButton:SetPoint("bottomright", columnHeader, "bottomright", -1, 1)
- resizerButton:EnableMouse(true)
- resizerButton:RegisterForClicks("LeftButtonDown", "LeftButtonUp")
- columnHeader.resizerButton = resizerButton
-
- resizerButton:SetScript("OnEnter", function()
- resizerButton.texture:SetVertexColor(1, 1, 1, 0.9)
- end)
-
- resizerButton:SetScript("OnLeave", function()
- resizerButton.texture:SetVertexColor(unpack(self.options.reziser_color))
- end)
-
- resizerButton:SetScript("OnMouseDown", function() --move this to a single function
- if (not columnHeader.bIsRezising) then
- --get the string length to know the min size
- local textLength = columnHeader.Text:GetStringWidth() + 6
- columnHeader:SetResizeBounds(math.max(textLength, self.options.reziser_min_width), columnHeader:GetHeight(), self.options.reziser_max_width, columnHeader:GetHeight())
- columnHeader.bIsRezising = true
- columnHeader:StartSizing("right")
- end
- end)
-
- resizerButton:SetScript("OnMouseUp", function()
- if (columnHeader.bIsRezising) then
- columnHeader.bIsRezising = false
- columnHeader:StopMovingOrSizing()
-
- --callback or modify into a passed by table?
- if (self.OnColumnSettingChangeCallback) then --need to get the header name
- local columnName = columnHeader.columnData.name
- xpcall(self.OnColumnSettingChangeCallback, geterrorhandler(), self, "width", columnName, columnHeader:GetWidth())
- end
- end
- end)
-
- resizerButton:SetScript("OnHide", function()
- if (columnHeader.bIsRezising) then
- columnHeader:StopMovingOrSizing()
- columnHeader.bIsRezising = false
- end
- end)
-
- resizerButton.texture = resizerButton:CreateTexture(nil, "overlay")
- resizerButton.texture:SetAllPoints()
- resizerButton.texture:SetColorTexture(1, 1, 1, 1)
-
- columnHeader.Arrow:SetPoint("right", columnHeader, "right", -1, 0)
-
- columnHeader.Separator:Hide()
- columnHeader.Arrow:Hide()
-
- self:UpdateSortArrow(columnHeader, false, "DESC")
-
- tinsert(self.columnHeadersCreated, columnHeader)
- columnHeader = columnHeader
- end
-
- self:ClearColumnHeader(columnHeader)
- self.NextHeader = self.NextHeader + 1
- return columnHeader
- end,
-
- NextHeader = 1,
- HeaderWidth = 0,
- HeaderHeight = 0,
-}
-
-local default_header_options = {
- backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
- backdrop_color = {0, 0, 0, 0.2},
- backdrop_border_color = {0.1, 0.1, 0.1, .2},
-
- text_color = {1, 1, 1, 1},
- text_size = 10,
- text_shadow = false,
- grow_direction = "RIGHT",
- padding = 2,
-
- reziser_shown = false, --make sure to set the callback function with: header:SetOnColumnResizeScript(callbackFunction)
- reziser_width = 2,
- reziser_color = {1, 0.6, 0, 0.6},
- reziser_min_width = 16,
- reziser_max_width = 200,
-
- --each piece of the header
- header_backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
- header_backdrop_color = {0, 0, 0, 0.5},
- header_backdrop_color_selected = {0.3, 0.3, 0.3, 0.5},
- header_backdrop_border_color = {0, 0, 0, 0},
- header_width = 120,
- header_height = 20,
-
- arrow_up_texture = [[Interface\Buttons\Arrow-Up-Down]],
- arrow_up_texture_coords = {0, 1, 6/16, 1},
- arrow_up_size = {12, 11},
- arrow_down_texture = [[Interface\Buttons\Arrow-Down-Down]],
- arrow_down_texture_coords = {0, 1, 0, 11/16},
- arrow_down_size = {12, 11},
- arrow_alpha = 0.659,
-
- use_line_separators = false,
- line_separator_color = {.1, .1, .1, .6},
- line_separator_width = 1,
- line_separator_height = 200,
- line_separator_gap_align = false,
-}
-
----@return headerframe
-function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
- ---@type headerframe
- local newHeader = _G.CreateFrame("frame", frameName or "$parentHeaderLine", parent, "BackdropTemplate")
-
- detailsFramework:Mixin(newHeader, detailsFramework.OptionsFunctions)
- detailsFramework:Mixin(newHeader, detailsFramework.HeaderCoreFunctions)
-
- newHeader:BuildOptionsTable(default_header_options, options)
-
- newHeader:SetBackdrop(newHeader.options.backdrop)
- newHeader:SetBackdropColor(unpack(newHeader.options.backdrop_color))
- newHeader:SetBackdropBorderColor(unpack(newHeader.options.backdrop_border_color))
-
- newHeader:SetHeaderTable(headerTable)
-
- return newHeader
-end
-
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--radio group
diff --git a/frames/window_playerbreakdown_spells.lua b/frames/window_playerbreakdown_spells.lua
index 7dba9966..6bff39aa 100644
--- a/frames/window_playerbreakdown_spells.lua
+++ b/frames/window_playerbreakdown_spells.lua
@@ -78,9 +78,21 @@ local headerContainerType = {}
---@type number
local columnOffset = 0
----default settings for the header of the spells container
----label is a localized string
----@type {name: string, width: number, selected: boolean|nil, label: string, align: string, enabled: boolean, attribute: number|nil, canSort: boolean|nil, dataType: string|nil, order: string|nil, offset: number|nil}[]
+---@class headercolumndatasaved : {enabled: boolean, width: number, align: string}
+local settingsPrototype = {
+ enabled = true,
+ width = 100,
+ align = "left",
+}
+
+---headercolumndata goes inside the header table which is passed to the header constructor or header:SetHeaderTable()
+---@class headercolumndata : {name:string, width:number, text:string, align:string, key:string, selected:boolean, canSort:boolean, dataType:string, order:string, offset:number, key:string}
+
+---columndata is the raw table with all options which can be used to create a headertable, some may not be used due to settings or filtering
+---@class columndata : {name:string, width:number, key:string, selected:boolean, label:string, align:string, enabled:boolean, attribute:number, canSort:boolean, dataType:string, order:string, offset:number}
+
+---default settings for the header of the spells container, label is a localized string, name is a string used to save the column settings, key is the key used to get the value from the spell table, width is the width of the column, align is the alignment of the text, enabled is if the column is enabled, canSort is if the column can be sorted, sortKey is the key used to sort the column, dataType is the type of data the column is sorting, order is the order of the sorting, offset is the offset of the column
+---@type columndata[]
local spellContainerColumnInfo = {
{name = "icon", width = 22, label = "", align = "center", enabled = true, offset = columnOffset},
{name = "target", width = 22, label = "", align = "center", enabled = true, offset = columnOffset},
@@ -89,18 +101,18 @@ local spellContainerColumnInfo = {
{name = "name", label = "spell name", width = 246, align = "left", enabled = true, offset = columnOffset},
{name = "amount", label = "total", key = "total", selected = true, width = 50, align = "left", enabled = true, canSort = true, sortKey = "total", dataType = "number", order = "DESC", offset = columnOffset},
{name = "persecond", label = "ps", key = "total", width = 50, align = "left", enabled = true, canSort = true, sortKey = "ps", offset = columnOffset, order = "DESC", dataType = "number"},
- {name = "percent", label = "%", key = "total", width = 50, align = "left", enabled = true, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
- {name = "casts", label = "casts", key = "total", width = 40, align = "left", enabled = false, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
- {name = "critpercent", label = "crit %", key = "total", width = 40, align = "left", enabled = false, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
- {name = "hits", label = "hits", key = "counter", width = 40, align = "left", enabled = false, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
- {name = "castavg", label = "cast avg", key = "total", width = 50, align = "left", enabled = false, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
- {name = "uptime", label = "uptime", key = "total", width = 45, align = "left", enabled = false, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
+ {name = "percent", label = "%", key = "percent", width = 50, align = "left", enabled = true, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
+ {name = "casts", label = "casts", key = "casts", width = 40, align = "left", enabled = true, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
+ {name = "critpercent", label = "crit %", key = "total", width = 40, align = "left", enabled = true, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
+ {name = "hits", label = "hits", key = "counter", width = 40, align = "left", enabled = true, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
+ {name = "castavg", label = "cast avg", key = "total", width = 50, align = "left", enabled = true, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
+ {name = "uptime", label = "uptime", key = "total", width = 45, align = "left", enabled = true, canSort = true, offset = columnOffset, order = "DESC", dataType = "number"},
{name = "overheal", label = "overheal", key = "total", width = 45, align = "left", enabled = false, canSort = true, order = "DESC", dataType = "number", attribute = DETAILS_ATTRIBUTE_HEAL, offset = columnOffset},
{name = "absorbed", label = "absorbed", key = "total", width = 45, align = "left", enabled = false, canSort = true, order = "DESC", dataType = "number", attribute = DETAILS_ATTRIBUTE_HEAL, offset = columnOffset},
}
---callback for when the user resizes a column on the header
----@param headerFrame headerframe
+---@param headerFrame df_headerframe
---@param optionName string
---@param columnName string
---@param value any
@@ -123,8 +135,8 @@ local onHeaderColumnOptionChanged = function(headerFrame, optionName, columnName
end
---run when the user clicks the columnHeader
----@param headerFrame headerframe
----@param columnHeader headercolumnframe
+---@param headerFrame df_headerframe
+---@param columnHeader df_headercolumnframe
local onColumnHeaderClickCallback = function(headerFrame, columnHeader)
print("column header clicked!")
@@ -163,16 +175,21 @@ function spellsTab.UpdateHeadersSettings(containerType)
local columnData = containerInfo[i]
---@type string
local columnName = columnData.name
+
--column settings for the column on details profile
+ ---@type headercolumndatasaved
local columnSettings = settings[columnName]
+
--check if this column does not have a mirror table in details profile
if (not columnSettings) then
- --create the mirror table
- settings[columnName] = {
- enabled = columnData.enabled,
- width = columnData.width,
- align = columnData.align,
- }
+ --create a table in Details! saved variables to save the column settings
+ ---@type headercolumndatasaved
+ local newColumnSettings = DetailsFramework.table.copy({}, settingsPrototype)
+ settings[columnName] = newColumnSettings
+
+ newColumnSettings.enabled = columnData.enabled
+ newColumnSettings.width = columnData.width
+ newColumnSettings.align = columnData.align
end
end
@@ -189,7 +206,7 @@ end
---@param containerType "spells"|"targets"
---@return {name: string, width: number, text: string, align: string}[]
function spellsTab.BuildHeaderTable(containerType)
- ---@type {name: string, width: number, text: string, align: string}[]
+ ---@type headercolumndata[]
local headerTable = {}
---@type instance
@@ -207,12 +224,12 @@ function spellsTab.BuildHeaderTable(containerType)
if (containerType == "spells") then
settings = spellsTab.spellcontainer_header_settings
containerInfo = spellContainerColumnInfo
+
elseif (containerType == "targets") then
end
for i = 1, #containerInfo do
- ---@type {name: string, width: number, selected: boolean|nil, label: string, align: string, enabled: boolean, attribute: number|nil, canSort: boolean|nil, dataType: string|nil, order: string|nil, offset: number|nil}
local columnData = containerInfo[i]
---@type {enabled: boolean, width: number, align: string}
local columnSettings = settings[columnData.name]
@@ -228,7 +245,11 @@ function spellsTab.BuildHeaderTable(containerType)
end
if (bCanAdd) then
- headerTable[#headerTable+1] = {
+ --print("key added:", columnData.key)
+ --key = "casts", key = "percent",
+
+ ---@type headercolumndata
+ local headerColumnData = {
width = columnSettings.width,
text = columnData.label,
name = columnData.name,
@@ -240,8 +261,13 @@ function spellsTab.BuildHeaderTable(containerType)
dataType = columnData.dataType,
order = columnData.order,
offset = columnData.offset,
+ key = columnData.key,
}
+
+ headerTable[#headerTable+1] = headerColumnData
end
+ else
+ --targets
end
end
@@ -343,7 +369,7 @@ function spellsTab.OnCreateTabCallback(tabButton, tabFrame)
spellsTab.TabFrame = tabFrame
--open the breakdown window at startup
- --[=[
+ --[=
C_Timer.After(1, function()
Details:OpenPlayerDetails(1)
C_Timer.After(1, function()
@@ -1299,7 +1325,7 @@ function spellsTab.CreateSpellScrollContainer(tabFrame)
local headerTable = {}
- ---@type headerframe
+ ---@type df_headerframe
local header = DetailsFramework:CreateHeader(tabFrame, headerTable, headerOptions)
scrollFrame.Header = header
scrollFrame.Header:SetPoint("topleft", scrollFrame, "topleft", 0, 1)
@@ -1320,11 +1346,10 @@ function spellsTab.CreateSpellScrollContainer(tabFrame)
--get which column is currently selected and the sort order
local columnIndex, order, key = scrollFrame.Header:GetSelectedColumn()
- --here need an api from the header frame to get the key to sort
- print("key:", key)
- --problem: -----
-
- --pre process the data which may be used into the scroll
+ --key = "casts", key = "percent",
+ --at this stage, data does not have the information about amount of casts and percent, it only has the total value, how to solve this?
+ --need to pre process the data before sorting it
+ --key "total" is workng as intended
---@type string
local keyToSort = "total"
diff --git a/functions/currentdps.lua b/functions/currentdps.lua
index 94bdb072..aa5b987e 100644
--- a/functions/currentdps.lua
+++ b/functions/currentdps.lua
@@ -1,8 +1,10 @@
-
local Details = _G.Details
local addonName, Details222 = ...
+local bIsEnabled = false
+local testCharacterName = "Ditador"
+
--namespace
Details.CurrentDps = {
Dps = {},
@@ -41,27 +43,27 @@ currentDpsFrame.OnUpdateFunc = function(self, deltaTime)
--get the damage done on this tick
local totalDamageThisTick = actorObject.total - actorTable.latestDamageAmount
--add the damage to the cache
- tinsert(actorTable.cache, 1, totalDamageThisTick)
+ table.insert(actorTable.cache, 1, totalDamageThisTick)
--set the latest damage amount
actorTable.latestDamageAmount = actorObject.total
--sum the total damage the actor inflicted
actorTable.totalDamage = actorTable.totalDamage + totalDamageThisTick
--cut the damage
- local damageRemoved = tremove(actorTable.cache, cacheOverflowIndex)
+ local damageRemoved = table.remove(actorTable.cache, cacheOverflowIndex)
if (damageRemoved) then
actorTable.totalDamage = actorTable.totalDamage - damageRemoved
- actorTable.totalDamage = max(0, actorTable.totalDamage) --safe guard
+ actorTable.totalDamage = math.max(0, actorTable.totalDamage) --safe guard
end
actorTable.currentDps = actorTable.totalDamage / dpsTime
- if (actorObject.nome == "Ditador") then
+ if (actorObject.nome == testCharacterName) then --debug
local formatToKFunc = Details:GetCurrentToKFunction()
print(actorTable.totalDamage, #actorTable.cache, dpsTime, formatToKFunc(nil, actorTable.currentDps))
end
- if (actorObject.nome == "Ditador") then
- --print("Dps:", actorTable.currentDps)
+ if (actorObject.nome == testCharacterName) then --debug
+ print("Dps:", actorTable.currentDps)
end
end
end
@@ -94,8 +96,13 @@ end
--handle internal details! events
local eventListener = Details:CreateEventListener()
eventListener:RegisterEvent("COMBAT_PLAYER_ENTER", function()
- --Details.CurrentDps.StartCurrentDpsTracker()
+ if (bIsEnabled) then
+ Details.CurrentDps.StartCurrentDpsTracker()
+ end
end)
+
eventListener:RegisterEvent("COMBAT_PLAYER_LEAVE", function()
- --Details.CurrentDps.StopCurrentDpsTracker()
+ if (bIsEnabled) then
+ Details.CurrentDps.StopCurrentDpsTracker()
+ end
end)
\ No newline at end of file