You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
789 lines
27 KiB
789 lines
27 KiB
|
|
local detailsFramework = DetailsFramework
|
|
|
|
if (not detailsFramework or not DetailsFrameworkCanLoad) then
|
|
return
|
|
end
|
|
|
|
local unpack = unpack
|
|
local CreateFrame = CreateFrame
|
|
local geterrorhandler = geterrorhandler
|
|
local wipe = wipe
|
|
|
|
--definitions
|
|
|
|
---@class df_headercolumndata : table
|
|
---@field key string?
|
|
---@field name string?
|
|
---@field icon string?
|
|
---@field texcoord table?
|
|
---@field text string?
|
|
---@field canSort boolean?
|
|
---@field selected boolean?
|
|
---@field width number?
|
|
---@field height number?
|
|
---@field align string?
|
|
---@field offset number?
|
|
---@field columnSpan number?
|
|
|
|
---@class df_headerchild : uiobject
|
|
---@field FramesToAlign table
|
|
|
|
---@class df_headerframe : frame, df_headermixin, df_optionsmixin
|
|
---@field columnOrder string
|
|
---@field columnHeadersCreated df_headercolumnframe[]
|
|
---@field options table
|
|
---@field HeaderTable df_headercolumndata[]
|
|
---@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) : number
|
|
---@field SetHeaderTable fun(self: df_headerframe, table)
|
|
---@field GetSelectedColumn fun(self: df_headerframe) : number, string, 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 internal use only
|
|
---@field SetColumnSettingChangedCallback fun(self: df_headerframe, func: function) : boolean
|
|
---@field ResetFramesToHeaderAlignment fun(self: df_headerframe)
|
|
---@field GetFramesFromHeaderAlignment fun(self: df_headerframe) : table
|
|
---@field GetSelectedHeaderColumnData fun(self: df_headerframe) : df_headercolumndata
|
|
---@field GetHeaderTable fun(self: df_headerframe) : df_headercolumndata[]
|
|
---@field PropagateClicks fun(self: df_headerframe, propagate: boolean) if the header and its children should propagate clicks
|
|
|
|
---@class df_headercolumnframe : button
|
|
---@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 YPosition number
|
|
---@field columnOffset number
|
|
---@field key string used to sort the values
|
|
|
|
---@class df_headerresizer : button
|
|
---@field texture texture
|
|
|
|
--mixed functions
|
|
---@class df_headerfunctions : table
|
|
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)
|
|
self.FramesToAlign = self.FramesToAlign or {}
|
|
--hide all frames
|
|
for i = 1, #self.FramesToAlign do
|
|
local uiObject = self.FramesToAlign[i]
|
|
uiObject:Hide()
|
|
end
|
|
wipe(self.FramesToAlign)
|
|
end,
|
|
|
|
SetFramesToHeaderAlignment = function(self, ...)
|
|
self.FramesToAlign = self.FramesToAlign or {}
|
|
---@cast self df_headerchild
|
|
wipe(self.FramesToAlign)
|
|
self.FramesToAlign = {...}
|
|
end,
|
|
|
|
GetFramesFromHeaderAlignment = function(self)
|
|
self.FramesToAlign = self.FramesToAlign or {}
|
|
return self.FramesToAlign
|
|
end,
|
|
|
|
---@param self uiobject
|
|
---@param headerFrame df_headerframe
|
|
---@param anchor string
|
|
AlignWithHeader = function(self, headerFrame, anchor)
|
|
assert(type(headerFrame) == "table" and headerFrame.GetColumnWidth, "Details! Framework: AlignWithHeader(): 'headerFrame' is not of type df_headerframe.\n" .. debugstack(2, 1, 1))
|
|
|
|
local columnHeaderFrames = headerFrame.columnHeadersCreated
|
|
anchor = anchor or "topleft"
|
|
|
|
---@cast self df_headerchild
|
|
|
|
for i = 1, #self.FramesToAlign do
|
|
---@type uiobject
|
|
local uiObject = self.FramesToAlign[i]
|
|
uiObject:ClearAllPoints()
|
|
|
|
---@type df_headercolumnframe
|
|
local columnHeader = columnHeaderFrames[i]
|
|
if (columnHeader) then
|
|
local offset = 0
|
|
|
|
if (columnHeader.columnAlign == "right") then
|
|
offset = columnHeader:GetWidth()
|
|
end
|
|
|
|
if (uiObject:GetObjectType() == "FontString") then
|
|
---@cast uiObject fontstring
|
|
if (columnHeader.columnAlign == "right") then
|
|
uiObject:SetJustifyH("right")
|
|
elseif (columnHeader.columnAlign == "left") then
|
|
uiObject:SetJustifyH("left")
|
|
elseif (columnHeader.columnAlign == "center") then
|
|
uiObject:SetJustifyH("center")
|
|
end
|
|
end
|
|
|
|
uiObject:SetPoint(columnHeader.columnAlign, self, anchor, columnHeader.XPosition + columnHeader.columnOffset + offset, 0)
|
|
uiObject:Show()
|
|
end
|
|
end
|
|
end,
|
|
|
|
---comment
|
|
---@param newColumnHeaderToSort df_headercolumnframe
|
|
---@param buttonClicked string
|
|
OnClick = function(newColumnHeaderToSort, buttonClicked)
|
|
--get the header main frame
|
|
local headerFrame = newColumnHeaderToSort:GetParent()
|
|
---@cast headerFrame df_headerframe
|
|
|
|
--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 newColumnHeaderToSort.columnData.canSort) then
|
|
return
|
|
end
|
|
|
|
--get the latest column header selected and reset its backdrop and hide the arrow
|
|
---@type df_headercolumnframe
|
|
local previousColumnHeader = headerFrame.columnHeadersCreated[headerFrame.columnSelected]
|
|
previousColumnHeader.Arrow:Hide()
|
|
headerFrame:ResetColumnHeaderBackdrop(previousColumnHeader)
|
|
|
|
headerFrame:SetBackdropColorForSelectedColumnHeader(newColumnHeaderToSort)
|
|
|
|
if (headerFrame.columnSelected == newColumnHeaderToSort.columnIndex) then
|
|
newColumnHeaderToSort.order = newColumnHeaderToSort.order ~= "ASC" and "ASC" or "DESC"
|
|
end
|
|
headerFrame.columnOrder = newColumnHeaderToSort.order
|
|
|
|
--set the new column header selected
|
|
headerFrame.columnSelected = newColumnHeaderToSort.columnIndex
|
|
|
|
headerFrame:UpdateSortArrow(newColumnHeaderToSort)
|
|
|
|
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 = xpcall(headerFrame.options.header_click_callback, geterrorhandler(), headerFrame, newColumnHeaderToSort, newColumnHeaderToSort.columnIndex, newColumnHeaderToSort.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,
|
|
|
|
PropagateClicks = function(self, propagate)
|
|
self.options.propagate_clicks = propagate
|
|
self:Refresh()
|
|
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,
|
|
|
|
---get header table
|
|
---@param self df_headerframe
|
|
---@return df_headercolumndata[]
|
|
GetHeaderTable = function(self)
|
|
return self.HeaderTable
|
|
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, string, 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, columnHeader.columnData.name
|
|
end,
|
|
|
|
---get selected header column data
|
|
---@param self df_headerframe
|
|
---@return df_headercolumndata
|
|
GetSelectedHeaderColumnData = function(self)
|
|
local columnSelected = self.columnSelected
|
|
return self.HeaderTable[columnSelected]
|
|
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
|
|
|
|
local columnSpan = 0
|
|
|
|
if not InCombatLockdown() then
|
|
self:SetPropagateMouseClicks(self.options.propagate_clicks)
|
|
end
|
|
|
|
--update header frames
|
|
for headerIndex = 1, headerSize do
|
|
--get the header button, a new one is created if it doesn't exists yet
|
|
local columnHeader = self:GetNextHeader()
|
|
local columnData = self.HeaderTable[headerIndex]
|
|
self:UpdateColumnHeader(columnHeader, headerIndex)
|
|
|
|
if not InCombatLockdown() then
|
|
columnHeader:SetPropagateMouseClicks(self.options.propagate_clicks)
|
|
end
|
|
|
|
--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
|
|
if (columnSpan > 0) then
|
|
columnHeader:Hide()
|
|
columnHeader.Separator:Hide()
|
|
previousColumnHeader:SetWidth(previousColumnHeader:GetWidth() + columnHeader:GetWidth() + self.options.padding)
|
|
else
|
|
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 == headerIndex) then
|
|
columnHeader.Separator:Hide()
|
|
end
|
|
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
|
|
|
|
if (columnSpan > 0) then
|
|
columnSpan = columnSpan - 1
|
|
else
|
|
columnSpan = columnData.columnSpan or 0
|
|
end
|
|
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")
|
|
|
|
--store the mouse xy position when onmousedown the column header, when the mouse is up, before calling its onclick function, check if the mouse position is the same, if not ignore the click
|
|
--this prevents the click event when the user is trying to move the parent frame
|
|
columnHeader:SetScript("OnMouseDown", function(columnHeader, buttonClicked)
|
|
columnHeader.mouseDownX, columnHeader.mouseDownY = GetCursorPosition()
|
|
end)
|
|
columnHeader:SetScript("OnMouseUp", function(columnHeader, buttonReleased)
|
|
local mouseUpX, mouseUpY = GetCursorPosition()
|
|
if (columnHeader.mouseDownX == mouseUpX and columnHeader.mouseDownY == mouseUpY) then
|
|
-- Call the OnClick function if the mouse hasn't moved
|
|
detailsFramework.HeaderFunctions.OnClick(columnHeader, buttonReleased)
|
|
end
|
|
end)
|
|
|
|
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)
|
|
|
|
C_Timer.After(0.2, function() --delay a bit to avoid the cursor flickering when moving fast
|
|
if (not resizerButton:IsMouseOver()) then
|
|
return
|
|
end
|
|
--change the cursor to resize
|
|
if (SetCursor) then
|
|
SetCursor("UI_RESIZE_CURSOR")
|
|
end
|
|
end)
|
|
end)
|
|
|
|
resizerButton:SetScript("OnLeave", function()
|
|
resizerButton.texture:SetVertexColor(unpack(self.options.reziser_color))
|
|
if (ResetCursor) then
|
|
ResetCursor()
|
|
end
|
|
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)
|
|
|
|
local xOffset = self.options.reziser_shown and -5 or -1
|
|
columnHeader.Arrow:SetPoint("right", columnHeader, "right", xOffset, 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,
|
|
|
|
---return a header button by passing its name (.name on the column table)
|
|
---@param self df_headerframe
|
|
---@param columnName string
|
|
---@return df_headercolumnframe|nil
|
|
GetHeaderColumnByName = function(self, columnName)
|
|
for _, headerColumnFrame in ipairs(self.columnHeadersCreated) do
|
|
if (headerColumnFrame.columnData.name == columnName) then
|
|
return headerColumnFrame
|
|
end
|
|
end
|
|
end,
|
|
|
|
NextHeader = 1,
|
|
HeaderWidth = 0,
|
|
HeaderHeight = 0,
|
|
}
|
|
|
|
--default options
|
|
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},
|
|
|
|
propagate_clicks = false,
|
|
|
|
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 df_headerframe, alias 'header'.
|
|
---a header is a frame that can hold multiple columns which are also frames, each column is a df_headercolumnframe, these columns are arranged in horizontal form.
|
|
---a header is used to organize columns giving them a name/title, a way to sort and align them.
|
|
---each column is placed on the right side of the previous column.
|
|
---@param parent frame
|
|
---@param headerTable df_headercolumndata[]
|
|
---@param options table?
|
|
---@param frameName string?
|
|
---@return df_headerframe
|
|
function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
|
|
---create the header frame which is returned by this function
|
|
---@type df_headerframe
|
|
local newHeader = CreateFrame("frame", frameName or ("$parentHeaderLine" .. math.random(100000000)), parent, "BackdropTemplate")
|
|
|
|
detailsFramework:Mixin(newHeader, detailsFramework.OptionsFunctions)
|
|
detailsFramework:Mixin(newHeader, detailsFramework.HeaderMixin)
|
|
|
|
options = options or {}
|
|
newHeader:BuildOptionsTable(default_header_options, options)
|
|
|
|
--set the backdrop and backdrop color following the values in the options table
|
|
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
|
|
|
|
|
|
--[=[example:
|
|
C_Timer.After(1, function()
|
|
|
|
|
|
local parent = UIParent
|
|
|
|
--declare the columns the headerFrame will have
|
|
---@type df_headercolumndata[]
|
|
local headerTable = {
|
|
{name = "playername", text = "Player Name", width = 120, align = "left", canSort = true},
|
|
{name = "damage", text = "Damage Done", width = 80, align = "right", canSort = true},
|
|
{name = "points", text = "Total Points", width = 80, align = "right", canSort = false},
|
|
}
|
|
local frameName = "MyAddOnOptionsFrame"
|
|
local options = {}
|
|
|
|
local headerFrame = DetailsFramework:CreateHeader(parent, headerTable, options, frameName)
|
|
headerFrame:SetPoint("center", parent, "center", 10, -10)
|
|
|
|
|
|
end)
|
|
--]=]
|