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 : frame
---@field RefreshOptions fun()
---@field widget_list table
---@field widget_list_by_type table
---@field widgetids table
---@field GetWidgetById fun(optionsFrame: df_menu, id: string): table this should return a widget from the widgetids table
---@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
---@field include_default boolean
---@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
detailsFramework.OptionsFrameMixin = {
}
local onWidgetSetInUse = function ( widget , widgetTable )
if ( widgetTable.childrenids ) then
widget.childrenids = widgetTable.childrenids
end
widget.children_follow_enabled = widgetTable.children_follow_enabled
if ( widgetTable.disabled ) then
widget : Disable ( )
else
if ( widget.IsEnabled and not widget : IsEnabled ( ) ) then
widget : Enable ( )
end
end
end
local setWidgetId = function ( parent , widgetTable , widgetObject )
if ( widgetTable.id ) then
parent.widgetids [ widgetTable.id ] = widgetObject
end
widgetTable.widget = widgetObject
end
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
--control the highlight color, if true, use color one, if false, use color two
--color one: .2, .2, .2, 0.5
--color two: .3, .3, .3, 0.5
local bHighlightColorOne = true
---create a button and a texture to highlight the button when the mouse is over it
---the button has the dimentions of the label and the widget
---@param frame frame
---@param label fontstring
---@param widgetWidth number
---@return unknown
local createOptionHighlightFrame = function ( frame , label , widgetWidth )
frame = frame.widget or frame
label = label.widget or label
local highlightFrame = CreateFrame ( " button " , 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 , 0.5 )
backgroundTexture : SetVertexColor ( .25 , .25 , .25 , 0.5 )
if ( bHighlightColorOne ) then
backgroundTexture : SetVertexColor ( .2 , .2 , .2 , 0.5 )
else
backgroundTexture : SetVertexColor ( .25 , .25 , .25 , 0.5 )
end
bHighlightColorOne = not bHighlightColorOne
PixelUtil.SetPoint ( backgroundTexture , " topleft " , highlightFrame , " topleft " , 0 , 0 )
PixelUtil.SetPoint ( backgroundTexture , " bottomright " , highlightFrame , " bottomright " , 0 , 0 )
highlightFrame.highlightTexture = highlightTexture
highlightFrame.parent = frame
return highlightFrame
end
local setLabelProperties = function ( parent , widget , widgetTable , currentXOffset , currentYOffset , template )
widget._get = widgetTable.get
widget.widget_type = " label "
widget : SetPoint ( currentXOffset , currentYOffset )
if ( widgetTable.text_template or template ) then
widget : SetTemplate ( widgetTable.text_template or template )
else
widget.fontsize = widgetTable.size or 10
end
if ( widgetTable.font ) then
widget.fontface = widgetTable.font
end
setWidgetId ( parent , widgetTable , widget )
onWidgetSetInUse ( widget , widgetTable )
end
local setDropdownProperties = function ( parent , widget , widgetTable , currentXOffset , currentYOffset , template , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth )
widget._get = widgetTable.get
widget.widget_type = " select "
widget : Refresh ( )
widget : Select ( widgetTable.get ( ) )
widget : SetTemplate ( template )
if ( widgetWidth ) then
widget : SetWidth ( widgetWidth )
end
if ( widgetHeight ) then
widget : SetHeight ( widgetHeight )
end
setWidgetId ( parent , widgetTable , widget )
local label = widget.hasLabel . widget
widget : ClearAllPoints ( )
label : ClearAllPoints ( )
if ( bAlignAsPairs ) then --regular
PixelUtil.SetPoint ( label , " topleft " , widget : GetParent ( ) , " topleft " , currentXOffset , currentYOffset )
PixelUtil.SetPoint ( widget.widget , " left " , label , " left " , nAlignAsPairsLength , 0 )
if ( not widget.highlightFrame ) then
local highlightFrame = createOptionHighlightFrame ( widget , label , ( widgetWidth or 140 ) + nAlignAsPairsLength + 5 )
widget.highlightFrame = highlightFrame
end
else
widget : SetPoint ( " left " , label , " right " , 2 , 0 )
label : SetPoint ( " topleft " , parent , " topleft " , currentXOffset , currentYOffset )
end
--global callback
if ( valueChangeHook ) then
widget : SetHook ( " OnOptionSelected " , valueChangeHook )
end
--hook list
if ( widgetTable.hooks ) then
for hookName , hookFunc in pairs ( widgetTable.hooks ) do
widget : SetHook ( hookName , hookFunc )
end
end
local widgetTotalSize = label : GetStringWidth ( ) + 144
if ( widgetTotalSize > maxColumnWidth ) then
maxColumnWidth = widgetTotalSize
end
if ( widget : GetWidth ( ) > maxWidgetWidth ) then
maxWidgetWidth = widget : GetWidth ( )
end
onWidgetSetInUse ( widget , widgetTable )
return maxColumnWidth , maxWidgetWidth
end
local highlightFrameOnClickToggle = function ( highlightFrame , mouseButton )
local parent = highlightFrame : GetParent ( )
local widget = parent.MyObject
local bNewState = not widget._get ( )
widget.OnSwitch ( widget , nil , bNewState ) --widget.OnSwitch = widgetTable.set
if ( bNewState ) then
widget : SetValue ( true )
else
widget : SetValue ( false )
end
if ( widget._valueChangeHook ) then
widget._valueChangeHook ( )
end
end
local setToggleProperties = function ( parent , widget , widgetTable , currentXOffset , currentYOffset , template , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , switchIsCheckbox , bUseBoxFirstOnAllWidgets , menuOptions , index , maxWidgetWidth )
widget._get = widgetTable.get
widget._set = widgetTable.set
widget.widget_type = " toggle "
widget.OnSwitch = widgetTable.set
if ( switchIsCheckbox ) then
widget : SetAsCheckBox ( )
end
if ( widgetTable.children_follow_enabled ) then
widget.SetValueOriginal = widget.SetValue --perhaps widgetTable.set() --perhaps setscrip OnClick
widget._name = widgetTable.name
local newSetFunc = function ( thisWidget , value )
--look for children ids
local childrenids = widgetTable.childrenids
--print(childrenids, type(childrenids))
if ( type ( childrenids ) == " table " ) then
for i , childId in ipairs ( childrenids ) do
local childWidget = parent : GetWidgetById ( childId )
--print("childWidget", childWidget)
if ( childWidget ) then
--if the children_follow_reverse is true, then the children will be enabled when the toogle is disabeld
--this is used when the main toggle is a kind of "Do This Automatically", if is not doing it automatically
--then the children should be enabled to set the options
if ( widgetTable.children_follow_reverse ) then
if ( value ) then
childWidget : Disable ( )
else
childWidget : Enable ( )
end
else
if ( value ) then
childWidget : Enable ( )
else
childWidget : Disable ( )
end
end
end
end
end
thisWidget.SetValueOriginal ( thisWidget , value )
return value
end
widget : SetValue ( widgetTable.get ( ) )
rawset ( widget , " SetValue " , newSetFunc )
else
if ( widget.SetValueOriginal ) then
rawset ( widget , " SetValue " , widget.SetValueOriginal )
rawset ( widget , " SetValueOriginal " , nil )
end
widget : SetValue ( widgetTable.get ( ) )
end
if ( widgetWidth ) then
PixelUtil.SetWidth ( widget.widget , widgetWidth )
end
if ( widgetHeight ) then
PixelUtil.SetHeight ( widget.widget , widgetHeight )
end
widget : SetTemplate ( template )
setWidgetId ( parent , widgetTable , widget )
local label = widget.hasLabel . widget
widget : ClearAllPoints ( )
label : ClearAllPoints ( )
local extraPaddingY = 0
if ( bAlignAsPairs ) then
if ( not widget.highlightFrame ) then
local highlightFrame = createOptionHighlightFrame ( widget , label , ( widgetWidth or 140 ) + nAlignAsPairsLength + 5 )
widget.highlightFrame = highlightFrame
end
widget._valueChangeHook = valueChangeHook
widget.highlightFrame : SetScript ( " OnClick " , highlightFrameOnClickToggle )
PixelUtil.SetPoint ( label , " topleft " , widget : GetParent ( ) , " topleft " , currentXOffset , currentYOffset )
PixelUtil.SetPoint ( widget.widget , " right " , widget.highlightFrame , " right " , - 3 , 0 )
else
if ( widgetTable.boxfirst or bUseBoxFirstOnAllWidgets ) then
label : SetPoint ( " left " , widget.widget or widget , " right " , 2 , 0 )
widget : SetPoint ( " topleft " , parent , " topleft " , currentXOffset , currentYOffset )
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
widget : SetPoint ( " left " , label , " right " , 2 , 0 )
label : SetPoint ( " topleft " , parent , " topleft " , currentXOffset , currentYOffset )
end
end
--global callback
if ( valueChangeHook ) then
widget : SetHook ( " OnSwitch " , valueChangeHook )
end
--hook list
if ( widgetTable.hooks ) then
for hookName , hookFunc in pairs ( widgetTable.hooks ) do
widget : SetHook ( hookName , hookFunc )
end
end
local widgetTotalSize = label : GetStringWidth ( ) + 32
if ( widgetTotalSize > maxColumnWidth ) then
maxColumnWidth = widgetTotalSize
end
if ( widget : GetWidth ( ) > maxWidgetWidth ) then
maxWidgetWidth = widget : GetWidth ( )
end
onWidgetSetInUse ( widget , widgetTable )
return maxColumnWidth , maxWidgetWidth , extraPaddingY
end
local setRangeProperties = function ( parent , widget , widgetTable , currentXOffset , currentYOffset , template , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , bIsDecimals , bAttachSliderButtonsToLeft )
widget._get = widgetTable.get
widget.widget_type = " range "
widget : SetTemplate ( template )
widget.bAttachButtonsToLeft = bAttachSliderButtonsToLeft
local currentValue = widgetTable.get ( )
if ( bIsDecimals ) then
widget.slider : SetValueStep ( 0.01 )
else
widget.slider : SetValueStep ( widgetTable.step or 1 )
currentValue = math.floor ( currentValue )
end
widget.useDecimals = bIsDecimals
widget.slider : SetMinMaxValues ( widgetTable.min , widgetTable.max )
widget.slider : SetValue ( currentValue or 0 )
widget.ivalue = widget.slider : GetValue ( )
if ( widgetWidth ) then
widget : SetWidth ( widgetWidth )
end
if ( widgetHeight ) then
widget : SetHeight ( widgetHeight )
end
widget : SetHook ( " OnValueChange " , widgetTable.set )
if ( valueChangeHook ) then
widget : SetHook ( " OnValueChange " , valueChangeHook )
end
if ( widgetTable.thumbscale ) then
widget : SetThumbSize ( widget.thumb . originalWidth * widgetTable.thumbscale , nil )
else
widget : SetThumbSize ( widget.thumb . originalWidth * 1.3 , nil )
end
--hook list
if ( widgetTable.hooks ) then
for hookName , hookFunc in pairs ( widgetTable.hooks ) do
widget : SetHook ( hookName , hookFunc )
end
end
setWidgetId ( parent , widgetTable , widget )
local label = widget.hasLabel . widget
widget : ClearAllPoints ( )
label : ClearAllPoints ( )
if ( bAlignAsPairs ) then
PixelUtil.SetPoint ( label , " topleft " , widget : GetParent ( ) , " topleft " , currentXOffset , currentYOffset )
PixelUtil.SetPoint ( widget.widget , " left " , label , " left " , nAlignAsPairsLength , 0 )
if ( not widget.highlightFrame ) then
local highlightFrame = createOptionHighlightFrame ( widget , label , ( widgetWidth or 140 ) + nAlignAsPairsLength + 5 )
widget.highlightFrame = highlightFrame
end
widget.bAttachButtonsToLeft = true
else
widget : SetPoint ( " left " , label , " right " , 2 , 0 )
label : SetPoint ( " topleft " , parent , " topleft " , currentXOffset , currentYOffset )
end
local widgetTotalSize = label : GetStringWidth ( ) + 146
if ( widgetTotalSize > maxColumnWidth ) then
maxColumnWidth = widgetTotalSize
end
if ( widget : GetWidth ( ) > maxWidgetWidth ) then
maxWidgetWidth = widget : GetWidth ( )
end
onWidgetSetInUse ( widget , widgetTable )
return maxColumnWidth , maxWidgetWidth
end
local setColorProperties = function ( parent , widget , widgetTable , currentXOffset , currentYOffset , template , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , bUseBoxFirstOnAllWidgets , extraPaddingY )
widget._get = widgetTable.get
widget.widget_type = " color "
local r , g , b , a = detailsFramework : ParseColors ( widgetTable.get ( ) )
widget : SetColor ( r , g , b , a )
widget.color_callback = widgetTable.set --callback
--[=[
if ( widgetWidth ) then
widget : SetWidth ( widgetWidth )
else
widget : SetWidth ( 18 )
end
if ( widgetHeight ) then
widget : SetHeight ( widgetHeight )
else
widget : SetHeight ( 18 )
end
--]=]
widget : SetTemplate ( template )
widget : SetWidth ( 18 )
widget : SetHeight ( 18 )
widget : SetHook ( " OnColorChanged " , widgetTable.set )
if ( valueChangeHook ) then
widget : SetHook ( " OnColorChanged " , valueChangeHook )
end
--hook list
if ( widgetTable.hooks ) then
for hookName , hookFunc in pairs ( widgetTable.hooks ) do
widget : SetHook ( hookName , hookFunc )
end
end
setWidgetId ( parent , widgetTable , widget )
local label = widget.hasLabel . widget
widget : ClearAllPoints ( )
label : ClearAllPoints ( )
if ( bAlignAsPairs ) then
if ( not widget.highlightFrame ) then
local highlightFrame = createOptionHighlightFrame ( widget , label , ( widgetWidth or 140 ) + nAlignAsPairsLength + 5 )
widget.highlightFrame = highlightFrame
end
----
widget._valueChangeHook = valueChangeHook
--widget.highlightFrame:SetScript("OnClick", highlightFrameOnClickToggle) --todo make this function for color picker color pick start
PixelUtil.SetPoint ( label , " topleft " , widget : GetParent ( ) , " topleft " , currentXOffset , currentYOffset )
PixelUtil.SetPoint ( widget.widget , " right " , widget.highlightFrame , " right " , - 3 , 0 )
else
if ( widgetTable.boxfirst or bUseBoxFirstOnAllWidgets ) then
label : SetPoint ( " left " , widget.widget , " right " , 2 , 0 )
widget : SetPoint ( currentXOffset , currentYOffset )
extraPaddingY = 1
else
widget : SetPoint ( " left " , label , " right " , 2 , 0 )
label : SetPoint ( " topleft " , parent , " topleft " , currentXOffset , currentYOffset )
end
end
local widgetTotalSize = label : GetStringWidth ( ) + 32
if ( widgetTotalSize > maxColumnWidth ) then
maxColumnWidth = widgetTotalSize
end
if ( widget : GetWidth ( ) > maxWidgetWidth ) then
maxWidgetWidth = widget : GetWidth ( )
end
onWidgetSetInUse ( widget , widgetTable )
return maxColumnWidth , maxWidgetWidth , extraPaddingY
end
local setExecuteProperties = function ( parent , widget , widgetTable , currentXOffset , currentYOffset , template , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , textTemplate , latestInlineWidget )
widget._get = widgetTable.get
widget.widget_type = " execute "
widget : SetTemplate ( template )
widget : SetWidth ( widgetWidth or widgetTable.width or 120 , widgetHeight or widgetTable.height or 18 )
widget : SetClickFunction ( widgetTable.func , widgetTable.param1 , widgetTable.param2 )
--button icon
if ( widgetTable.icontexture ) then
widget : SetIcon ( widgetTable.icontexture , nil , nil , nil , widgetTable.icontexcoords , nil , nil , 2 )
end
textTemplate = widgetTable.text_template or textTemplate or detailsFramework.font_templates [ " ORANGE_FONT_TEMPLATE " ]
widget.textcolor = textTemplate.color
widget.textfont = textTemplate.font
widget.textsize = textTemplate.size
--hook list
if ( widgetTable.hooks ) then
for hookName , hookFunc in pairs ( widgetTable.hooks ) do
widget : SetHook ( hookName , hookFunc )
end
end
setWidgetId ( parent , widgetTable , widget )
local label = widget.hasLabel . widget
widget : ClearAllPoints ( )
label : ClearAllPoints ( )
if ( bAlignAsPairs ) then
PixelUtil.SetPoint ( label , " topleft " , widget : GetParent ( ) , " topleft " , currentXOffset , currentYOffset )
PixelUtil.SetPoint ( widget.widget , " left " , label , " left " , nAlignAsPairsLength , 0 )
if ( not widget.highlightFrame ) then
local highlightFrame = createOptionHighlightFrame ( widget , label , ( widgetWidth or 140 ) + nAlignAsPairsLength + 5 )
widget.highlightFrame = highlightFrame
end
else
if ( widgetTable.inline ) then
if ( latestInlineWidget ) then
widget : SetPoint ( " left " , latestInlineWidget , " right " , 2 , 0 )
latestInlineWidget = widget
else
widget : SetPoint ( currentXOffset , currentYOffset )
latestInlineWidget = widget
end
else
widget : SetPoint ( currentXOffset , currentYOffset )
end
end
local widgetTotalSize = widget : GetWidth ( ) + 4
if ( widgetTotalSize > maxColumnWidth ) then
maxColumnWidth = widgetTotalSize
end
if ( widget : GetWidth ( ) > maxWidgetWidth ) then
maxWidgetWidth = widget : GetWidth ( )
end
onWidgetSetInUse ( widget , widgetTable )
return maxColumnWidth , maxWidgetWidth , latestInlineWidget
end
local setTextEntryProperties = function ( parent , widget , widgetTable , currentXOffset , currentYOffset , template , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , textTemplate , latestInlineWidget )
widget._get = widgetTable.get
widget.text = widgetTable.get ( )
widget.widget_type = " textentry "
widget : SetTemplate ( widgetTable.template or widgetTable.button_template or template )
widget : SetWidth ( widgetWidth or widgetTable.width or 120 , widgetHeight or widgetTable.height or 18 )
widget : SetCommitFunction ( widgetTable.func or widgetTable.set )
widget : SetHook ( " OnEnterPressed " , function ( ... )
local upFunc = widgetTable.func or widgetTable.set
upFunc ( ... )
if ( valueChangeHook ) then
valueChangeHook ( )
end
end )
widget : SetHook ( " OnEditFocusLost " , function ( ... )
local upFunc = widgetTable.func or widgetTable.set
upFunc ( ... )
if ( valueChangeHook ) then
valueChangeHook ( )
end
end )
textTemplate = widgetTable.text_template or textTemplate or detailsFramework.font_templates [ " ORANGE_FONT_TEMPLATE " ]
widget.textcolor = textTemplate.color
widget.textfont = textTemplate.font
widget.textsize = textTemplate.size
--hook list
if ( widgetTable.hooks ) then
for hookName , hookFunc in pairs ( widgetTable.hooks ) do
widget : SetHook ( hookName , hookFunc )
end
end
setWidgetId ( parent , widgetTable , widget )
local label = widget.hasLabel . widget
widget : ClearAllPoints ( )
label : ClearAllPoints ( )
if ( bAlignAsPairs ) then
PixelUtil.SetPoint ( label , " topleft " , widget : GetParent ( ) , " topleft " , currentXOffset , currentYOffset )
PixelUtil.SetPoint ( widget.widget , " left " , label , " left " , nAlignAsPairsLength , 0 )
if ( not widget.highlightFrame ) then
local highlightFrame = createOptionHighlightFrame ( widget , label , ( widgetWidth or 140 ) + nAlignAsPairsLength + 5 )
widget.highlightFrame = highlightFrame
end
else
widget : SetPoint ( " left " , label , " right " , 2 , 0 )
label : SetPoint ( " topleft " , parent , " topleft " , currentXOffset , currentYOffset )
end
local widgetTotalSize = label : GetStringWidth ( ) + 64 --need review, might not be correct
if ( widgetTotalSize > maxColumnWidth ) then
maxColumnWidth = widgetTotalSize
end
if ( widget : GetWidth ( ) > maxWidgetWidth ) then
maxWidgetWidth = widget : GetWidth ( )
end
onWidgetSetInUse ( widget , widgetTable )
return maxColumnWidth , maxWidgetWidth
end
local onMenuBuilt = function ( parent )
--refresh the options to find children to disable or enable
if ( parent.build_menu_options ) then
for index , widgetTable in ipairs ( parent.build_menu_options ) do
if ( widgetTable.children_follow_enabled ) then --not found, bug
local widget = widgetTable.widget
local childrenids = widgetTable.childrenids
if ( type ( childrenids ) == " table " ) then
for i , childId in ipairs ( childrenids ) do
local childWidget = parent : GetWidgetById ( childId )
if ( childWidget ) then
local value = widget : GetValue ( )
if ( widgetTable.children_follow_reverse ) then
if ( value ) then
childWidget : Disable ( )
else
childWidget : Enable ( )
end
else
if ( value ) then
childWidget : Enable ( )
else
childWidget : Disable ( )
end
end
end
end
end
end
end
end
end
local refreshOptions = function ( self )
for _ , widget in ipairs ( self.widget_list ) do
if ( widget._get ) then
if ( widget.widget_type == " label " ) then
if ( widget._get ( ) and not widget.languageAddonId ) then
widget : SetText ( widget._get ( ) )
end
elseif ( widget.widget_type == " select " ) then
widget : Select ( widget._get ( ) )
elseif ( widget.widget_type == " toggle " or widget.widget_type == " range " ) then
widget : SetValue ( widget._get ( ) )
elseif ( widget.widget_type == " textentry " ) then
widget : SetText ( widget._get ( ) )
elseif ( widget.widget_type == " color " ) then
local default_value , g , b , a = widget._get ( )
if ( type ( default_value ) == " table " ) then
widget : SetColor ( unpack ( default_value ) )
else
widget : SetColor ( default_value , g , b , a )
end
end
end
end
onMenuBuilt ( self )
end
detailsFramework.internalFunctions . RefreshOptionsPanel = refreshOptions
local parseOptionsTypes = function ( menuOptions )
--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 == " audiodropdown " ) then
widgetTable.type = " selectaudio "
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
end
local parseOptionsTable = function ( menuOptions )
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
local bAttachSliderButtonsToLeft = menuOptions.slider_buttons_to_left
--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 languageAddonId = menuOptions.language_addonId
return bUseBoxFirstOnAllWidgets , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , nAlignAsPairsSpacing , bUseScrollFrame , languageAddonId , bAttachSliderButtonsToLeft
end
local parseParent = function ( bUseScrollFrame , parent , height , yOffset )
if ( bUseScrollFrame ) then
local width , height = parent : GetSize ( )
parent = parent : GetScrollChild ( )
parent : SetSize ( width , height )
else
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
end
return parent , height
end
local parseLanguageTable = function ( languageAddonId )
local languageTable
if ( languageAddonId ) then
languageTable = DetailsFramework.Language . GetLanguageTable ( languageAddonId )
end
return languageTable
end
local getFrameById = function ( self , id )
return self.widgetids [ id ]
end
function detailsFramework : ClearOptionsPanel ( frame )
for i = 1 , # frame.widget_list do
frame.widget_list [ i ] : Hide ( )
if ( frame.widget_list [ i ] . hasLabel ) then
frame.widget_list [ i ] . hasLabel : SetText ( " " )
end
end
table.wipe ( frame.widgetids )
end
function detailsFramework : SetAsOptionsPanel ( frame )
--print("refresh_options", refresh_options)
frame.RefreshOptions = refreshOptions
frame.widget_list = { }
frame.widget_list_by_type = {
[ " dropdown " ] = { } , -- "select"
[ " switch " ] = { } , -- "toggle"
[ " slider " ] = { } , -- "range"
[ " color " ] = { } , --
[ " button " ] = { } , -- "execute"
[ " textentry " ] = { } , --
[ " label " ] = { } , --"text"
}
frame.widgetids = { }
frame.GetWidgetById = getFrameById
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
--clean children ids, children ids are used to disable or enable other widgets when a widget is disabled or enabled
if ( widgetObject.childrenids ) then
table.wipe ( widgetObject.childrenids )
end
widgetObject.children_follow_enabled = nil
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 )
bHighlightColorOne = true
local amountLineWidgetAdded = 0
local biggestColumnHeight = 0 --used to resize the scrollbox child when a scrollbox is passed
local latestInlineWidget
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
--which is the next widget to get from the pool
local widgetIndexes = {
label = 1 ,
dropdown = 1 ,
switch = 1 ,
slider = 1 ,
color = 1 ,
button = 1 ,
textentry = 1 ,
}
parseOptionsTypes ( menuOptions )
local bUseBoxFirstOnAllWidgets , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , nAlignAsPairsSpacing , bUseScrollFrame , languageAddonId , bAttachSliderButtonsToLeft = parseOptionsTable ( menuOptions )
parent , height = parseParent ( bUseScrollFrame , parent , height , yOffset )
local languageTable = parseLanguageTable ( languageAddonId )
parent.build_menu_options = menuOptions
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 )
label : ClearAllPoints ( )
widgetCreated = label
setLabelProperties ( parent , label , widgetTable , currentXOffset , currentYOffset , textTemplate )
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
amountLineWidgetAdded = amountLineWidgetAdded + 1
--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
local defaultHeight = 18
do
if ( widgetTable.type == " selectfont " ) then
local func = detailsFramework : CreateFontListGenerator ( widgetTable.set , widgetTable.include_default )
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 )
elseif ( widgetTable.type == " selectaudio " ) then
local func = detailsFramework : CreateAudioListGenerator ( widgetTable.set )
dropdown : SetFunction ( func )
else
dropdown : SetFunction ( widgetTable.values )
end
end
local descPhrase = getDescPhraseText ( languageTable , widgetTable )
dropdown : SetTooltip ( descPhrase )
local namePhrase = getNamePhraseText ( languageTable , widgetTable , useColon , languageAddonId )
dropdown.hasLabel . text = namePhrase
dropdown.hasLabel : SetTemplate ( widgetTable.text_template or textTemplate )
maxColumnWidth , maxWidgetWidth = setDropdownProperties ( parent , dropdown , widgetTable , currentXOffset , currentYOffset , textTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth )
amountLineWidgetAdded = amountLineWidgetAdded + 1
--switchs
elseif ( widgetTable.type == " toggle " or widgetTable.type == " switch " ) then
local switch = getMenuWidgetVolative ( parent , " switch " , widgetIndexes )
widgetCreated = switch
local descPhrase = getDescPhraseText ( languageTable , widgetTable )
switch : SetTooltip ( descPhrase )
local namePhrase = getNamePhraseText ( languageTable , widgetTable , useColon , languageAddonId )
switch.hasLabel . text = namePhrase
switch.hasLabel : SetTemplate ( widgetTable.text_template or textTemplate )
maxColumnWidth , maxWidgetWidth , extraPaddingY = setToggleProperties ( parent , switch , widgetTable , currentXOffset , currentYOffset , switchTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , true , bUseBoxFirstOnAllWidgets , menuOptions , index , maxWidgetWidth )
amountLineWidgetAdded = amountLineWidgetAdded + 1
--slider
elseif ( widgetTable.type == " range " ) then
local slider = getMenuWidgetVolative ( parent , " slider " , widgetIndexes )
widgetCreated = slider
local descPhrase = getDescPhraseText ( languageTable , widgetTable )
slider : SetTooltip ( descPhrase )
local namePhrase = getNamePhraseText ( languageTable , widgetTable , useColon , languageAddonId )
slider.hasLabel . text = namePhrase
slider.hasLabel : SetTemplate ( widgetTable.text_template or textTemplate )
maxColumnWidth , maxWidgetWidth = setRangeProperties ( parent , slider , widgetTable , currentXOffset , currentYOffset , sliderTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , widgetTable.usedecimals , bAttachSliderButtonsToLeft )
amountLineWidgetAdded = amountLineWidgetAdded + 1
--color
elseif ( widgetTable.type == " color " ) then
local colorpick = getMenuWidgetVolative ( parent , " color " , widgetIndexes )
widgetCreated = colorpick
local descPhrase = getDescPhraseText ( languageTable , widgetTable )
colorpick : SetTooltip ( descPhrase )
local label = colorpick.hasLabel
local namePhrase = getNamePhraseText ( languageTable , widgetTable , useColon , languageAddonId )
label.text = namePhrase
label : SetTemplate ( widgetTable.text_template or textTemplate )
maxColumnWidth , maxWidgetWidth , extraPaddingY = setColorProperties ( parent , colorpick , widgetTable , currentXOffset , currentYOffset , switchTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , bUseBoxFirstOnAllWidgets , extraPaddingY )
amountLineWidgetAdded = amountLineWidgetAdded + 1
--button
elseif ( widgetTable.type == " execute " or widgetTable.type == " button " ) then
local button = getMenuWidgetVolative ( parent , " button " , widgetIndexes )
button.widget_type = " execute "
widgetCreated = button
maxColumnWidth , maxWidgetWidth , latestInlineWidget = setExecuteProperties ( parent , button , widgetTable , currentXOffset , currentYOffset , buttonTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , textTemplate , latestInlineWidget )
local namePhrase = getNamePhraseText ( languageTable , widgetTable , useColon , languageAddonId )
button.text = namePhrase
local descPhrase = getDescPhraseText ( languageTable , widgetTable )
button : SetTooltip ( descPhrase )
amountLineWidgetAdded = amountLineWidgetAdded + 1
--textentry
elseif ( widgetTable.type == " textentry " ) then
local textentry = getMenuWidgetVolative ( parent , " textentry " , widgetIndexes )
widgetCreated = textentry
local descPhrase = getDescPhraseText ( languageTable , widgetTable )
textentry : SetTooltip ( descPhrase )
local namePhrase = getNamePhraseText ( languageTable , widgetTable , useColon , languageAddonId )
textentry.hasLabel . text = namePhrase
textentry.hasLabel : SetTemplate ( widgetTable.text_template or textTemplate )
maxColumnWidth , maxWidgetWidth = setTextEntryProperties ( parent , textentry , widgetTable , currentXOffset , currentYOffset , buttonTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , textTemplate )
amountLineWidgetAdded = amountLineWidgetAdded + 1
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 ( 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
amountLineWidgetAdded = 0
maxColumnWidth = 0
maxWidgetWidth = 0
end
else
if ( widgetTable.type == " breakline " or currentYOffset < height ) then
currentYOffset = yOffset
currentXOffset = currentXOffset + maxColumnWidth + 20
amountLineWidgetAdded = 0
maxColumnWidth = 0
end
end
if widgetCreated then
widgetCreated : Show ( )
end
end
end
end
detailsFramework.RefreshUnsafeOptionsWidgets ( )
onMenuBuilt ( parent )
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 )
local tNow = debugprofilestop ( )
detailsFramework : BuildMenu22 ( parent , menuOptions , xOffset , yOffset , height , useColon , textTemplate , dropdownTemplate , switchTemplate , switchIsCheckbox , sliderTemplate , buttonTemplate , valueChangeHook )
local tEnd = debugprofilestop ( )
print ( " BuildMenu for " , ( menuOptions.Name or " -- " ) , floor ( tEnd - tNow ) , " ms " )
end
--]=]
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 amountLineWidgetAdded = 0
local biggestColumnHeight = 0 --used to resize the scrollbox child when a scrollbox is passed
local latestInlineWidget
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
bHighlightColorOne = true
--parse settings and the options table
parseOptionsTypes ( menuOptions )
local bUseBoxFirstOnAllWidgets , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , nAlignAsPairsSpacing , bUseScrollFrame , languageAddonId , bAttachSliderButtonsToLeft = parseOptionsTable ( menuOptions )
parent , height = parseParent ( bUseScrollFrame , parent , height , yOffset )
local languageTable = parseLanguageTable ( languageAddonId )
parent.build_menu_options = menuOptions
if ( not parent.widget_list ) then
detailsFramework : SetAsOptionsPanel ( parent )
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 - 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 " )
setLabelProperties ( parent , label , widgetTable , 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 )
amountLineWidgetAdded = amountLineWidgetAdded + 1
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
do
if ( widgetTable.type == " selectfont " ) then
dropdown = detailsFramework : CreateFontDropDown ( parent , widgetTable.set , widgetTable.get ( ) , widgetWidth or 140 , widgetHeight or defaultHeight , nil , " $parentWidget " .. index , dropdownTemplate , widgetTable.include_default )
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 )
elseif ( widgetTable.type == " selectaudio " ) then
dropdown = detailsFramework : CreateAudioDropDown ( 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
end
local descPhraseId = getDescripttionPhraseID ( widgetTable , languageAddonId , languageTable )
DetailsFramework.Language . RegisterTableKeyWithDefault ( languageAddonId , dropdown , " have_tooltip " , descPhraseId , widgetTable.desc )
local label = detailsFramework : NewLabel ( parent , nil , " $parentLabel " .. index , nil , " " , " GameFontNormal " , widgetTable.text_template or textTemplate or 12 )
dropdown.hasLabel = label
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
maxColumnWidth , maxWidgetWidth = setDropdownProperties ( parent , dropdown , widgetTable , currentXOffset , currentYOffset , textTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth )
--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
amountLineWidgetAdded = amountLineWidgetAdded + 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 )
local label = detailsFramework : NewLabel ( parent , nil , " $parentLabel " .. index , nil , " " , " GameFontNormal " , widgetTable.text_template or textTemplate or 12 )
switch.hasLabel = label
local namePhraseId = getNamePhraseID ( widgetTable , languageAddonId , languageTable , true )
DetailsFramework.Language . RegisterObjectWithDefault ( languageAddonId , label.widget , namePhraseId , formatOptionNameWithColon ( widgetTable.name , useColon ) )
maxColumnWidth , maxWidgetWidth , extraPaddingY = setToggleProperties ( parent , switch , widgetTable , currentXOffset , currentYOffset , switchTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , switchIsCheckbox , bUseBoxFirstOnAllWidgets , menuOptions , index , maxWidgetWidth )
--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
amountLineWidgetAdded = amountLineWidgetAdded + 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 )
local label = detailsFramework : NewLabel ( parent , nil , " $parentLabel " .. index , nil , " " , " GameFontNormal " , widgetTable.text_template or textTemplate or 12 )
slider.hasLabel = label
local namePhraseId = getNamePhraseID ( widgetTable , languageAddonId , languageTable , true )
DetailsFramework.Language . RegisterObjectWithDefault ( languageAddonId , label.widget , namePhraseId , formatOptionNameWithColon ( widgetTable.name , useColon ) )
maxColumnWidth , maxWidgetWidth = setRangeProperties ( parent , slider , widgetTable , currentXOffset , currentYOffset , sliderTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , bIsDecimals , bAttachSliderButtonsToLeft )
--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
amountLineWidgetAdded = amountLineWidgetAdded + 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 )
local label = detailsFramework : NewLabel ( parent , nil , " $parentLabel " .. index , nil , " " , " GameFontNormal " , widgetTable.text_template or textTemplate or 12 )
colorpick.hasLabel = label
local namePhraseId = getNamePhraseID ( widgetTable , languageAddonId , languageTable , true )
DetailsFramework.Language . RegisterObjectWithDefault ( languageAddonId , label.widget , namePhraseId , formatOptionNameWithColon ( widgetTable.name , useColon ) )
maxColumnWidth , maxWidgetWidth , extraPaddingY = setColorProperties ( parent , colorpick , widgetTable , currentXOffset , currentYOffset , buttonTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , bUseBoxFirstOnAllWidgets , extraPaddingY )
--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
amountLineWidgetAdded = amountLineWidgetAdded + 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 )
button.widget_type = " execute "
local label = detailsFramework : NewLabel ( parent , nil , " $parentLabel " .. index , nil , " " , " GameFontNormal " , widgetTable.text_template or textTemplate or 12 )
button.hasLabel = label
local namePhraseId = getNamePhraseID ( widgetTable , languageAddonId , languageTable , true )
DetailsFramework.Language . RegisterObjectWithDefault ( languageAddonId , button.widget , namePhraseId , widgetTable.name )
local descPhraseId = getDescripttionPhraseID ( widgetTable , languageAddonId , languageTable )
DetailsFramework.Language . RegisterTableKeyWithDefault ( languageAddonId , button , " have_tooltip " , descPhraseId , widgetTable.desc )
maxColumnWidth , maxWidgetWidth , latestInlineWidget = setExecuteProperties ( parent , button , widgetTable , currentXOffset , currentYOffset , buttonTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , textTemplate , latestInlineWidget )
--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
amountLineWidgetAdded = amountLineWidgetAdded + 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 )
local label = detailsFramework : NewLabel ( parent , nil , " $parentLabel " .. index , nil , " " , " GameFontNormal " , widgetTable.text_template or textTemplate or 12 )
textentry.hasLabel = label
textentry.align = widgetTable.align or " left "
local descPhraseId = getDescripttionPhraseID ( widgetTable , languageAddonId , languageTable )
DetailsFramework.Language . RegisterTableKeyWithDefault ( languageAddonId , textentry , " have_tooltip " , descPhraseId , widgetTable.desc )
local namePhraseId = getNamePhraseID ( widgetTable , languageAddonId , languageTable , true )
DetailsFramework.Language . RegisterObjectWithDefault ( languageAddonId , label.widget , namePhraseId , formatOptionNameWithColon ( widgetTable.name , useColon ) )
maxColumnWidth , maxWidgetWidth = setTextEntryProperties ( parent , textentry , widgetTable , currentXOffset , currentYOffset , buttonTemplate , widgetWidth , widgetHeight , bAlignAsPairs , nAlignAsPairsLength , valueChangeHook , maxColumnWidth , maxWidgetWidth , textTemplate )
--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
amountLineWidgetAdded = amountLineWidgetAdded + 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
amountLineWidgetAdded = 0
maxColumnWidth = 0
maxWidgetWidth = 0
end
else
if ( widgetTable.type == " breakline " or currentYOffset < height ) then
currentYOffset = yOffset
currentXOffset = currentXOffset + maxColumnWidth + 20
amountLineWidgetAdded = 0
maxColumnWidth = 0
end
end
end --no widget.hidden
end --end loop
if ( bUseScrollFrame ) then
parent : SetHeight ( biggestColumnHeight * - 1 )
end
detailsFramework.RefreshUnsafeOptionsWidgets ( )
onMenuBuilt ( parent )
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