Version Bump and Framework Update

This commit is contained in:
Tercio Jose
2023-05-20 11:16:48 -03:00
parent 7f4d966460
commit 64a7053089
11 changed files with 506 additions and 263 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
local dversion = 429
local dversion = 430
local major, minor = "DetailsFramework-1.0", dversion
local DF, oldminor = LibStub:NewLibrary(major, minor)
+40 -8
View File
@@ -11,13 +11,16 @@ local geterrorhandler = geterrorhandler
local wipe = wipe
--definitions
---@class df_headercolumndata : {key: string, name: string, icon: string, texcoord: table, text: string, canSort: boolean, selected: boolean, width: number, height: number, align: string, offset: number}
---@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 HeaderTable df_headercolumndata[]
---@field columnSelected number
---@class df_headermixin : table
@@ -25,8 +28,8 @@ local wipe = wipe
---@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 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)
@@ -127,8 +130,8 @@ detailsFramework.HeaderFunctions = {
---@param buttonClicked string
OnClick = function(columnHeader, buttonClicked)
--get the header main frame
---@type df_headerframe
local headerFrame = columnHeader:GetParent()
---@cast headerFrame df_headerframe
--if this header does not have a clickable header, just ignore
if (not headerFrame.columnSelected) then
@@ -352,7 +355,6 @@ detailsFramework.HeaderMixin = {
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
@@ -417,7 +419,7 @@ detailsFramework.HeaderMixin = {
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
@@ -589,6 +591,7 @@ detailsFramework.HeaderMixin = {
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},
@@ -629,13 +632,17 @@ local default_header_options = {
line_separator_gap_align = false,
}
---create a header frame
---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 table
---@param options table|nil
---@param frameName string|nil
---@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", parent, "BackdropTemplate")
@@ -644,6 +651,7 @@ function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
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))
@@ -651,4 +659,28 @@ function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
newHeader:SetHeaderTable(headerTable)
return newHeader
end
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)
--]=]
+1
View File
@@ -34,4 +34,5 @@
<Script file="pictureedit.lua"/>
<Script file="auras.lua"/>
<Script file="tabcontainer.lua"/>
</Ui>
+24 -237
View File
@@ -1976,37 +1976,50 @@ local no_options = {}
---UseStatusBar = false, --if true, creates a status bar at the bottom of the frame (frame.StatusBar)
---NoCloseButton = false, --if true, won't show the close button
---NoTitleBar = false, --if true, don't create the title bar
---@param parent table
---@param width number|nil
---@param height number|nil
---@param title string|nil
---@param frameName string|nil
---@param panelOptions table|nil
---@param savedVariableTable table|nil
---@return table
---@class simplepanel
---@field TitleBar frame
---@field Title fontstring
---@field Close button
---@field SetTitle fun(self: simplepanel, title: string)
---@param parent frame the parent frame
---@param width number|nil the width of the panel
---@param height number|nil the height of the panel
---@param title string|nil a string to show in the title bar
---@param frameName string|nil the name of the frame
---@param panelOptions table|nil a table with options described above
---@param savedVariableTable table|nil a table to save the scale of the panel
---@return frame
function detailsFramework:CreateSimplePanel(parent, width, height, title, frameName, panelOptions, savedVariableTable)
--create a saved variable table if the savedVariableTable has been not passed within the function call
if (savedVariableTable and frameName and not savedVariableTable[frameName]) then
savedVariableTable[frameName] = {
scale = 1
}
end
--create a frame name if the frameName has been not passed within the function call
if (not frameName) then
frameName = "DetailsFrameworkSimplePanel" .. detailsFramework.SimplePanelCounter
detailsFramework.SimplePanelCounter = detailsFramework.SimplePanelCounter + 1
end
--default parent is UIParent
if (not parent) then
parent = UIParent
parent = _G["UIParent"]
end
--default options
panelOptions = panelOptions or no_options
local simplePanel = CreateFrame("frame", frameName, UIParent,"BackdropTemplate")
--create the frame
local simplePanel = CreateFrame("frame", frameName, _G["UIParent"],"BackdropTemplate")
simplePanel:SetSize(width or 400, height or 250)
simplePanel:SetPoint("center", UIParent, "center", 0, 0)
simplePanel:SetPoint("center", _G["UIParent"], "center", 0, 0)
simplePanel:SetFrameStrata("FULLSCREEN")
simplePanel:EnableMouse()
simplePanel:SetMovable(true)
--set the backdrop
simplePanel:SetBackdrop(SimplePanel_frame_backdrop)
simplePanel:SetBackdropColor(unpack(SimplePanel_frame_backdrop_color))
simplePanel:SetBackdropBorderColor(unpack(SimplePanel_frame_backdrop_border_color))
@@ -3418,232 +3431,6 @@ function detailsFramework:FindHighestParent(self)
return highestParent
end
detailsFramework.TabContainerFunctions = {}
local button_tab_template = detailsFramework.table.copy({}, detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
button_tab_template.backdropbordercolor = nil
detailsFramework.TabContainerFunctions.CreateUnderlineGlow = function(button)
local selectedGlow = button:CreateTexture(nil, "background", nil, -4)
selectedGlow:SetPoint("topleft", button.widget, "bottomleft", -7, 0)
selectedGlow:SetPoint("topright", button.widget, "bottomright", 7, 0)
selectedGlow:SetTexture([[Interface\BUTTONS\UI-Panel-Button-Glow]])
selectedGlow:SetTexCoord(0, 95/128, 30/64, 38/64)
selectedGlow:SetBlendMode("ADD")
selectedGlow:SetHeight(8)
selectedGlow:SetAlpha(.75)
selectedGlow:Hide()
button.selectedUnderlineGlow = selectedGlow
end
detailsFramework.TabContainerFunctions.OnMouseDown = function(self, button)
--search for UIParent
local f = detailsFramework:FindHighestParent (self)
local container = self:GetParent()
if (button == "LeftButton") then
if (not f.IsMoving and f:IsMovable()) then
f:StartMoving()
f.IsMoving = true
end
elseif (button == "RightButton") then
if (not f.IsMoving and container.IsContainer) then
if (self.IsFrontPage) then
if (container.CanCloseWithRightClick) then
if (f.CloseFunction) then
f:CloseFunction()
else
f:Hide()
end
end
else
--goes back to front page
detailsFramework.TabContainerFunctions.SelectIndex (self, _, 1)
end
end
end
end
detailsFramework.TabContainerFunctions.OnMouseUp = function(self, button)
local f = detailsFramework:FindHighestParent (self)
if (f.IsMoving) then
f:StopMovingOrSizing()
f.IsMoving = false
end
end
detailsFramework.TabContainerFunctions.SelectIndex = function(self, fixedParam, menuIndex)
local mainFrame = self.AllFrames and self or self.mainFrame or self:GetParent()
for i = 1, #mainFrame.AllFrames do
mainFrame.AllFrames[i]:Hide()
if (mainFrame.ButtonNotSelectedBorderColor) then
mainFrame.AllButtons[i]:SetBackdropBorderColor(unpack(mainFrame.ButtonNotSelectedBorderColor))
end
if (mainFrame.AllButtons[i].selectedUnderlineGlow) then
mainFrame.AllButtons[i].selectedUnderlineGlow:Hide()
end
end
mainFrame.AllFrames[menuIndex]:Show()
if mainFrame.AllFrames[menuIndex].RefreshOptions then
mainFrame.AllFrames[menuIndex]:RefreshOptions()
end
if (mainFrame.ButtonSelectedBorderColor) then
mainFrame.AllButtons[menuIndex]:SetBackdropBorderColor(unpack(mainFrame.ButtonSelectedBorderColor))
end
if (mainFrame.AllButtons[menuIndex].selectedUnderlineGlow) then
mainFrame.AllButtons[menuIndex].selectedUnderlineGlow:Show()
end
mainFrame.CurrentIndex = menuIndex
if (mainFrame.hookList.OnSelectIndex) then
detailsFramework:QuickDispatch(mainFrame.hookList.OnSelectIndex, mainFrame, mainFrame.AllButtons[menuIndex])
end
end
detailsFramework.TabContainerFunctions.SetIndex = function(self, index)
self.CurrentIndex = index
end
local tab_container_on_show = function(self)
local index = self.CurrentIndex
self.SelectIndex (self.AllButtons[index], nil, index)
end
function detailsFramework:CreateTabContainer (parent, title, frameName, frameList, optionsTable, hookList, languageInfo)
local options_text_template = detailsFramework:GetTemplate("font", "OPTIONS_FONT_TEMPLATE")
local options_dropdown_template = detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
local options_switch_template = detailsFramework:GetTemplate("switch", "OPTIONS_CHECKBOX_TEMPLATE")
local options_slider_template = detailsFramework:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE")
local options_button_template = detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")
optionsTable = optionsTable or {}
local parentFrameWidth = parent:GetWidth()
local y_offset = optionsTable.y_offset or 0
local buttonWidth = optionsTable.button_width or 160
local buttonHeight = optionsTable.button_height or 20
local buttonAnchorX = optionsTable.button_x or 230
local buttonAnchorY = optionsTable.button_y or -32
local button_text_size = optionsTable.button_text_size or 10
local containerWidthOffset = optionsTable.container_width_offset or 0
local mainFrame = CreateFrame("frame", frameName, parent.widget or parent, "BackdropTemplate")
mainFrame:SetAllPoints()
detailsFramework:Mixin(mainFrame, detailsFramework.TabContainerFunctions)
mainFrame.hookList = hookList or {}
local mainTitle = detailsFramework:CreateLabel(mainFrame, title, 24, "white")
mainTitle:SetPoint("topleft", mainFrame, "topleft", 10, -30 + y_offset)
mainFrame:SetFrameLevel(200)
mainFrame.AllFrames = {}
mainFrame.AllButtons = {}
mainFrame.CurrentIndex = 1
mainFrame.IsContainer = true
mainFrame.ButtonSelectedBorderColor = optionsTable.button_selected_border_color or {1, 1, 0, 1}
mainFrame.ButtonNotSelectedBorderColor = optionsTable.button_border_color or {0, 0, 0, 0}
if (optionsTable.right_click_interact ~= nil) then
mainFrame.CanCloseWithRightClick = optionsTable.right_click_interact
else
mainFrame.CanCloseWithRightClick = true
end
--languageInfo
local addonId = languageInfo and languageInfo.language_addonId or "none"
for i, frameInfo in ipairs(frameList) do
local f = CreateFrame("frame", "$parent" .. frameInfo.name, mainFrame, "BackdropTemplate")
f:SetAllPoints()
f:SetFrameLevel(210)
f:Hide()
--attempt to get the localized text from the language system using the addonId and the frameInfo.title
local phraseId = frameInfo.title
local bIsLanguagePrahseID = detailsFramework.Language.DoesPhraseIDExistsInDefaultLanguage(addonId, phraseId)
local title = detailsFramework:CreateLabel(f, "", 16, "silver")
if (bIsLanguagePrahseID) then
DetailsFramework.Language.RegisterObjectWithDefault(addonId, title.widget, frameInfo.title, frameInfo.title)
else
title:SetText(frameInfo.title)
end
title:SetPoint("topleft", mainTitle, "bottomleft", 0, 0)
f.titleText = title
local tabButton = detailsFramework:CreateButton(mainFrame, detailsFramework.TabContainerFunctions.SelectIndex, buttonWidth, buttonHeight, frameInfo.title, i, nil, nil, nil, "$parentTabButton" .. frameInfo.name, false, button_tab_template)
if (bIsLanguagePrahseID) then
DetailsFramework.Language.RegisterObjectWithDefault(addonId, tabButton.widget, frameInfo.title, frameInfo.title)
end
PixelUtil.SetSize(tabButton, buttonWidth, buttonHeight)
tabButton:SetFrameLevel(220)
tabButton.textsize = button_text_size
tabButton.mainFrame = mainFrame
detailsFramework.TabContainerFunctions.CreateUnderlineGlow(tabButton)
local rightClickToBack
if (i == 1 or optionsTable.rightbutton_always_close) then
rightClickToBack = detailsFramework:CreateLabel(f, "right click to close", 10, "gray")
rightClickToBack:SetPoint("bottomright", f, "bottomright", -1, optionsTable.right_click_y or 0)
if (optionsTable.close_text_alpha) then
rightClickToBack:SetAlpha(optionsTable.close_text_alpha)
end
f.IsFrontPage = true
else
rightClickToBack = detailsFramework:CreateLabel(f, "right click to go back to main menu", 10, "gray")
rightClickToBack:SetPoint("bottomright", f, "bottomright", -1, optionsTable.right_click_y or 0)
if (optionsTable.close_text_alpha) then
rightClickToBack:SetAlpha(optionsTable.close_text_alpha)
end
end
if (optionsTable.hide_click_label) then
rightClickToBack:Hide()
end
f:SetScript("OnMouseDown", detailsFramework.TabContainerFunctions.OnMouseDown)
f:SetScript("OnMouseUp", detailsFramework.TabContainerFunctions.OnMouseUp)
tinsert(mainFrame.AllFrames, f)
tinsert(mainFrame.AllButtons, tabButton)
end
--order buttons
local x = buttonAnchorX
local y = buttonAnchorY
local spaceBetweenButtons = 3
local allocatedSpaceForButtons = parentFrameWidth - ((#frameList - 2) * spaceBetweenButtons) - buttonAnchorX + containerWidthOffset
local amountButtonsPerRow = floor(allocatedSpaceForButtons / buttonWidth)
mainFrame.AllButtons[1]:SetPoint("topleft", mainTitle, "topleft", x, y)
x = x + buttonWidth + 2
for i = 2, #mainFrame.AllButtons do
local button = mainFrame.AllButtons[i]
PixelUtil.SetPoint(button, "topleft", mainTitle, "topleft", x, y)
x = x + buttonWidth + 2
if (i % amountButtonsPerRow == 0) then
x = buttonAnchorX
y = y - buttonHeight - 1
end
end
--when show the frame, reset to the current internal index
mainFrame:SetScript("OnShow", tab_container_on_show)
--select the first frame
mainFrame.SelectIndex (mainFrame.AllButtons[1], nil, 1)
print()
return mainFrame
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ~right ~click to ~close
+422
View File
@@ -0,0 +1,422 @@
local detailsFramework = DetailsFramework
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local unpack = unpack
local CreateFrame = CreateFrame
local PixelUtil = PixelUtil
---@class df_tabinfotable : {name: string, text: string}
---@class df_tabcontainer : frame
---@field AllFrames df_tabcontainerframe[]
---@field AllButtons df_tabcontainerbutton[]
---@field AllFramesByName table<string, df_tabcontainerframe>
---@field AllButtonsByName table<string, df_tabcontainerbutton>
---@field hookList table
---@field CurrentIndex number
---@field IsContainer boolean
---@field ButtonSelectedBorderColor table
---@field ButtonNotSelectedBorderColor table
---@field CanCloseWithRightClick boolean
---@field SetIndex fun(self: df_tabcontainer, index: number)
---@field SelectTabByIndex fun(self: df_tabcontainer, menuIndex: number)
---@field SelectTabByName fun(self: df_tabcontainer, name: string)
---@field CreateUnderlineGlow fun(button: button)
---@field OnShow fun(self: df_tabcontainer)
---@field GetTabFrameByName fun(self: df_tabcontainer, name: string): df_tabcontainerframe
---@field GetTabFrameByIndex fun(self: df_tabcontainer, index: number): df_tabcontainerframe
---@field GetTabButtonByName fun(self: df_tabcontainer, name: string): df_tabcontainerbutton
---@field GetTabButtonByIndex fun(self: df_tabcontainer, index: number): df_tabcontainerbutton
---@class df_tabcontainerframe : frame
---@field bIsFrontPage boolean
---@field titleText fontstring
---@field tabIndex number
---@field OnMouseDown fun(self: df_tabcontainerframe, button: string)
---@field OnMouseUp fun(self: df_tabcontainerframe, button: string)
---@field RefreshOptions fun(self: df_tabcontainerframe)|nil
---@class df_tabcontainerbutton : button
---@field selectedUnderlineGlow texture
---@field textsize number
---@field mainFrame df_tabcontainer
---@field leftSelectionIndicator texture
--create a template for the tab buttons
local tabTemplate = detailsFramework.table.copy({}, detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
tabTemplate.backdropbordercolor = nil
detailsFramework.TabContainerMixin = {
---@param self df_tabcontainer
---@param tabIndex number
---@return df_tabcontainerframe
GetTabFrameByIndex = function(self, tabIndex)
return self.AllFrames[tabIndex]
end,
---@param self df_tabcontainer
---@param name string
---@return df_tabcontainerframe
GetTabFrameByName = function(self, name)
return self.AllFramesByName[name]
end,
---@param self df_tabcontainer
---@param tabIndex number
---@return df_tabcontainerbutton
GetTabButtonByIndex = function(self, tabIndex)
return self.AllButtons[tabIndex]
end,
---@param self df_tabcontainer
---@param name string
---@return df_tabcontainerbutton
GetTabButtonByName = function(self, name)
return self.AllButtonsByName[name]
end,
---@param self df_tabcontainer
---@param backdropTable backdrop|nil
---@param backdropColorTable table|string|nil
---@param backdropBorderColorTable table|string|nil
SetTabFramesBackdrop = function(self, backdropTable, backdropColorTable, backdropBorderColorTable)
for tabIndex, tabFrame in ipairs(self.AllFrames) do
if (backdropTable) then
tabFrame:SetBackdrop(backdropTable)
end
if (backdropColorTable) then
local r, g, b, a = detailsFramework:ParseColors(backdropColorTable)
tabFrame:SetBackdropColor(r, g, b, a)
end
if (backdropBorderColorTable) then
local r, g, b, a = detailsFramework:ParseColors(backdropColorTable)
tabFrame:SetBackdropBorderColor(r, g, b, a)
end
end
end,
---create a underglow texture for the selected tab, this texture is a small yellow bright gradient below the button
---@param self df_tabcontainerbutton
CreateUnderlineGlow = function(self)
local selectedGlow = self:CreateTexture(nil, "background", nil, -4)
selectedGlow:SetPoint("topleft", self["widget"], "bottomleft", -7, 0)
selectedGlow:SetPoint("topright", self["widget"], "bottomright", 7, 0)
selectedGlow:SetTexture([[Interface\BUTTONS\UI-Panel-Button-Glow]])
selectedGlow:SetTexCoord(0, 95/128, 30/64, 38/64)
selectedGlow:SetBlendMode("ADD")
selectedGlow:SetHeight(8)
selectedGlow:SetAlpha(.75)
selectedGlow:Hide()
self.selectedUnderlineGlow = selectedGlow
end,
---@param tabContainer df_tabcontainer
---@param menuIndex number
SelectTabByIndex = function(tabContainer, menuIndex)
---@type df_tabcontainerbutton
local tabButton = tabContainer.AllButtons[menuIndex]
---@type df_tabcontainerframe
local tabFrame = tabContainer.AllFrames[menuIndex]
--hide all tab frame and hide the selection glow from tab buttons
for i = 1, #tabContainer.AllFrames do
---@type df_tabcontainerframe
local thisTabFrame = tabContainer.AllFrames[i]
thisTabFrame:Hide()
---@type df_tabcontainerbutton
local thisTabButton = tabContainer.AllButtons[i]
if (tabContainer.ButtonNotSelectedBorderColor) then
thisTabButton:SetBackdropBorderColor(unpack(tabContainer.ButtonNotSelectedBorderColor))
end
if (thisTabButton.selectedUnderlineGlow) then
thisTabButton.selectedUnderlineGlow:Hide()
end
end
tabFrame:Show()
if (tabFrame.RefreshOptions) then
tabFrame:RefreshOptions()
end
if (tabContainer.ButtonSelectedBorderColor) then
tabButton:SetBackdropBorderColor(unpack(tabContainer.ButtonSelectedBorderColor))
end
if (tabButton.selectedUnderlineGlow) then
tabButton.selectedUnderlineGlow:Show()
end
tabContainer.CurrentIndex = menuIndex
if (tabContainer.hookList.OnSelectIndex) then
detailsFramework:QuickDispatch(tabContainer.hookList.OnSelectIndex, tabContainer, tabButton)
end
end,
---@param tabContainer df_tabcontainer
---@param name string
SelectTabByName = function(tabContainer, name)
---@type df_tabcontainerframe
local tabFrame = tabContainer.AllFramesByName[name]
if (tabFrame) then
local tabIndex = tabFrame.tabIndex
tabContainer:SelectTabByIndex(tabIndex)
else
error("df_tabcontainer:SelectTabByName(name): param #2 'name' not found within 'tabContainer.AllFramesByName'.")
end
end,
---@param self df_tabcontainer
---@param index number
SetIndex = function(self, index)
self.CurrentIndex = index
end,
---@param self df_tabcontainer
OnShow = function(self)
local index = self.CurrentIndex
self:SelectTabByIndex(index)
end
}
detailsFramework.TabContainerFrameMixin = {
---@param self df_tabcontainerframe
---@param button string
OnMouseDown = function(self, button)
--search for UIParent
---@type frame
local highestParent = detailsFramework:FindHighestParent(self)
local tabContainer = self:GetParent()
---@cast tabContainer df_tabcontainer
if (button == "LeftButton") then
if (not highestParent.IsMoving and highestParent:IsMovable()) then
highestParent:StartMoving()
highestParent.IsMoving = true
end
elseif (button == "RightButton") then
if (not highestParent.IsMoving and tabContainer.IsContainer) then
if (self.bIsFrontPage) then
if (tabContainer.CanCloseWithRightClick) then
if (highestParent["CloseFunction"]) then
highestParent["CloseFunction"](highestParent)
else
highestParent:Hide()
end
end
else
--goes back to front page
tabContainer:SelectTabByIndex(1)
end
end
end
end,
---@param self df_tabcontainerframe
---@param button string
OnMouseUp = function(self, button)
local frame = detailsFramework:FindHighestParent(self)
if (frame.IsMoving) then
frame:StopMovingOrSizing()
frame.IsMoving = false
end
end,
}
---creates a frame called tabContainer which is used as base for the tab container object
---the function receives a table called tabList which contains sub tables with two keys 'name' and 'text', name is the frame name and text is the text displayed on the button
---then the function iterate amongst the tabList and create a frame and a button for each entry using the value of the 'text' key as the text for the button and 'name' for the name of the frame
---when the user click on a button, the tabContainer hide all frames and show the frame which was created together with that button
---@param parent frame the parent frame
---@param title string a string to use as the title of the tab container, the title is always shown
---@param frameName string the frame name to pass into the CreateFrame function
---@param tabList df_tabinfotable[] the list of tabs to create, each entry has a 'name' and 'text' keys
---@param optionsTable {button_border_color: table, button_selected_border_color: table, right_click_y: number, hide_click_label: boolean, close_text_alpha: number, rightbutton_always_close: boolean, right_click_interact: boolean, y_offset: number, button_width: number, button_height: number, button_x: number, button_y: number, button_text_size: number, container_width_offset: number}|nil
---@param hookList table<string, function>|nil
---@param languageInfo any
---@return df_tabcontainer
function detailsFramework:CreateTabContainer(parent, title, frameName, tabList, optionsTable, hookList, languageInfo)
optionsTable = optionsTable or {}
local parentFrameWidth = parent:GetWidth()
local yOffset = optionsTable.y_offset or 0
local buttonWidth = optionsTable.button_width or 160
local buttonHeight = optionsTable.button_height or 20
local buttonAnchorX = optionsTable.button_x or 230
local buttonAnchorY = optionsTable.button_y or 0
local buttonTextSize = optionsTable.button_text_size or 10
local containerWidthOffset = optionsTable.container_width_offset or 0
--create the base frame
---@type df_tabcontainer
local tabContainer = CreateFrame("frame", frameName, parent["widget"] or parent, "BackdropTemplate")
tabContainer.hookList = hookList or {}
detailsFramework:Mixin(tabContainer, detailsFramework.TabContainerMixin)
--create the fontstring which show the title
---@type fontstring
local mainTitle = detailsFramework:CreateLabel(tabContainer, title, 24, "white")
mainTitle:SetPoint("topleft", tabContainer, "topleft", 10, -30 + yOffset)
tabContainer.AllFrames = {}
tabContainer.AllButtons = {}
tabContainer.AllFramesByName = {}
tabContainer.AllButtonsByName = {}
tabContainer.CurrentIndex = 1
tabContainer.IsContainer = true
tabContainer.ButtonSelectedBorderColor = optionsTable.button_selected_border_color or {1, 1, 0, 1}
tabContainer.ButtonNotSelectedBorderColor = optionsTable.button_border_color or {0, 0, 0, 0}
if (optionsTable.right_click_interact ~= nil) then
tabContainer.CanCloseWithRightClick = optionsTable.right_click_interact
else
tabContainer.CanCloseWithRightClick = true
end
--languageInfo
local addonId = languageInfo and languageInfo.language_addonId or "none"
for tabIndex, tabInfo in ipairs(tabList) do
--create a frame which will be shown when the tabButton is clicked
--when this tab isn't selected, this frame is hidden
---@type df_tabcontainerframe
local tabFrame = CreateFrame("frame", "$parent" .. tabInfo.name, tabContainer, "BackdropTemplate")
detailsFramework:Mixin(tabFrame, detailsFramework.TabContainerFrameMixin)
tabFrame:SetAllPoints()
tabFrame:SetFrameLevel(210)
tabFrame:SetScript("OnMouseDown", tabFrame.OnMouseDown)
tabFrame:SetScript("OnMouseUp", tabFrame.OnMouseUp)
tabFrame.tabIndex = tabIndex
tabFrame:Hide()
--attempt to get the localized text from the language system using the addonId and the frameInfo.text
local phraseId = tabInfo.text
local bIsLanguagePrahseID = detailsFramework.Language.DoesPhraseIDExistsInDefaultLanguage(addonId, phraseId)
--create the fontstring which show this tab text, this text is only shown when the tab is shown
local titleLabel = detailsFramework:CreateLabel(tabFrame, "", 16, "silver")
if (bIsLanguagePrahseID) then
DetailsFramework.Language.RegisterObjectWithDefault(addonId, titleLabel, tabInfo.text, tabInfo.text)
else
titleLabel:SetText(tabInfo.text)
end
titleLabel:SetPoint("topleft", mainTitle, "bottomleft", 0, 0)
tabFrame.titleText = titleLabel
---@type df_tabcontainerbutton
local tabButton = detailsFramework:CreateButton(tabContainer, function() tabContainer:SelectTabByIndex(tabIndex) end, buttonWidth, buttonHeight, tabInfo.text, tabIndex, nil, nil, nil, "$parentTabButton" .. tabInfo.name, false, tabTemplate)
PixelUtil.SetSize(tabButton, buttonWidth, buttonHeight)
tabButton:SetFrameLevel(220)
tabButton.textsize = buttonTextSize
tabButton.mainFrame = tabContainer
tabContainer.CreateUnderlineGlow(tabButton)
--register the fontstring with the language system
if (bIsLanguagePrahseID) then
DetailsFramework.Language.RegisterObjectWithDefault(addonId, tabButton["widget"], tabInfo.text, tabInfo.text)
end
local rightClickToBack
if (tabIndex == 1 or optionsTable.rightbutton_always_close) then
rightClickToBack = detailsFramework:CreateLabel(tabFrame, "right click to close", 10, "gray")
rightClickToBack:SetPoint("bottomright", tabFrame, "bottomright", -1, optionsTable.right_click_y or 0)
if (optionsTable.close_text_alpha) then
rightClickToBack:SetAlpha(optionsTable.close_text_alpha)
end
tabFrame.bIsFrontPage = true
else
rightClickToBack = detailsFramework:CreateLabel(tabFrame, "right click to go back to main menu", 10, "gray")
rightClickToBack:SetPoint("bottomright", tabFrame, "bottomright", -1, optionsTable.right_click_y or 0)
if (optionsTable.close_text_alpha) then
rightClickToBack:SetAlpha(optionsTable.close_text_alpha)
end
end
if (optionsTable.hide_click_label) then
rightClickToBack:Hide()
end
table.insert(tabContainer.AllFrames, tabFrame)
table.insert(tabContainer.AllButtons, tabButton)
tabContainer.AllFramesByName[tabInfo.name] = tabFrame
tabContainer.AllFramesByName[tabInfo.text] = tabFrame
tabContainer.AllButtonsByName[tabInfo.name] = tabButton
tabContainer.AllButtonsByName[tabInfo.text] = tabButton
end
--order buttons
local x = buttonAnchorX
local y = buttonAnchorY
local spaceBetweenButtons = 3
local allocatedSpaceForButtons = parentFrameWidth - ((#tabList - 2) * spaceBetweenButtons) - buttonAnchorX + containerWidthOffset
local amountButtonsPerRow = math.floor(allocatedSpaceForButtons / buttonWidth)
tabContainer.AllButtons[1]:SetPoint("topleft", mainTitle, "topleft", x, y)
x = x + buttonWidth + 2
for i = 2, #tabContainer.AllButtons do
local button = tabContainer.AllButtons[i]
PixelUtil.SetPoint(button, "topleft", mainTitle, "topleft", x, y)
x = x + buttonWidth + 2
if (i % amountButtonsPerRow == 0) then
x = buttonAnchorX
y = y - buttonHeight - 1
end
end
--when show the frame, reset to the current internal index
tabContainer:SetScript("OnShow", tabContainer.OnShow)
--select the first frame
local defaultTab = 1
tabContainer:SelectTabByIndex(defaultTab)
return tabContainer
end
--[=[example:
local parent = UIParent
local title = "My AddOn Options"
local frameName = "MyAddOnOptionsFrame"
local tabList = {
{name = "GeneralSettings", text = "General Settings"},
{name = "AdvancedSettings", text = "Advanced Settings"},
{name = "AboutTheAddon", text = "Addon Info"},
}
local optionsTable = {}
local hookList = {}
local languageInfo = {language_addonId = "MyAddOnTocName"}
local tabContainer = DetailsFramework:CreateTabContainer(parent, title, frameName, tabList, optionsTable, hookList, languageInfo)
tabContainer:SetPoint("center", UIParent, "center", 0, 0)
tabContainer:SetSize(750, 450)
tabContainer:Show()
--ways for getting a tab frame and start to create widgets inside it
local tabIndex = 1
local generalSettingsTabFrame = tabContainer:GetTabFrameByIndex(tabIndex) --using a tabIndex
local advancedSettingsTabFrame = tabContainer:GetTabFrameByName("Advanced Settings") --using the tab text
local aboutTabFrame = tabContainer:GetTabFrameByName("AboutTheAddon") --using the tab name
--clicking on tab buttons will automatically show the tab frame, to select a tab frame without clicking on the button, use:
tabContainer:SelectTabByIndex(tabIndex) --using a tabIndex
tabContainer:SelectTabByName("Advanced Settings") --using the tab text
tabContainer:SelectTabByName("AdvancedSettings") --using the tab name
--modify the background color by applying a backdrop
local backdropTable = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}
local backdropColor = {DetailsFramework:GetDefaultBackdropColor()}
local backdropBorderColor = {0, 0, 0, 1}
tabContainer:SetTabFramesBackdrop(backdropTable, backdropColor, backdropBorderColor)
--]=]