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.

1547 lines
66 KiB

local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local unpack = unpack
local C_Timer = C_Timer
local InCombatLockdown = InCombatLockdown
local CreateFrame = CreateFrame
local PixelUtil = PixelUtil
local _
---@class df_menu_table : table
---@field text_template table
---@field id string an unique string or number to identify the button, from parent.widgetids[id], parent is the first argument of BuildMenu and BuildMenuVolatile
---@field namePhraseId string the phrase id (from language localization) to use on the button
---@class df_menu_label : df_menu_table
---@field get function
---@field color table
---@field font string
---@field size number
---@field text string
---@class df_menu_dropdown : df_menu_table
---@field type string
---@field set function
---@field get function
---@field values table
---@field name string
---@field desc string
---@field descPhraseId string
---@field hooks table
---@class df_menu_toggle : df_menu_table
---@field set function
---@field get function
---@field name string
---@field desc string
---@field descPhraseId string
---@field hooks table
---@field width number
---@field height number
---@field boxfirst boolean
---@class df_menu_range : df_menu_table
---@field set function
---@field get function
---@field min number
---@field max number
---@field step number
---@field name string
---@field desc string
---@field descPhraseId string
---@field hooks table
---@field thumbscale number
---@field usedecimals boolean if true allow fraction values
---@class df_menu_color : df_menu_table
---@field set function
---@field get function
---@field name string
---@field desc string
---@field descPhraseId string
---@field hooks table
---@field boxfirst boolean
---@class df_menu_button : df_menu_table
---@field func function the function to execute when the button is pressed
---@field param1 any the first parameter to pass to the function
---@field param2 any the second parameter to pass to the function
---@field name string text to show on the button
---@field desc string text to show on the tooltip
---@field descPhraseId string the phrase id (from language localization) to use on the tooltip
---@field hooks table a table with hooks to add to the button
---@field width number
---@field height number
---@field inline boolean
---@field icontexture any
---@field icontexcoords table
---@class df_menu_textentry : df_menu_table
---@field func function the function to execute when enter key is pressed
---@field set function same as above 'func'
---@field get function
---@field name string text to show on the button
---@field desc string text to show on the tooltip
---@field descPhraseId string the phrase id (from language localization) to use on the tooltip
---@field hooks table a table with hooks to add to the button
---@field inline boolean if true, the widget is placed in the rigt side of the previous one
---@field align string "left", "center" or "right"
---@field nocombat boolean can't edit when in combat
---@field spacement boolean gives a little of more space from the next widget
local onEnterHighlight = function(self)
self.highlightTexture:Show()
if (self.parent:GetScript("OnEnter")) then
self.parent:GetScript("OnEnter")(self.parent)
end
end
local onLeaveHighlight = function(self)
self.highlightTexture:Hide()
if (self.parent:GetScript("OnLeave")) then
self.parent:GetScript("OnLeave")(self.parent)
end
end
local createOptionHighlightTexture = function(frame, label, widgetWidth)
frame = frame.widget or frame
label = label.widget or label
local highlightFrame = CreateFrame("frame", nil, frame)
highlightFrame:EnableMouse(true)
highlightFrame:SetFrameLevel(frame:GetFrameLevel()-1)
PixelUtil.SetSize(highlightFrame, widgetWidth, frame:GetHeight() + 1)
PixelUtil.SetPoint(highlightFrame, "topleft", label, "topleft", -2, 5)
highlightFrame:SetScript("OnEnter", onEnterHighlight)
highlightFrame:SetScript("OnLeave", onLeaveHighlight)
local highlightTexture = highlightFrame:CreateTexture(nil, "overlay")
highlightTexture:SetColorTexture(1, 1, 1, 0.1)
PixelUtil.SetPoint(highlightTexture, "topleft", highlightFrame, "topleft", 0, 0)
PixelUtil.SetPoint(highlightTexture, "bottomright", highlightFrame, "bottomright", 0, 0)
highlightTexture:Hide()
local backgroundTexture = highlightFrame:CreateTexture(nil, "artwork")
backgroundTexture:SetColorTexture(1, 1, 1)
backgroundTexture:SetVertexColor(.25, .25, .25, 0.5)
PixelUtil.SetPoint(backgroundTexture, "topleft", highlightFrame, "topleft", 0, 0)
PixelUtil.SetPoint(backgroundTexture, "bottomright", highlightFrame, "bottomright", 0, 0)
highlightFrame.highlightTexture = highlightTexture
highlightFrame.parent = frame
return highlightTexture
end
local formatOptionNameWithColon = function(text, useColon)
if (text) then
if (useColon) then
text = text .. ":"
return text
else
return text
end
end
end
local widgetsToDisableOnCombat = {}
local getMenuWidgetVolative = function(parent, widgetType, indexTable)
local widgetObject
if (widgetType == "label") then
widgetObject = parent.widget_list_by_type[widgetType][indexTable[widgetType]]
if (not widgetObject) then
widgetObject = detailsFramework:CreateLabel(parent, "", 10, "white", "", nil, "$parentWidget" .. widgetType .. indexTable[widgetType], "overlay")
table.insert(parent.widget_list, widgetObject)
table.insert(parent.widget_list_by_type[widgetType], widgetObject)
end
indexTable[widgetType] = indexTable[widgetType] + 1
elseif (widgetType == "dropdown") then
widgetObject = parent.widget_list_by_type[widgetType][indexTable[widgetType]]
if (not widgetObject) then
widgetObject = detailsFramework:CreateDropDown(parent, function() return {} end, nil, 120, 18, nil, "$parentWidget" .. widgetType .. indexTable[widgetType])
widgetObject.hasLabel = detailsFramework:CreateLabel(parent, "", 10, "white", "", nil, "$parentWidget" .. widgetType .. indexTable[widgetType] .. "label", "overlay")
table.insert(parent.widget_list, widgetObject)
table.insert(parent.widget_list_by_type[widgetType], widgetObject)
else
widgetObject:ClearHooks()
widgetObject.hasLabel.text = ""
end
indexTable[widgetType] = indexTable[widgetType] + 1
elseif (widgetType == "switch") then
widgetObject = parent.widget_list_by_type[widgetType][indexTable[widgetType]]
if (not widgetObject) then
widgetObject = detailsFramework:CreateSwitch(parent, nil, true, 20, 20, nil, nil, nil, "$parentWidget" .. widgetType .. indexTable[widgetType])
widgetObject.hasLabel = detailsFramework:CreateLabel(parent, "", 10, "white", "", nil, "$parentWidget" .. widgetType .. indexTable[widgetType] .. "label", "overlay")
table.insert(parent.widget_list, widgetObject)
table.insert(parent.widget_list_by_type[widgetType], widgetObject)
else
widgetObject:ClearHooks()
end
indexTable[widgetType] = indexTable[widgetType] + 1
elseif (widgetType == "slider") then
widgetObject = parent.widget_list_by_type[widgetType][indexTable[widgetType]]
if (not widgetObject) then
widgetObject = detailsFramework:CreateSlider(parent, 120, 20, 1, 2, 1, 1, false, nil, "$parentWidget" .. widgetType .. indexTable[widgetType])
widgetObject.hasLabel = detailsFramework:CreateLabel(parent, "", 10, "white", "", nil, "$parentWidget" .. widgetType .. indexTable[widgetType] .. "label", "overlay")
table.insert(parent.widget_list, widgetObject)
table.insert(parent.widget_list_by_type[widgetType], widgetObject)
else
widgetObject:ClearHooks()
end
indexTable[widgetType] = indexTable[widgetType] + 1
elseif (widgetType == "color") then
widgetObject = parent.widget_list_by_type[widgetType][indexTable[widgetType]]
if (not widgetObject) then
widgetObject = detailsFramework:CreateColorPickButton(parent, "$parentWidget" .. widgetType .. indexTable[widgetType], nil, function()end, 1)
widgetObject.hasLabel = detailsFramework:CreateLabel(parent, "", 10, "white", "", nil, "$parentWidget" .. widgetType .. indexTable[widgetType] .. "label", "overlay")
table.insert(parent.widget_list, widgetObject)
table.insert(parent.widget_list_by_type[widgetType], widgetObject)
else
widgetObject:ClearHooks()
end
indexTable[widgetType] = indexTable[widgetType] + 1
elseif (widgetType == "button") then
widgetObject = parent.widget_list_by_type[widgetType][indexTable[widgetType]]
if (not widgetObject) then
widgetObject = detailsFramework:CreateButton(parent, function()end, 120, 18, "", nil, nil, nil, nil, "$parentWidget" .. widgetType .. indexTable[widgetType])
widgetObject.hasLabel = detailsFramework:CreateLabel(parent, "", 10, "white", "", nil, "$parentWidget" .. widgetType .. indexTable[widgetType] .. "label", "overlay")
table.insert(parent.widget_list, widgetObject)
table.insert(parent.widget_list_by_type[widgetType], widgetObject)
else
widgetObject:ClearHooks()
end
indexTable[widgetType] = indexTable[widgetType] + 1
elseif (widgetType == "textentry") then
widgetObject = parent.widget_list_by_type[widgetType][indexTable[widgetType]]
if (not widgetObject) then
widgetObject = detailsFramework:CreateTextEntry(parent, function()end, 120, 18, nil, "$parentWidget" .. widgetType .. indexTable[widgetType])
widgetObject.hasLabel = detailsFramework:CreateLabel(parent, "", 10, "white", "", nil, "$parentWidget" .. widgetType .. indexTable[widgetType] .. "label", "overlay")
table.insert(parent.widget_list, widgetObject)
table.insert(parent.widget_list_by_type[widgetType], widgetObject)
else
widgetObject:ClearHooks()
end
indexTable[widgetType] = indexTable[widgetType] + 1
end
--if the widget is inside the no combat table, remove it
for i = 1, #widgetsToDisableOnCombat do
if (widgetsToDisableOnCombat[i] == widgetObject) then
table.remove(widgetsToDisableOnCombat, i)
break
end
end
return widgetObject
end
--get the description phrase from the language table or use the .desc or .deschraseid
local getDescPhraseText = function(languageTable, widgetTable)
local descPhraseId = languageTable and (languageTable[widgetTable.descPhraseId] or languageTable[widgetTable.desc])
return descPhraseId or widgetTable.descPhraseId or widgetTable.desc or widgetTable.name or "-?-"
end
local getNamePhraseID = function(widgetTable, languageAddonId, languageTable, bIgnoreEmbed)
if (widgetTable.namePhraseId) then
return widgetTable.namePhraseId
end
if (not languageTable) then
return
end
local keyName = widgetTable.name
if (widgetTable.type == "label" and widgetTable.get) then
local key = widgetTable.get()
if (key and type(key) == "string") then
keyName = key
end
end
--embed key is when the phraseId is inside a string surounded by @
local embedPhraseId = keyName:match("@(.-)@")
local hasValue = detailsFramework.Language.DoesPhraseIDExistsInDefaultLanguage(languageAddonId, embedPhraseId or keyName)
if (not hasValue) then
return
end
if (embedPhraseId and not bIgnoreEmbed) then
return embedPhraseId, true
else
return keyName
end
end
local getNamePhraseText = function(languageTable, widgetTable, useColon, languageAddonId)
local namePhraseId, bWasEmbed = getNamePhraseID(widgetTable, languageAddonId, languageTable)
local namePhrase = languageTable and (languageTable[namePhraseId] or languageTable[widgetTable.namePhraseId] or languageTable[widgetTable.name])
if (bWasEmbed and widgetTable.name) then
namePhrase = widgetTable.name:gsub("@" .. namePhraseId .. "@", namePhrase)
end
return namePhrase or formatOptionNameWithColon(widgetTable.name, useColon) or widgetTable.namePhraseId or widgetTable.name or "-?-"
end
--volatile menu can be called several times, each time all settings are reset and a new menu is built reusing the widgets
function detailsFramework:BuildMenuVolatile(parent, menuOptions, xOffset, yOffset, height, useColon, textTemplate, dropdownTemplate, switchTemplate, switchIsCheckbox, sliderTemplate, buttonTemplate, valueChangeHook)
if (not parent.widget_list) then
detailsFramework:SetAsOptionsPanel(parent)
end
detailsFramework:ClearOptionsPanel(parent)
local currentXOffset = xOffset or 0
local currentYOffset = yOffset or 0
local maxColumnWidth = 0
local latestInlineWidget
local widgetIndexes = {
label = 1,
dropdown = 1,
switch = 1,
slider = 1,
color = 1,
button = 1,
textentry = 1,
}
if (height and type(height) == "number") then
height = math.abs((height or parent:GetHeight()) - math.abs(yOffset) + 20)
height = height * -1
else
height = parent:GetHeight()
end
--normalize format types
for index, widgetTable in ipairs(menuOptions) do
if (widgetTable.type == "space") then
widgetTable.type = "blank"
elseif (widgetTable.type == "fontdropdown") then
widgetTable.type = "selectfont"
elseif (widgetTable.type == "colordropdown") then
widgetTable.type = "selectcolor"
elseif (widgetTable.type == "outlinedropdown") then
widgetTable.type = "selectoutline"
elseif (widgetTable.type == "anchordropdown") then
widgetTable.type = "selectanchor"
elseif (widgetTable.type == "dropdown") then
widgetTable.type = "select"
elseif (widgetTable.type == "switch") then
widgetTable.type = "toggle"
elseif (widgetTable.type == "slider") then
widgetTable.type = "range"
elseif (widgetTable.type == "button") then
widgetTable.type = "execute"
end
end
--catch some options added in the hash part of the menu table
local bUseBoxFirstOnAllWidgets = menuOptions.always_boxfirst
local bAlignAsPairs = menuOptions.align_as_pairs
local nAlignAsPairsLength = menuOptions.align_as_pairs_string_space or 160
local languageAddonId = menuOptions.language_addonId
local widgetWidth = menuOptions.widget_width
local widgetHeight = menuOptions.widget_height
local languageTable
if (languageAddonId) then
languageTable = DetailsFramework.Language.GetLanguageTable(languageAddonId)
end
for index, widgetTable in ipairs(menuOptions) do
if (not widgetTable.hidden) then
local widgetCreated
if (latestInlineWidget) then
if (not widgetTable.inline) then
latestInlineWidget = nil
currentYOffset = currentYOffset - 20
end
end
local extraPaddingY = 0
if (not widgetTable.novolatile) then
--step a line
if (widgetTable.type == "blank" or widgetTable.type == "space") then
--do nothing
elseif (widgetTable.type == "label" or widgetTable.type == "text") then
local label = getMenuWidgetVolative(parent, "label", widgetIndexes)
widgetCreated = label
local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable)
local namePhrase = (languageTable and (languageTable[namePhraseId] or languageTable[widgetTable.namePhraseId] or languageTable[widgetTable.name])) or (widgetTable.get and widgetTable.get()) or widgetTable.text or (widgetTable.namePhraseId) or ""
label.text = namePhrase
label.color = widgetTable.color
if (widgetTable.font) then
label.fontface = widgetTable.font
end
if (widgetTable.text_template or textTemplate) then
label:SetTemplate(widgetTable.text_template or textTemplate)
else
label.fontsize = widgetTable.size or 10
end
label._get = widgetTable.get
label.widget_type = "label"
label:ClearAllPoints()
label:SetPoint(currentXOffset, currentYOffset)
if (widgetTable.id) then
parent.widgetids [widgetTable.id] = label
end
--dropdowns
elseif (widgetTable.type:find("select")) then
assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get() not found in the widget table for 'select'")
local dropdown = getMenuWidgetVolative(parent, "dropdown", widgetIndexes)
widgetCreated = dropdown
if (widgetTable.type == "selectfont") then
local func = detailsFramework:CreateFontListGenerator(widgetTable.set)
dropdown:SetFunction(func)
elseif (widgetTable.type == "selectcolor") then
local func = detailsFramework:CreateColorListGenerator(widgetTable.set)
dropdown:SetFunction(func)
elseif (widgetTable.type == "selectanchor") then
local func = detailsFramework:CreateAnchorPointListGenerator(widgetTable.set)
dropdown:SetFunction(func)
elseif (widgetTable.type == "selectoutline") then
local func = detailsFramework:CreateOutlineListGenerator(widgetTable.set)
dropdown:SetFunction(func)
else
dropdown:SetFunction(widgetTable.values)
end
dropdown:Refresh()
dropdown:Select(widgetTable.get())
dropdown:SetTemplate(dropdownTemplate)
if (widgetWidth) then
dropdown:SetWidth(widgetWidth)
end
if (widgetHeight) then
dropdown:SetHeight(widgetHeight)
end
local descPhrase = getDescPhraseText(languageTable, widgetTable)
dropdown:SetTooltip(descPhrase)
dropdown._get = widgetTable.get
dropdown.widget_type = "select"
local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId)
dropdown.hasLabel.text = namePhrase
dropdown.hasLabel:SetTemplate(widgetTable.text_template or textTemplate)
--as these are reused widgets, clean the previous point
dropdown:ClearAllPoints()
dropdown.hasLabel:ClearAllPoints()
if (bAlignAsPairs) then
dropdown.hasLabel:SetPoint(currentXOffset, currentYOffset)
dropdown:SetPoint("left", dropdown.hasLabel, "left", nAlignAsPairsLength, 0)
else
dropdown:SetPoint("left", dropdown.hasLabel, "right", 2, 0)
dropdown.hasLabel:SetPoint(currentXOffset, currentYOffset)
end
--global callback
if (valueChangeHook) then
dropdown:SetHook("OnOptionSelected", valueChangeHook)
end
--hook list (hook list is wiped when getting the widget)
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
dropdown:SetHook(hookName, hookFunc)
end
end
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = dropdown
end
local widgetTotalSize = dropdown.hasLabel.widget:GetStringWidth() + 140 + 4
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
--switchs
elseif (widgetTable.type == "toggle" or widgetTable.type == "switch") then
local switch = getMenuWidgetVolative(parent, "switch", widgetIndexes)
widgetCreated = switch
switch:SetValue(widgetTable.get())
switch:SetTemplate(switchTemplate)
switch:SetAsCheckBox() --it's always a checkbox on volatile menu
local descPhrase = getDescPhraseText(languageTable, widgetTable)
switch:SetTooltip(descPhrase)
switch._get = widgetTable.get
switch.widget_type = "toggle"
switch.OnSwitch = widgetTable.set
if (valueChangeHook) then
switch:SetHook("OnSwitch", valueChangeHook)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
switch:SetHook(hookName, hookFunc)
end
end
if (widgetTable.width) then
switch:SetWidth(widgetTable.width)
end
if (widgetTable.height) then
switch:SetHeight(widgetTable.height)
end
local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId)
switch.hasLabel.text = namePhrase
switch.hasLabel:SetTemplate(widgetTable.text_template or textTemplate)
switch:ClearAllPoints()
switch.hasLabel:ClearAllPoints()
if (bAlignAsPairs) then
switch.hasLabel:SetPoint(currentXOffset, currentYOffset)
switch:SetPoint("left", switch.hasLabel, "left", nAlignAsPairsLength, 0)
else
if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then
switch:SetPoint(currentXOffset, currentYOffset)
switch.hasLabel:SetPoint("left", switch, "right", 2)
local nextWidgetTable = menuOptions[index+1]
if (nextWidgetTable) then
if (nextWidgetTable.type ~= "blank" and nextWidgetTable.type ~= "breakline" and nextWidgetTable.type ~= "toggle" and nextWidgetTable.type ~= "color") then
extraPaddingY = 4
end
end
else
switch.hasLabel:SetPoint(currentXOffset, currentYOffset)
switch:SetPoint("left", switch.hasLabel, "right", 2)
end
end
if (widgetTable.id) then
parent.widgetids [widgetTable.id] = switch
end
local widgetTotalSize = switch.hasLabel:GetStringWidth() + 32
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
--slider
elseif (widgetTable.type == "range" or widgetTable.type == "slider") then
local slider = getMenuWidgetVolative(parent, "slider", widgetIndexes)
widgetCreated = slider
if (widgetTable.usedecimals) then
slider.slider:SetValueStep(0.01)
else
slider.slider:SetValueStep(widgetTable.step or 1)
end
slider.useDecimals = widgetTable.usedecimals
slider.slider:SetMinMaxValues(widgetTable.min, widgetTable.max)
slider.slider:SetValue(widgetTable.get())
slider.ivalue = slider.slider:GetValue()
slider:SetTemplate(sliderTemplate)
if (widgetWidth) then
slider:SetWidth(widgetWidth)
end
if (widgetHeight) then
slider:SetHeight(widgetHeight)
end
local descPhrase = getDescPhraseText(languageTable, widgetTable)
slider:SetTooltip(descPhrase)
slider._get = widgetTable.get
slider.widget_type = "range"
slider:SetHook("OnValueChange", widgetTable.set)
if (valueChangeHook) then
slider:SetHook("OnValueChange", valueChangeHook)
end
if (widgetTable.thumbscale) then
slider:SetThumbSize (slider.thumb.originalWidth * widgetTable.thumbscale, nil)
else
slider:SetThumbSize (slider.thumb.originalWidth * 1.3, nil)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
slider:SetHook(hookName, hookFunc)
end
end
local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId)
slider.hasLabel.text = namePhrase
slider.hasLabel:SetTemplate(widgetTable.text_template or textTemplate)
slider:ClearAllPoints()
slider.hasLabel:ClearAllPoints()
if (bAlignAsPairs) then
slider.hasLabel:SetPoint(currentXOffset, currentYOffset)
slider:SetPoint("left", slider.hasLabel, "left", nAlignAsPairsLength, 0)
else
slider:SetPoint("left", slider.hasLabel, "right", 2)
slider.hasLabel:SetPoint(currentXOffset, currentYOffset)
end
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = slider
end
local widgetTotalSize = slider.hasLabel:GetStringWidth() + 146
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
--color
elseif (widgetTable.type == "color" or widgetTable.type == "color") then
local colorpick = getMenuWidgetVolative(parent, "color", widgetIndexes)
widgetCreated = colorpick
colorpick.color_callback = widgetTable.set --callback
colorpick:SetTemplate(buttonTemplate)
colorpick:SetSize(18, 18)
local descPhrase = getDescPhraseText(languageTable, widgetTable)
colorpick:SetTooltip(descPhrase)
colorpick._get = widgetTable.get
colorpick.widget_type = "color"
local default_value, g, b, a = widgetTable.get()
if (type(default_value) == "table") then
colorpick:SetColor(unpack(default_value))
else
colorpick:SetColor(default_value, g, b, a)
end
if (valueChangeHook) then
colorpick:SetHook("OnColorChanged", valueChangeHook)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
colorpick:SetHook(hookName, hookFunc)
end
end
local label = colorpick.hasLabel
local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId)
label.text = namePhrase
label:SetTemplate(widgetTable.text_template or textTemplate)
label:ClearAllPoints()
colorpick:ClearAllPoints()
if (bAlignAsPairs) then
label:SetPoint(currentXOffset, currentYOffset)
colorpick:SetPoint("left", label, "left", nAlignAsPairsLength, 0)
else
if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then
label:SetPoint("left", colorpick, "right", 2, 0)
colorpick:SetPoint(currentXOffset, currentYOffset)
extraPaddingY = 1
else
colorpick:SetPoint("left", label, "right", 2, 0)
label:SetPoint(currentXOffset, currentYOffset)
end
end
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = colorpick
end
local widgetTotalSize = label:GetStringWidth() + 32
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
--button
elseif (widgetTable.type == "execute" or widgetTable.type == "button") then
local button = getMenuWidgetVolative(parent, "button", widgetIndexes)
widgetCreated = button
button:SetTemplate(buttonTemplate)
button:SetSize(widgetWidth or widgetTable.width or 120, widgetHeight or widgetTable.height or 18)
button:SetClickFunction(widgetTable.func, widgetTable.param1, widgetTable.param2)
local textTemplate = widgetTable.text_template or textTemplate or detailsFramework.font_templates["ORANGE_FONT_TEMPLATE"]
button.textcolor = textTemplate.color
button.textfont = textTemplate.font
button.textsize = textTemplate.size
local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId)
button.text = namePhrase
button:ClearAllPoints()
if (bAlignAsPairs) then
button:SetPoint(currentXOffset, currentYOffset)
else
if (widgetTable.inline) then
if (latestInlineWidget) then
button:SetPoint("left", latestInlineWidget, "right", 2, 0)
latestInlineWidget = button
else
button:SetPoint(currentXOffset, currentYOffset)
latestInlineWidget = button
end
else
button:SetPoint(currentXOffset, currentYOffset)
end
end
local descPhrase = getDescPhraseText(languageTable, widgetTable)
button:SetTooltip(descPhrase)
button.widget_type = "execute"
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
button:SetHook(hookName, hookFunc)
end
end
if (widgetTable.width) then
button:SetWidth(widgetTable.width)
end
if (widgetTable.height) then
button:SetHeight(widgetTable.height)
end
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = button
end
local widgetTotalSize = button:GetWidth() + 4
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
--textentry
elseif (widgetTable.type == "textentry") then
local textentry = getMenuWidgetVolative(parent, "textentry", widgetIndexes)
widgetCreated = textentry
textentry:SetCommitFunction(widgetTable.func or widgetTable.set)
textentry:SetTemplate(widgetTable.template or widgetTable.button_template or buttonTemplate)
textentry:SetSize(widgetWidth or widgetTable.width or 120, widgetHeight or widgetTable.height or 18)
local descPhrase = getDescPhraseText(languageTable, widgetTable)
textentry:SetTooltip(descPhrase)
textentry.text = widgetTable.get()
textentry._get = widgetTable.get
textentry.widget_type = "textentry"
textentry:SetHook("OnEnterPressed", function(...)
local upFunc = widgetTable.func or widgetTable.set
upFunc(...)
if (valueChangeHook) then
valueChangeHook()
end
end)
textentry:SetHook("OnEditFocusLost", function(...)
local upFunc = widgetTable.func or widgetTable.set
upFunc(...)
if (valueChangeHook) then
valueChangeHook()
end
end)
local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId)
textentry.hasLabel.text = namePhrase
textentry.hasLabel:SetTemplate(widgetTable.text_template or textTemplate)
textentry.hasLabel:ClearAllPoints()
textentry:ClearAllPoints()
if (bAlignAsPairs) then
textentry.hasLabel:SetPoint(currentXOffset, currentYOffset)
textentry:SetPoint("left", textentry.hasLabel, "left", nAlignAsPairsLength, 0)
else
textentry:SetPoint("left", textentry.hasLabel, "right", 2)
textentry.hasLabel:SetPoint(currentXOffset, currentYOffset)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
textentry:SetHook(hookName, hookFunc)
end
end
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = textentry
end
local widgetTotalSize = textentry.hasLabel:GetStringWidth() + 64
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
end --end loop
if (widgetTable.nocombat) then
table.insert(widgetsToDisableOnCombat, widgetCreated)
end
if (not widgetTable.inline) then
if (widgetTable.spacement) then
currentYOffset = currentYOffset - 30
else
currentYOffset = currentYOffset - 20
end
end
if (extraPaddingY > 0) then
currentYOffset = currentYOffset - extraPaddingY
end
if (widgetTable.type == "breakline" or currentYOffset < height) then
currentYOffset = yOffset
currentXOffset = currentXOffset + maxColumnWidth + 20
maxColumnWidth = 0
end
if widgetCreated then
widgetCreated:Show()
end
end
end
end
detailsFramework.RefreshUnsafeOptionsWidgets()
end
local getDescripttionPhraseID = function(widgetTable, languageAddonId, languageTable)
if (widgetTable.descPhraseId) then
return widgetTable.descPhraseId
end
if (not languageTable) then
return
end
local hasValue = detailsFramework.Language.DoesPhraseIDExistsInDefaultLanguage(languageAddonId, widgetTable.desc)
if (not hasValue) then
return
end
return widgetTable.desc
end
---classes used by the menu builder on the menuOptions table on both functions BuildMenu and BuildMenuVolatile
---the menuOptions consists of a table with several tables inside in array, each table is a widget to be created
---class df_menu_label is used when the sub table of menuOptions has a key named "type" with the value "label" or "text"
function detailsFramework:BuildMenu(parent, menuOptions, xOffset, yOffset, height, useColon, textTemplate, dropdownTemplate, switchTemplate, switchIsCheckbox, sliderTemplate, buttonTemplate, valueChangeHook)
--how many widgets has been created on this line loop pass
local amountLineWidgetCreated = 0
local latestInlineWidget
--normalize format types
for index, widgetTable in ipairs(menuOptions) do
if (widgetTable.type == "space") then
widgetTable.type = "blank"
elseif (widgetTable.type == "fontdropdown") then
widgetTable.type = "selectfont"
elseif (widgetTable.type == "colordropdown") then
widgetTable.type = "selectcolor"
elseif (widgetTable.type == "outlinedropdown") then
widgetTable.type = "selectoutline"
elseif (widgetTable.type == "anchordropdown") then
widgetTable.type = "selectanchor"
elseif (widgetTable.type == "dropdown") then
widgetTable.type = "select"
elseif (widgetTable.type == "switch") then
widgetTable.type = "toggle"
elseif (widgetTable.type == "slider") then
widgetTable.type = "range"
elseif (widgetTable.type == "button") then
widgetTable.type = "execute"
end
end
--catch some options added in the hash part of the menu table
local bUseBoxFirstOnAllWidgets = menuOptions.always_boxfirst
local widgetWidth = menuOptions.widget_width --a width to be used on all widgets
local widgetHeight = menuOptions.widget_height --a height to be used on all widgets
local bAlignAsPairs = menuOptions.align_as_pairs
local nAlignAsPairsLength = menuOptions.align_as_pairs_string_space or 160
local nAlignAsPairsSpacing = menuOptions.align_as_pairs_spacing or 20
--if a scrollbox is passed, the height can be ignored
--the scrollBox child will be used as the parent, and the height of the child will be resized to fit the widgets
local bUseScrollFrame = menuOptions.use_scrollframe
local biggestColumnHeight = 0 --used to resize the scrollbox child when a scrollbox is passed
if (not bUseScrollFrame) then
if (height and type(height) == "number") then
height = math.abs((height or parent:GetHeight()) - math.abs(yOffset) + 20)
height = height * -1
else
height = parent:GetHeight()
end
else
local width, height = parent:GetSize()
parent = parent:GetScrollChild()
parent:SetSize(width, height)
end
local languageAddonId = menuOptions.language_addonId
local languageTable
if (languageAddonId) then
languageTable = DetailsFramework.Language.GetLanguageTable(languageAddonId)
end
if (not parent.widget_list) then
detailsFramework:SetAsOptionsPanel(parent)
end
local currentXOffset = xOffset or 0
local currentYOffset = yOffset or 0
local maxColumnWidth = 0 --biggest width of widget + text size on the current column loop pass
local maxWidgetWidth = 0 --biggest widget width on the current column loop pass
local maxWidth = parent:GetWidth() --total width the buildmenu can use - not in use
for index, widgetTable in ipairs(menuOptions) do
if (not widgetTable.hidden) then
local widgetCreated
if (latestInlineWidget) then
if (not widgetTable.inline) then
latestInlineWidget = nil
currentYOffset = currentYOffset - 28
end
end
local extraPaddingY = 0
if (widgetTable.type == "blank") then
--do nothing
elseif (widgetTable.type == "label" or widgetTable.type == "text") then
---@cast widgetTable df_menu_label
local label = detailsFramework:CreateLabel(parent, "", widgetTable.text_template or textTemplate or widgetTable.size, widgetTable.color, widgetTable.font, nil, "$parentWidget" .. index, "overlay")
label._get = widgetTable.get
label.widget_type = "label"
label:SetPoint(currentXOffset, currentYOffset)
local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable)
if (namePhraseId) then
DetailsFramework.Language.RegisterObject(languageAddonId, label.widget, namePhraseId)
label.languageAddonId = languageAddonId
else
local textToSet = (widgetTable.get and widgetTable.get()) or widgetTable.text or ""
label:SetText(textToSet)
end
--store the widget created into the overall table and the widget by type
table.insert(parent.widget_list, label)
table.insert(parent.widget_list_by_type.label, label)
amountLineWidgetCreated = amountLineWidgetCreated + 1
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = label
end
elseif (widgetTable.type:find("select")) then
---@cast widgetTable df_menu_dropdown
assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'select'")
local defaultHeight = 18
local dropdown
if (widgetTable.type == "selectfont") then
dropdown = detailsFramework:CreateFontDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate)
elseif (widgetTable.type == "selectcolor") then
dropdown = detailsFramework:CreateColorDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate)
elseif (widgetTable.type == "selectanchor") then
dropdown = detailsFramework:CreateAnchorPointDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate)
elseif (widgetTable.type == "selectoutline") then
dropdown = detailsFramework:CreateOutlineDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate)
else
dropdown = detailsFramework:NewDropDown(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 140, widgetHeight or defaultHeight, widgetTable.values, widgetTable.get(), dropdownTemplate)
end
local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable)
DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, dropdown, "have_tooltip", descPhraseId, widgetTable.desc)
dropdown._get = widgetTable.get
dropdown.widget_type = "select"
local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12)
local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true)
DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon))
dropdown.addonId = languageAddonId
if (languageAddonId) then
detailsFramework.Language.RegisterCallback(languageAddonId, function(addonId, languageId, ...) dropdown:Select(dropdown:GetValue()) end)
C_Timer.After(0.1, function() dropdown:Select(dropdown:GetValue()) end)
end
if (bAlignAsPairs) then
PixelUtil.SetPoint(label.widget, "topleft", dropdown:GetParent(), "topleft", currentXOffset, currentYOffset)
PixelUtil.SetPoint(dropdown.widget, "left", label.widget, "left", nAlignAsPairsLength, 0)
createOptionHighlightTexture(dropdown, label, (widgetWidth or 140) + nAlignAsPairsLength + 5)
else
dropdown:SetPoint("left", label, "right", 2, 0)
label:SetPoint(currentXOffset, currentYOffset)
end
dropdown.hasLabel = label
--global callback
if (valueChangeHook) then
dropdown:SetHook("OnOptionSelected", valueChangeHook)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
dropdown:SetHook(hookName, hookFunc)
end
end
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = dropdown
end
local widgetTotalSize = label.widget:GetStringWidth() + 144
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
if (dropdown:GetWidth() > maxWidgetWidth) then
maxWidgetWidth = dropdown:GetWidth()
end
--store the widget created into the overall table and the widget by type
table.insert(parent.widget_list, dropdown)
table.insert(parent.widget_list_by_type.dropdown, dropdown)
widgetCreated = dropdown
amountLineWidgetCreated = amountLineWidgetCreated + 1
elseif (widgetTable.type == "toggle") then
---@cast widgetTable df_menu_toggle
local switch = detailsFramework:NewSwitch(parent, nil, "$parentWidget" .. index, nil, 60, 20, nil, nil, widgetTable.get(), nil, nil, nil, nil, switchTemplate)
local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable)
DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, switch, "have_tooltip", descPhraseId, widgetTable.desc)
switch._get = widgetTable.get
switch.widget_type = "toggle"
switch.OnSwitch = widgetTable.set
if (switchIsCheckbox) then
switch:SetAsCheckBox()
end
if (valueChangeHook) then
switch:SetHook("OnSwitch", valueChangeHook)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
switch:SetHook(hookName, hookFunc)
end
end
if (widgetTable.width) then
PixelUtil.SetWidth(switch.widget, widgetTable.width)
end
if (widgetTable.height) then
PixelUtil.SetHeight(switch.widget, widgetTable.height)
end
local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12)
local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true)
DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon))
if (bAlignAsPairs) then
PixelUtil.SetPoint(label.widget, "topleft", switch:GetParent(), "topleft", currentXOffset, currentYOffset)
PixelUtil.SetPoint(switch.widget, "left", label.widget, "left", nAlignAsPairsLength, 0)
createOptionHighlightTexture(switch, label, (widgetWidth or 140) + nAlignAsPairsLength + 5)
else
if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then
switch:SetPoint(currentXOffset, currentYOffset)
label:SetPoint("left", switch, "right", 2)
local nextWidgetTable = menuOptions[index+1]
if (nextWidgetTable) then
if (nextWidgetTable.type ~= "blank" and nextWidgetTable.type ~= "breakline" and nextWidgetTable.type ~= "toggle" and nextWidgetTable.type ~= "color") then
extraPaddingY = 4
end
end
else
label:SetPoint(currentXOffset, currentYOffset)
switch:SetPoint("left", label, "right", 2, 0)
end
end
switch.hasLabel = label
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = switch
end
local widgetTotalSize = label.widget:GetStringWidth() + 32
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
if (switch:GetWidth() > maxWidgetWidth) then
maxWidgetWidth = switch:GetWidth()
end
--store the widget created into the overall table and the widget by type
table.insert(parent.widget_list, switch)
table.insert(parent.widget_list_by_type.switch, switch)
widgetCreated = switch
amountLineWidgetCreated = amountLineWidgetCreated + 1
elseif (widgetTable.type == "range") then
---@cast widgetTable df_menu_range
assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'range'")
local bIsDecimals = widgetTable.usedecimals
local slider = detailsFramework:NewSlider(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 140, widgetHeight or 18, widgetTable.min, widgetTable.max, widgetTable.step, widgetTable.get(), bIsDecimals, nil, nil, sliderTemplate)
local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable)
DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, slider, "have_tooltip", descPhraseId, widgetTable.desc)
slider._get = widgetTable.get
slider.widget_type = "range"
slider:SetHook("OnValueChange", widgetTable.set)
if (widgetTable.thumbscale) then
slider:SetThumbSize(slider.thumb:GetWidth() * widgetTable.thumbscale, nil)
else
slider:SetThumbSize(slider.thumb:GetWidth() * 1.3, nil)
end
if (valueChangeHook) then
slider:SetHook("OnValueChange", valueChangeHook)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
slider:SetHook(hookName, hookFunc)
end
end
local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12)
local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true)
DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon))
if (bAlignAsPairs) then
PixelUtil.SetPoint(label.widget, "topleft", slider:GetParent(), "topleft", currentXOffset, currentYOffset)
PixelUtil.SetPoint(slider.widget, "left", label.widget, "left", nAlignAsPairsLength, 0)
createOptionHighlightTexture(slider, label, (widgetWidth or 140) + nAlignAsPairsLength + 5)
else
slider:SetPoint("left", label, "right", 2)
label:SetPoint(currentXOffset, currentYOffset)
end
slider.hasLabel = label
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = slider
end
local widgetTotalSize = label.widget:GetStringWidth() + 146
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
if (slider:GetWidth() > maxWidgetWidth) then
maxWidgetWidth = slider:GetWidth()
end
--store the widget created into the overall table and the widget by type
table.insert(parent.widget_list, slider)
table.insert(parent.widget_list_by_type.slider, slider)
widgetCreated = slider
amountLineWidgetCreated = amountLineWidgetCreated + 1
elseif (widgetTable.type == "color") then
---@cast widgetTable df_menu_color
assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'color'")
local colorpick = detailsFramework:NewColorPickButton(parent, "$parentWidget" .. index, nil, widgetTable.set, nil, buttonTemplate)
local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable)
DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, colorpick, "have_tooltip", descPhraseId, widgetTable.desc)
colorpick._get = widgetTable.get
colorpick.widget_type = "color"
colorpick:SetSize(18, 18)
local r, g, b, a = detailsFramework:ParseColors(widgetTable.get())
colorpick:SetColor(r, g, b, a)
if (valueChangeHook) then
colorpick:SetHook("OnColorChanged", valueChangeHook)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
colorpick:SetHook(hookName, hookFunc)
end
end
local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12)
local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true)
DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon))
if (bAlignAsPairs) then
label:SetPoint(currentXOffset, currentYOffset)
colorpick:SetPoint("left", label, "left", nAlignAsPairsLength, 0)
createOptionHighlightTexture(colorpick, label, (widgetWidth or 140) + nAlignAsPairsLength + 5)
else
if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then
label:SetPoint("left", colorpick, "right", 2)
colorpick:SetPoint(currentXOffset, currentYOffset)
extraPaddingY = 1
else
colorpick:SetPoint("left", label, "right", 2)
label:SetPoint(currentXOffset, currentYOffset)
end
end
colorpick.hasLabel = label
if (widgetTable.id) then
parent.widgetids[widgetTable.id] = colorpick
end
local widgetTotalSize = label.widget:GetStringWidth() + 32
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
if (colorpick:GetWidth() > maxWidgetWidth) then
maxWidgetWidth = colorpick:GetWidth()
end
--store the widget created into the overall table and the widget by type
table.insert(parent.widget_list, colorpick)
table.insert(parent.widget_list_by_type.color, colorpick)
widgetCreated = colorpick
amountLineWidgetCreated = amountLineWidgetCreated + 1
elseif (widgetTable.type == "execute") then
---@cast widgetTable df_menu_button
local button = detailsFramework:NewButton(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 120, widgetHeight or 18, widgetTable.func, widgetTable.param1, widgetTable.param2, nil, "", nil, buttonTemplate, textTemplate)
local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true)
DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, button.widget, namePhraseId, widgetTable.name)
if (not buttonTemplate) then
button:InstallCustomTexture()
end
if (widgetTable.inline) then
if (latestInlineWidget) then
button:SetPoint("left", latestInlineWidget, "right", 2, 0)
latestInlineWidget = button
else
button:SetPoint(currentXOffset, currentYOffset)
latestInlineWidget = button
end
else
button:SetPoint(currentXOffset, currentYOffset)
end
local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable)
DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, button, "have_tooltip", descPhraseId, widgetTable.desc)
button.widget_type = "execute"
--button icon
if (widgetTable.icontexture) then
button:SetIcon(widgetTable.icontexture, nil, nil, nil, widgetTable.icontexcoords, nil, nil, 2)
end
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
button:SetHook(hookName, hookFunc)
end
end
if (widgetTable.id) then
parent.widgetids [widgetTable.id] = button
end
if (widgetTable.width and not widgetWidth) then
button:SetWidth(widgetTable.width)
end
if (widgetTable.height and not widgetHeight) then
button:SetHeight(widgetTable.height)
end
local widgetTotalSize = button:GetWidth() + 4
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
if (button:GetWidth() > maxWidgetWidth) then
maxWidgetWidth = button:GetWidth()
end
--store the widget created into the overall table and the widget by type
table.insert(parent.widget_list, button)
table.insert(parent.widget_list_by_type.button, button)
widgetCreated = button
amountLineWidgetCreated = amountLineWidgetCreated + 1
elseif (widgetTable.type == "textentry") then
---@cast widgetTable df_menu_textentry
local textentry = detailsFramework:CreateTextEntry(parent, widgetTable.func or widgetTable.set, widgetWidth or 120, widgetHeight or 18, nil, "$parentWidget" .. index, nil, buttonTemplate)
textentry.align = widgetTable.align or "left"
local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable)
DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, textentry, "have_tooltip", descPhraseId, widgetTable.desc)
textentry.text = widgetTable.get()
textentry._get = widgetTable.get
textentry.widget_type = "textentry"
textentry:SetHook("OnEnterPressed", widgetTable.func or widgetTable.set)
textentry:SetHook("OnEditFocusLost", widgetTable.func or widgetTable.set)
local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12)
local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true)
DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon))
if (bAlignAsPairs) then
label:SetPoint(currentXOffset, currentYOffset)
textentry:SetPoint("left", label, "left", nAlignAsPairsLength, 0)
createOptionHighlightTexture(textentry, label, (widgetWidth or 140) + nAlignAsPairsLength + 5)
else
textentry:SetPoint("left", label, "right", 2)
label:SetPoint(currentXOffset, currentYOffset)
end
textentry.hasLabel = label
--hook list
if (widgetTable.hooks) then
for hookName, hookFunc in pairs(widgetTable.hooks) do
textentry:SetHook(hookName, hookFunc)
end
end
if (widgetTable.id) then
parent.widgetids [widgetTable.id] = textentry
end
local widgetTotalSize = label.widget:GetStringWidth() + 64
if (widgetTotalSize > maxColumnWidth) then
maxColumnWidth = widgetTotalSize
end
if (textentry:GetWidth() > maxWidgetWidth) then
maxWidgetWidth = textentry:GetWidth()
end
--store the widget created into the overall table and the widget by type
table.insert(parent.widget_list, textentry)
table.insert(parent.widget_list_by_type.textentry, textentry)
widgetCreated = textentry
amountLineWidgetCreated = amountLineWidgetCreated + 1
end
if (widgetTable.nocombat) then
table.insert(widgetsToDisableOnCombat, widgetCreated)
end
if (not widgetTable.inline) then
if (widgetTable.spacement) then
currentYOffset = currentYOffset - 30
else
currentYOffset = currentYOffset - 20
end
end
if (extraPaddingY > 0) then
currentYOffset = currentYOffset - extraPaddingY
end
if (bUseScrollFrame) then
if (widgetTable.type == "breakline") then
biggestColumnHeight = math.min(currentYOffset, biggestColumnHeight)
currentYOffset = yOffset
if (bAlignAsPairs) then
currentXOffset = currentXOffset + nAlignAsPairsLength + (widgetWidth or maxWidgetWidth) + nAlignAsPairsSpacing
else
currentXOffset = currentXOffset + maxColumnWidth + 20
end
amountLineWidgetCreated = 0
maxColumnWidth = 0
maxWidgetWidth = 0
end
else
if (widgetTable.type == "breakline" or currentYOffset < height) then
currentYOffset = yOffset
currentXOffset = currentXOffset + maxColumnWidth + 20
amountLineWidgetCreated = 0
maxColumnWidth = 0
end
end
end
end
if (bUseScrollFrame) then
parent:SetHeight(biggestColumnHeight * -1)
end
detailsFramework.RefreshUnsafeOptionsWidgets()
end
local lockNotSafeWidgetsForCombat = function()
for _, widget in ipairs(widgetsToDisableOnCombat) do
widget:Disable()
end
end
local unlockNotSafeWidgetsForCombat = function()
for _, widget in ipairs(widgetsToDisableOnCombat) do
widget:Enable()
end
end
function detailsFramework.RefreshUnsafeOptionsWidgets()
if (detailsFramework.PlayerHasCombatFlag) then
lockNotSafeWidgetsForCombat()
else
unlockNotSafeWidgetsForCombat()
end
end
detailsFramework.PlayerHasCombatFlag = false
local ProtectCombatFrame = CreateFrame("frame")
ProtectCombatFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
ProtectCombatFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
ProtectCombatFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
ProtectCombatFrame:SetScript("OnEvent", function(self, event)
if (event == "PLAYER_ENTERING_WORLD") then
if (InCombatLockdown()) then
detailsFramework.PlayerHasCombatFlag = true
else
detailsFramework.PlayerHasCombatFlag = false
end
detailsFramework.RefreshUnsafeOptionsWidgets()
elseif (event == "PLAYER_REGEN_ENABLED") then
detailsFramework.PlayerHasCombatFlag = false
detailsFramework.RefreshUnsafeOptionsWidgets()
elseif (event == "PLAYER_REGEN_DISABLED") then
detailsFramework.PlayerHasCombatFlag = true
detailsFramework.RefreshUnsafeOptionsWidgets()
end
end)
function detailsFramework:CreateInCombatTexture(frame)
if (detailsFramework.debug and not frame) then
error("Details! Framework: CreateInCombatTexture invalid frame on parameter 1.")
end
local inCombatBackgroundTexture = detailsFramework:CreateImage(frame)
inCombatBackgroundTexture:SetColorTexture(.6, 0, 0, .1)
inCombatBackgroundTexture:Hide()
local inCombatLabel = detailsFramework:CreateLabel(frame, "you are in combat", 24, "silver")
inCombatLabel:SetPoint("right", inCombatBackgroundTexture, "right", -10, 0)
inCombatLabel:Hide()
frame:RegisterEvent("PLAYER_REGEN_DISABLED")
frame:RegisterEvent("PLAYER_REGEN_ENABLED")
frame:SetScript("OnEvent", function(self, event)
if (event == "PLAYER_REGEN_DISABLED") then
inCombatBackgroundTexture:Show()
inCombatLabel:Show()
elseif (event == "PLAYER_REGEN_ENABLED") then
inCombatBackgroundTexture:Hide()
inCombatLabel:Hide()
end
end)
return inCombatBackgroundTexture
end