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.
1537 lines
48 KiB
1537 lines
48 KiB
if not WeakAuras.IsCorrectVersion() or not WeakAuras.IsLibsOK() then return end
|
|
local AddonName, OptionsPrivate = ...
|
|
|
|
local L = WeakAuras.L
|
|
local regionOptions = WeakAuras.regionOptions
|
|
|
|
local commonOptionsCache = {}
|
|
OptionsPrivate.commonOptionsCache = commonOptionsCache
|
|
commonOptionsCache.data = {}
|
|
|
|
commonOptionsCache.GetOrCreateData = function(self, info)
|
|
local base = self.data
|
|
for i, key in ipairs(info) do
|
|
base[key] = base[key] or {}
|
|
base = base[key]
|
|
end
|
|
return base
|
|
end
|
|
|
|
commonOptionsCache.GetData = function(self, info)
|
|
local base = self.data
|
|
for i, key in ipairs(info) do
|
|
if base[key] and type(base[key]) == "table" then
|
|
base = base[key]
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
return base
|
|
end
|
|
|
|
commonOptionsCache.SetSameAll = function(self, info, value)
|
|
local base = self:GetOrCreateData(info)
|
|
base.sameAll = value
|
|
end
|
|
|
|
commonOptionsCache.GetSameAll = function(self, info)
|
|
local base = self:GetData(info)
|
|
if base then
|
|
return base.sameAll
|
|
end
|
|
end
|
|
|
|
commonOptionsCache.SetNameAll = function(self, info, value)
|
|
local base = self:GetOrCreateData(info)
|
|
base.nameAll = value
|
|
end
|
|
|
|
commonOptionsCache.GetNameAll = function(self, info)
|
|
local base = self:GetData(info)
|
|
if base then
|
|
return base.nameAll
|
|
end
|
|
end
|
|
|
|
commonOptionsCache.Clear = function(self)
|
|
self.data = {}
|
|
end
|
|
|
|
|
|
local parsePrefix = function(input, data, create)
|
|
local subRegionIndex, property = string.match(input, "^sub%.(%d+)%..-%.(.+)")
|
|
subRegionIndex = tonumber(subRegionIndex)
|
|
if subRegionIndex then
|
|
if create then
|
|
data.subRegions = data.subRegions or {}
|
|
data.subRegions[subRegionIndex] = data.subRegions[subRegionIndex] or {}
|
|
else
|
|
if not data.subRegions or not data.subRegions[subRegionIndex] then
|
|
return nil
|
|
end
|
|
end
|
|
return data.subRegions[subRegionIndex], property
|
|
end
|
|
local index = string.find(input, ".", 1, true);
|
|
if (index) then
|
|
return data, string.sub(input, index + 1);
|
|
end
|
|
return data, input
|
|
end
|
|
|
|
local function setFuncs(option, input)
|
|
if type(input) == "function" then
|
|
option.func = input
|
|
else
|
|
option.func = input.func
|
|
option.disabled = input.disabled
|
|
end
|
|
end
|
|
|
|
local function addCollapsibleHeader(options, key, input, order, isGroupTab)
|
|
if input.__noHeader then
|
|
return
|
|
end
|
|
local title = input.__title
|
|
local hasAdd = input.__add
|
|
local hasDelete = input.__delete
|
|
local hasUp = input.__up
|
|
local hasDown = input.__down
|
|
local hasDuplicate = input.__duplicate
|
|
local hasApplyTemplate = input.__applyTemplate
|
|
local defaultCollapsed = input.__collapsed
|
|
local hiddenFunc = input.__hidden
|
|
local notcollapsable = input.__notcollapsable
|
|
local marginTop = input.__topLine
|
|
local withoutheader = input.__withoutheader
|
|
local isCollapsed = input.__isCollapsed
|
|
local setCollapsed = input.__setCollapsed
|
|
|
|
if not isCollapsed then
|
|
isCollapsed = function()
|
|
return OptionsPrivate.IsCollapsed("collapse", "region", key, defaultCollapsed)
|
|
end
|
|
end
|
|
|
|
if not setCollapsed then
|
|
setCollapsed = function(info, button, secondCall)
|
|
if not notcollapsable and not secondCall then
|
|
local isCollapsed = OptionsPrivate.IsCollapsed("collapse", "region", key, defaultCollapsed)
|
|
OptionsPrivate.SetCollapsed("collapse", "region", key, not isCollapsed)
|
|
end
|
|
end
|
|
end
|
|
|
|
local titleWidth = WeakAuras.doubleWidth - (hasAdd and 0.15 or 0) - (hasDelete and 0.15 or 0) - (hasUp and 0.15 or 0)
|
|
- (hasDown and 0.15 or 0) - (hasDuplicate and 0.15 or 0) - (hasApplyTemplate and 0.15 or 0)
|
|
|
|
options[key .. "collapseSpacer"] = {
|
|
type = marginTop and "header" or "description",
|
|
name = "",
|
|
order = order,
|
|
width = "full",
|
|
hidden = hiddenFunc,
|
|
}
|
|
|
|
if not withoutheader then
|
|
options[key .. "collapseButton"] = {
|
|
type = "execute",
|
|
name = title,
|
|
order = order + 0.1,
|
|
width = titleWidth,
|
|
func = setCollapsed,
|
|
image = function()
|
|
if notcollapsable then
|
|
return "Interface\\AddOns\\WeakAuras\\Media\\Textures\\bullet1", 18, 18
|
|
else
|
|
return isCollapsed() and "Interface\\AddOns\\WeakAuras\\Media\\Textures\\expand" or "Interface\\AddOns\\WeakAuras\\Media\\Textures\\collapse", 18, 18
|
|
end
|
|
end,
|
|
control = "WeakAurasExpand",
|
|
hidden = hiddenFunc
|
|
}
|
|
|
|
if hasAdd then
|
|
options[key .. "addButton"] = {
|
|
type = "execute",
|
|
name = L["Add"],
|
|
order = order + 0.2,
|
|
width = 0.15,
|
|
image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\add",
|
|
imageWidth = 24,
|
|
imageHeight = 24,
|
|
control = "WeakAurasIcon",
|
|
hidden = hiddenFunc
|
|
}
|
|
setFuncs(options[key .. "addButton"], input.__add)
|
|
end
|
|
|
|
if hasUp then
|
|
options[key .. "upButton"] = {
|
|
type = "execute",
|
|
name = L["Move Up"],
|
|
order = order + 0.3,
|
|
width = 0.15,
|
|
image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\moveup",
|
|
imageWidth = 24,
|
|
imageHeight = 24,
|
|
control = "WeakAurasIcon",
|
|
hidden = hiddenFunc
|
|
}
|
|
setFuncs(options[key .. "upButton"], input.__up)
|
|
end
|
|
|
|
if hasDown then
|
|
options[key .. "downButton"] = {
|
|
type = "execute",
|
|
name = L["Move Down"],
|
|
order = order + 0.4,
|
|
width = 0.15,
|
|
image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\movedown",
|
|
imageWidth = 24,
|
|
imageHeight = 24,
|
|
control = "WeakAurasIcon",
|
|
hidden = hiddenFunc
|
|
}
|
|
setFuncs(options[key .. "downButton"], input.__down)
|
|
end
|
|
|
|
if hasDuplicate then
|
|
options[key .. "duplicateButton"] = {
|
|
type = "execute",
|
|
name = L["Duplicate"],
|
|
order = order + 0.5,
|
|
width = 0.15,
|
|
image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\duplicate",
|
|
imageWidth = 24,
|
|
imageHeight = 24,
|
|
control = "WeakAurasIcon",
|
|
hidden = hiddenFunc
|
|
}
|
|
setFuncs(options[key .. "duplicateButton"], input.__duplicate)
|
|
end
|
|
|
|
if hasDelete then
|
|
options[key .. "deleteButton"] = {
|
|
type = "execute",
|
|
name = L["Delete"],
|
|
order = order + 0.6,
|
|
width = 0.15,
|
|
image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\delete",
|
|
imageWidth = 24,
|
|
imageHeight = 24,
|
|
control = "WeakAurasIcon",
|
|
hidden = hiddenFunc
|
|
}
|
|
setFuncs(options[key .. "deleteButton"], input.__delete)
|
|
end
|
|
|
|
if hasApplyTemplate then
|
|
options[key .. "applyTemplate"] = {
|
|
type = "execute",
|
|
name = L["Apply Template"],
|
|
order = order + 0.7,
|
|
width = 0.15,
|
|
image = "Interface\\AddOns\\WeakAuras\\Media\\Textures\\template",
|
|
imageWidth = 24,
|
|
imageHeight = 24,
|
|
control = "WeakAurasIcon",
|
|
hidden = hiddenFunc
|
|
}
|
|
setFuncs(options[key .. "applyTemplate"], input.__applyTemplate)
|
|
end
|
|
end
|
|
|
|
if hiddenFunc then
|
|
return function()
|
|
return hiddenFunc() or isCollapsed()
|
|
end
|
|
else
|
|
return isCollapsed
|
|
end
|
|
end
|
|
|
|
local function copyOptionTable(input, orderAdjustment, collapsedFunc)
|
|
local resultOption = CopyTable(input);
|
|
resultOption.order = orderAdjustment + resultOption.order;
|
|
if collapsedFunc then
|
|
local oldHidden = resultOption.hidden;
|
|
if oldHidden ~= nil then
|
|
local oldFunc
|
|
if type(oldHidden) ~= "function" then
|
|
oldFunc = function(...) return oldHidden end
|
|
else
|
|
oldFunc = oldHidden
|
|
end
|
|
resultOption.hidden = function(...)
|
|
if collapsedFunc() then
|
|
return true
|
|
else
|
|
return oldFunc(...)
|
|
end
|
|
end
|
|
else
|
|
resultOption.hidden = collapsedFunc;
|
|
end
|
|
end
|
|
return resultOption;
|
|
end
|
|
|
|
local flattenRegionOptions = function(allOptions, isGroupTab)
|
|
local result = {};
|
|
local base = 1000;
|
|
|
|
for optionGroup, options in pairs(allOptions) do
|
|
local groupBase = base * options.__order
|
|
|
|
local collapsedFunc = addCollapsibleHeader(result, optionGroup, options, groupBase, isGroupTab)
|
|
|
|
for optionName, option in pairs(options) do
|
|
if not optionName:find("^__") then
|
|
result[optionGroup .. "." .. optionName] = copyOptionTable(option, groupBase, collapsedFunc);
|
|
end
|
|
end
|
|
end
|
|
|
|
return result;
|
|
end
|
|
|
|
local function fixMetaOrders(allOptions)
|
|
-- assumes that the results from create methods are contiguous in __order fields
|
|
-- shifts __order fields such that each optionGroup is ordered correctly relative
|
|
-- to its peers, but has a unique __order number in the combined option table.
|
|
local groupOrders = {}
|
|
local maxGroupOrder = 0
|
|
for optionGroup, options in pairs(allOptions) do
|
|
local metaOrder = options.__order
|
|
groupOrders[metaOrder] = groupOrders[metaOrder] or {}
|
|
maxGroupOrder = max(maxGroupOrder, metaOrder)
|
|
tinsert(groupOrders[metaOrder], optionGroup)
|
|
end
|
|
|
|
local index = 0
|
|
local newOrder = 1
|
|
while index <= maxGroupOrder do
|
|
index = index + 1
|
|
if groupOrders[index] then
|
|
table.sort(groupOrders[index])
|
|
for _, optionGroup in ipairs(groupOrders[index]) do
|
|
allOptions[optionGroup].__order = newOrder
|
|
newOrder = newOrder + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function removeFuncs(intable, removeFunc)
|
|
for i,v in pairs(intable) do
|
|
if(i == "get" or i == "set" or i == "hidden" or i == "disabled") then
|
|
intable[i] = nil;
|
|
elseif (i == "func" and removeFunc) then
|
|
intable[i] = nil
|
|
elseif(type(v) == "table" and i ~= "values" and i ~= "extraFunctions") then
|
|
removeFuncs(v, removeFunc)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function getChildOption(options, info)
|
|
for i=1,#info do
|
|
options = options.args[info[i]];
|
|
if not(options) then
|
|
return nil;
|
|
end
|
|
|
|
if (options.hidden) then
|
|
local type = type(options.hidden);
|
|
if (type == "bool") then
|
|
if (options.hidden) then
|
|
return nil;
|
|
end
|
|
elseif (type == "function") then
|
|
if (options.hidden(info)) then
|
|
return nil;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return options
|
|
end
|
|
|
|
local function hiddenChild(childOptionTable, info)
|
|
for i=#childOptionTable,0,-1 do
|
|
if(childOptionTable[i].hidden ~= nil) then
|
|
if(type(childOptionTable[i].hidden) == "boolean") then
|
|
return childOptionTable[i].hidden;
|
|
elseif(type(childOptionTable[i].hidden) == "function") then
|
|
return childOptionTable[i].hidden(info);
|
|
end
|
|
end
|
|
end
|
|
return false;
|
|
end
|
|
|
|
local function CreateHiddenAll(subOption)
|
|
return function(data, info)
|
|
if(#data.controlledChildren == 0) then
|
|
return true;
|
|
end
|
|
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOptions = OptionsPrivate.EnsureOptions(child, subOption)
|
|
local childOption = childOptions;
|
|
local childOptionTable = {[0] = childOption};
|
|
for i=1,#info do
|
|
childOption = childOption.args[info[i]];
|
|
childOptionTable[i] = childOption;
|
|
end
|
|
if (childOption) then
|
|
if (not hiddenChild(childOptionTable, info)) then
|
|
return false;
|
|
end
|
|
end
|
|
end
|
|
|
|
return true;
|
|
end
|
|
end
|
|
|
|
local function disabledChild(childOptionTable, info)
|
|
for i=#childOptionTable,0,-1 do
|
|
if(childOptionTable[i].disabled ~= nil) then
|
|
if(type(childOptionTable[i].disabled) == "boolean") then
|
|
return childOptionTable[i].disabled;
|
|
elseif(type(childOptionTable[i].disabled) == "function") then
|
|
return childOptionTable[i].disabled(info);
|
|
end
|
|
end
|
|
end
|
|
return false;
|
|
end
|
|
|
|
local function CreateDisabledAll(subOption)
|
|
return function(data, info)
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOptions = OptionsPrivate.EnsureOptions(child, subOption);
|
|
local childOption = childOptions;
|
|
local childOptionTable = {[0] = childOption};
|
|
for i=1,#info do
|
|
childOption = childOption.args[info[i]];
|
|
childOptionTable[i] = childOption;
|
|
end
|
|
if (childOption) then
|
|
if (not disabledChild(childOptionTable, info)) then
|
|
return false;
|
|
end
|
|
end
|
|
end
|
|
|
|
return true;
|
|
end
|
|
end
|
|
|
|
local function disabledOrHiddenChild(childOptionTable, info)
|
|
return hiddenChild(childOptionTable, info) or disabledChild(childOptionTable, info);
|
|
end
|
|
|
|
|
|
local function replaceNameDescFuncs(intable, data, subOption)
|
|
local function compareTables(tableA, tableB)
|
|
if(#tableA == #tableB) then
|
|
for j=1,#tableA do
|
|
if(type(tableA[j]) == "number" and type(tableB[j]) == "number") then
|
|
if((math.floor(tableA[j] * 100) / 100) ~= (math.floor(tableB[j] * 100) / 100)) then
|
|
return false;
|
|
end
|
|
else
|
|
if(tableA[j] ~= tableB[j]) then
|
|
return false;
|
|
end
|
|
end
|
|
end
|
|
else
|
|
return false;
|
|
end
|
|
return true;
|
|
end
|
|
|
|
local function getValueFor(options, info, key)
|
|
local childOptionTable = {[0] = options};
|
|
for i=1,#info do
|
|
options = options.args[info[i]];
|
|
if (not options) then
|
|
return nil;
|
|
end
|
|
childOptionTable[i] = options;
|
|
end
|
|
|
|
if (disabledOrHiddenChild(childOptionTable, info)) then
|
|
return nil;
|
|
end
|
|
|
|
for i=#childOptionTable,0,-1 do
|
|
if(childOptionTable[i][key]) then
|
|
return childOptionTable[i][key];
|
|
end
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
local function combineKeys(info)
|
|
local combinedKeys = nil;
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local values = getValueFor(OptionsPrivate.EnsureOptions(child, subOption), info, "values");
|
|
if (values) then
|
|
if (type(values) == "function") then
|
|
values = values(info);
|
|
end
|
|
if (type(values) == "table") then
|
|
combinedKeys = combinedKeys or {};
|
|
for k, v in pairs(values) do
|
|
combinedKeys[k] = v;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return combinedKeys;
|
|
end
|
|
|
|
local function regionPrefix(input)
|
|
local index = string.find(input, ".", 1, true);
|
|
if (index) then
|
|
local regionType = string.sub(input, 1, index - 1);
|
|
return regionOptions[regionType] and regionType;
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
local function sameAll(info)
|
|
local cached = commonOptionsCache:GetSameAll(info)
|
|
if (cached ~= nil) then
|
|
return cached
|
|
end
|
|
|
|
local combinedValues = {};
|
|
local first = true;
|
|
local combinedKeys = combineKeys(info);
|
|
|
|
local isToggle = nil
|
|
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
if isToggle == nil then
|
|
local childOption = getChildOption(OptionsPrivate.EnsureOptions(child, subOption), info)
|
|
isToggle = childOption and childOption.type == "toggle"
|
|
end
|
|
|
|
local regionType = regionPrefix(info[#info]);
|
|
if(child and (not regionType or child.regionType == regionType or regionType == "sub")) then
|
|
local childOptions = OptionsPrivate.EnsureOptions(child, subOption)
|
|
local get = getValueFor(childOptions, info, "get");
|
|
if (combinedKeys) then
|
|
for key, _ in pairs(combinedKeys) do
|
|
local values = {};
|
|
if (get) then
|
|
values = { get(info, key) };
|
|
end
|
|
if (combinedValues[key] == nil) then
|
|
combinedValues[key] = values;
|
|
else
|
|
if (not compareTables(combinedValues[key], values)) then
|
|
commonOptionsCache:SetSameAll(info, false)
|
|
return nil;
|
|
end
|
|
end
|
|
end
|
|
else
|
|
local values = {};
|
|
if (get) then
|
|
values = { get(info) };
|
|
if isToggle and values[1] == nil then
|
|
values[1] = false
|
|
end
|
|
end
|
|
if(first) then
|
|
combinedValues = values;
|
|
first = false;
|
|
else
|
|
if (not compareTables(combinedValues, values)) then
|
|
commonOptionsCache:SetSameAll(info, false)
|
|
return nil;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
commonOptionsCache:SetSameAll(info, true)
|
|
return true;
|
|
end
|
|
|
|
local function nameAll(info)
|
|
local cached = commonOptionsCache:GetNameAll(info)
|
|
if (cached ~= nil) then
|
|
return cached
|
|
end
|
|
|
|
local combinedName;
|
|
local first = true;
|
|
local foundNames = {};
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOption = getChildOption(OptionsPrivate.EnsureOptions(child, subOption), info);
|
|
if (childOption) then
|
|
local name;
|
|
if(type(childOption.name) == "function") then
|
|
name = childOption.name(info);
|
|
else
|
|
name = childOption.name;
|
|
commonOptionsCache:SetNameAll(info, name)
|
|
return name
|
|
end
|
|
if (not name) then
|
|
-- Do nothing
|
|
elseif(first) then
|
|
if (name ~= "") then
|
|
combinedName = name;
|
|
first = false;
|
|
end
|
|
foundNames[name] = true;
|
|
elseif not(foundNames[name]) then
|
|
if (name ~= "") then
|
|
if (childOption.type == "description") then
|
|
combinedName = combinedName .. "\n\n" .. name;
|
|
else
|
|
combinedName = combinedName .. " / " .. name;
|
|
end
|
|
end
|
|
foundNames[name] = true;
|
|
end
|
|
end
|
|
end
|
|
if combinedName then
|
|
commonOptionsCache:SetNameAll(info, combinedName)
|
|
end
|
|
|
|
return combinedName or ""
|
|
end
|
|
|
|
local function descAll(info)
|
|
local combinedDesc;
|
|
local first = true;
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOption = getChildOption(OptionsPrivate.EnsureOptions(child, subOption), info);
|
|
if (childOption) then
|
|
local desc;
|
|
if(type(childOption.desc) == "function") then
|
|
desc = childOption.desc(info);
|
|
else
|
|
desc = childOption.desc;
|
|
end
|
|
if(first) then
|
|
combinedDesc = desc;
|
|
first = false;
|
|
elseif not(combinedDesc == desc) then
|
|
return L["Not all children have the same value for this option"];
|
|
end
|
|
end
|
|
end
|
|
return combinedDesc;
|
|
end
|
|
|
|
local function recurse(intable)
|
|
for i,v in pairs(intable) do
|
|
if(i == "name" and type(v) ~= "table") then
|
|
intable.name = function(info)
|
|
local name = nameAll(info);
|
|
if(sameAll(info)) then
|
|
return name;
|
|
else
|
|
if(name == "") then
|
|
return name;
|
|
else
|
|
return "|cFF4080FF"..(name or "error").."|r";
|
|
end
|
|
end
|
|
end
|
|
intable.desc = function(info)
|
|
if(sameAll(info)) then
|
|
return descAll(info);
|
|
else
|
|
local combinedKeys = nil;
|
|
if (intable.type == "multiselect") then
|
|
combinedKeys = combineKeys(info)
|
|
end
|
|
|
|
local values = {};
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOptions = OptionsPrivate.EnsureOptions(child, subOption)
|
|
local childOption = childOptions;
|
|
local childOptionTable = {[0] = childOption};
|
|
for i=1,#info do
|
|
childOption = childOption.args[info[i]];
|
|
childOptionTable[i] = childOption;
|
|
end
|
|
if (childOption and not hiddenChild(childOptionTable, info)) then
|
|
for i=#childOptionTable,0,-1 do
|
|
if(childOptionTable[i].get) then
|
|
if(intable.type == "toggle") then
|
|
local name, tri;
|
|
if(type(childOption.name) == "function") then
|
|
name = childOption.name(info);
|
|
tri = true;
|
|
else
|
|
name = childOption.name;
|
|
end
|
|
if(tri and childOptionTable[i].get(info)) then
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r"..name);
|
|
elseif(tri) then
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r"..L["Ignored"]);
|
|
elseif(childOptionTable[i].get(info)) then
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r|cFF00FF00"..L["Enabled"].."|r");
|
|
else
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r|cFFFF0000"..L["Disabled"].."|r");
|
|
end
|
|
elseif(intable.type == "color") then
|
|
local r, g, b = childOptionTable[i].get(info);
|
|
r, g, b = r or 1, g or 1, b or 1;
|
|
tinsert(values, ("|cFF%2x%2x%2x%s|r"):format(r * 220 + 35, g * 220 + 35, b * 220 + 35, child.id));
|
|
elseif(intable.type == "select") then
|
|
local selectValues = type(intable.values) == "table" and intable.values or intable.values(info);
|
|
local key = childOptionTable[i].get(info);
|
|
local display = key and selectValues[key] or L["None"];
|
|
if intable.dialogControl == "LSM30_Font" then
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r" .. key);
|
|
else
|
|
if type(display) == "string" then
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r"..display);
|
|
elseif type(display) == "table" then
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r"..display[1].."/"..display[2] );
|
|
end
|
|
end
|
|
elseif(intable.type == "multiselect") then
|
|
local selectedValues = {};
|
|
for k, v in pairs(combinedKeys) do
|
|
if (childOptionTable[i].get(info, k)) then
|
|
tinsert(selectedValues, tostring(v))
|
|
end
|
|
end
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r"..table.concat(selectedValues, ","));
|
|
else
|
|
local display = childOptionTable[i].get(info) or L["None"];
|
|
if(type(display) == "number") then
|
|
display = math.floor(display * 100) / 100;
|
|
else
|
|
if #display > 50 then
|
|
display = display:sub(1, 50) .. "..."
|
|
end
|
|
end
|
|
tinsert(values, "|cFFE0E000"..child.id..": |r"..display);
|
|
end
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return table.concat(values, "\n");
|
|
end
|
|
end
|
|
elseif(type(v) == "table" and i ~= "values") then
|
|
recurse(v);
|
|
end
|
|
end
|
|
end
|
|
recurse(intable);
|
|
end
|
|
|
|
local function replaceImageFuncs(intable, data, subOption)
|
|
local function imageAll(info)
|
|
local combinedImage = {};
|
|
local first = true;
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOption = OptionsPrivate.EnsureOptions(child, subOption)
|
|
if not(childOption) then
|
|
return "error"
|
|
end
|
|
childOption = getChildOption(childOption, info);
|
|
if childOption and childOption.image then
|
|
local image = {childOption.image(info)};
|
|
if(first) then
|
|
combinedImage = image;
|
|
first = false;
|
|
else
|
|
if not(combinedImage[1] == image[1]) then
|
|
return "", 0, 0;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return unpack(combinedImage);
|
|
end
|
|
|
|
local function recurse(intable)
|
|
for i,v in pairs(intable) do
|
|
if(i == "image" and type(v) == "function") then
|
|
intable[i] = imageAll;
|
|
elseif(type(v) == "table" and i ~= "values") then
|
|
recurse(v);
|
|
end
|
|
end
|
|
end
|
|
recurse(intable);
|
|
end
|
|
|
|
local function replaceValuesFuncs(intable, data, subOption)
|
|
local function valuesAll(info)
|
|
local combinedValues = {};
|
|
local handledValues = {};
|
|
local first = true;
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOption = OptionsPrivate.EnsureOptions(child, subOption)
|
|
if not(childOption) then
|
|
return "error"
|
|
end
|
|
|
|
childOption = getChildOption(childOption, info);
|
|
if (childOption) then
|
|
local values = childOption.values;
|
|
if (type(values) == "function") then
|
|
values = values(info);
|
|
end
|
|
if(first) then
|
|
for k, v in pairs(values) do
|
|
handledValues[k] = handledValues[k] or {};
|
|
handledValues[k][v] = true;
|
|
combinedValues[k] = v;
|
|
end
|
|
first = false;
|
|
else
|
|
for k, v in pairs(values) do
|
|
if (handledValues[k] and handledValues[k][v]) then
|
|
-- Already known key/value pair
|
|
else
|
|
if (combinedValues[k]) then
|
|
combinedValues[k] = combinedValues[k] .. "/" .. v;
|
|
else
|
|
combinedValues[k] = v;
|
|
end
|
|
handledValues[k] = handledValues[k] or {};
|
|
handledValues[k][v] = true;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return combinedValues;
|
|
end
|
|
|
|
local function recurse(intable)
|
|
for i,v in pairs(intable) do
|
|
if(i == "values" and type(v) == "function") then
|
|
intable[i] = valuesAll;
|
|
elseif(type(v) == "table" and i ~= "values") then
|
|
recurse(v);
|
|
end
|
|
end
|
|
end
|
|
recurse(intable);
|
|
end
|
|
|
|
local getHelper = {
|
|
first = true,
|
|
combinedValues = {},
|
|
same = true,
|
|
Set = function(self, values)
|
|
if self.same == false then
|
|
return false
|
|
end
|
|
if(self.first) then
|
|
self.combinedValues = values;
|
|
self.first = false;
|
|
return true
|
|
else
|
|
if(#self.combinedValues == #values) then
|
|
for j=1,#self.combinedValues do
|
|
if(type(self.combinedValues[j]) == "number" and type(values[j]) == "number") then
|
|
if((math.floor(self.combinedValues[j] * 100) / 100) ~= (math.floor(values[j] * 100) / 100)) then
|
|
self.same = false;
|
|
break;
|
|
end
|
|
else
|
|
if(self.combinedValues[j] ~= values[j]) then
|
|
self.same = false;
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
else
|
|
self.same = false;
|
|
end
|
|
return self.same
|
|
end
|
|
end,
|
|
Get = function(self)
|
|
return self.combinedValues
|
|
end,
|
|
GetSame = function(self)
|
|
return self.same
|
|
end,
|
|
HasValue = function(self)
|
|
return not self.first
|
|
end
|
|
}
|
|
|
|
|
|
local function CreateGetAll(subOption)
|
|
return function(data, info, ...)
|
|
local isToggle = nil
|
|
|
|
local allChildren = CopyTable(getHelper)
|
|
local enabledChildren = CopyTable(getHelper)
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
if isToggle == nil then
|
|
local childOptions = getChildOption(OptionsPrivate.EnsureOptions(child, subOption), info)
|
|
isToggle = childOptions and childOptions.type == "toggle"
|
|
end
|
|
|
|
local childOptions = OptionsPrivate.EnsureOptions(child, subOption)
|
|
local childOption = childOptions;
|
|
local childOptionTable = {[0] = childOption};
|
|
for i=1,#info do
|
|
childOption = childOption.args[info[i]];
|
|
childOptionTable[i] = childOption;
|
|
end
|
|
if (childOption) then
|
|
for i=#childOptionTable,0,-1 do
|
|
if(childOptionTable[i].get) then
|
|
local values = {childOptionTable[i].get(info, ...)};
|
|
if isToggle and values[1] == nil then
|
|
values[1] = false
|
|
end
|
|
|
|
allChildren:Set(values)
|
|
if not disabledOrHiddenChild(childOptionTable, info) then
|
|
enabledChildren:Set(values)
|
|
end
|
|
|
|
if not allChildren:GetSame() and not enabledChildren:GetSame() then
|
|
return nil;
|
|
end
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if enabledChildren:HasValue() then
|
|
return unpack(enabledChildren:Get())
|
|
else
|
|
-- This can happen if all children are disabled
|
|
return unpack(allChildren:Get())
|
|
end
|
|
end
|
|
end
|
|
|
|
local function CreateSetAll(subOption, getAll)
|
|
return function(data, info, ...)
|
|
OptionsPrivate.Private.pauseOptionsProcessing(true);
|
|
OptionsPrivate.Private.PauseAllDynamicGroups()
|
|
local before = getAll(data, info, ...)
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOptions = OptionsPrivate.EnsureOptions(child, subOption)
|
|
local childOption = childOptions;
|
|
local childOptionTable = {[0] = childOption};
|
|
for i=1,#info do
|
|
childOption = childOption.args[info[i]];
|
|
childOptionTable[i] = childOption;
|
|
end
|
|
|
|
if (childOption and not disabledOrHiddenChild(childOptionTable, info)) then
|
|
for i=#childOptionTable,0,-1 do
|
|
if(childOptionTable[i].set) then
|
|
if (childOptionTable[i].type == "multiselect") then
|
|
childOptionTable[i].set(info, ..., not before);
|
|
else
|
|
childOptionTable[i].set(info, ...);
|
|
end
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
OptionsPrivate.Private.ResumeAllDynamicGroups()
|
|
OptionsPrivate.Private.pauseOptionsProcessing(false);
|
|
OptionsPrivate.Private.ScanForLoads();
|
|
OptionsPrivate.SortDisplayButtons(nil, true);
|
|
OptionsPrivate.UpdateOptions()
|
|
end
|
|
end
|
|
|
|
local function CreateExecuteAll(subOption)
|
|
return function(data, info, button)
|
|
local secondCall = nil
|
|
for child in OptionsPrivate.Private.TraverseLeafs(data) do
|
|
local childOptions = OptionsPrivate.EnsureOptions(child, subOption)
|
|
local childOption = childOptions;
|
|
local childOptionTable = {[0] = childOption};
|
|
for i=1,#info do
|
|
childOption = childOption.args[info[i]];
|
|
childOptionTable[i] = childOption;
|
|
end
|
|
|
|
if (childOption and not disabledOrHiddenChild(childOptionTable, info)) then
|
|
-- Some functions, that is the expand/collapse functions need to be
|
|
-- effectively called only once. Passing in the secondCall parameter allows
|
|
-- them to distinguish between the first and every other call
|
|
childOption.func(info, button, secondCall)
|
|
secondCall = true
|
|
end
|
|
end
|
|
WeakAuras.ClearAndUpdateOptions(data.id)
|
|
end
|
|
end
|
|
|
|
local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint, group)
|
|
local metaOrder = 99
|
|
local function IsParentDynamicGroup()
|
|
if data.parent then
|
|
local parentData = WeakAuras.GetData(data.parent)
|
|
return parentData and parentData.regionType == "dynamicgroup"
|
|
end
|
|
end
|
|
|
|
local function IsGroupByFrame()
|
|
return data.regionType == "dynamicgroup" and data.useAnchorPerUnit
|
|
end
|
|
|
|
local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20;
|
|
local positionOptions = {
|
|
__title = L["Position Settings"],
|
|
__order = metaOrder,
|
|
width = {
|
|
type = "range",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Width"],
|
|
order = 60,
|
|
min = 1,
|
|
softMax = screenWidth,
|
|
max = 4 * screenWidth,
|
|
bigStep = 1,
|
|
hidden = hideWidthHeight,
|
|
},
|
|
height = {
|
|
type = "range",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Height"],
|
|
order = 61,
|
|
min = 1,
|
|
softMax = screenHeight,
|
|
max = 4 * screenHeight,
|
|
bigStep = 1,
|
|
hidden = hideWidthHeight,
|
|
},
|
|
xOffset = {
|
|
type = "range",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["X Offset"],
|
|
order = 62,
|
|
softMin = (-1 * screenWidth),
|
|
min = (-4 * screenWidth),
|
|
softMax = screenWidth,
|
|
max = 4 * screenWidth,
|
|
bigStep = 10,
|
|
get = function() return data.xOffset end,
|
|
set = function(info, v)
|
|
data.xOffset = v;
|
|
WeakAuras.Add(data);
|
|
WeakAuras.UpdateThumbnail(data);
|
|
OptionsPrivate.ResetMoverSizer();
|
|
OptionsPrivate.Private.AddParents(data)
|
|
end
|
|
},
|
|
yOffset = {
|
|
type = "range",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Y Offset"],
|
|
order = 63,
|
|
softMin = (-1 * screenHeight),
|
|
min = (-4 * screenHeight),
|
|
softMax = screenHeight,
|
|
max = 4 * screenHeight,
|
|
bigStep = 10,
|
|
get = function() return data.yOffset end,
|
|
set = function(info, v)
|
|
data.yOffset = v;
|
|
WeakAuras.Add(data);
|
|
WeakAuras.UpdateThumbnail(data);
|
|
OptionsPrivate.ResetMoverSizer();
|
|
OptionsPrivate.Private.AddParents(data)
|
|
end
|
|
},
|
|
selfPoint = {
|
|
type = "select",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Anchor"],
|
|
order = 70,
|
|
hidden = IsParentDynamicGroup,
|
|
values = OptionsPrivate.Private.point_types,
|
|
disabled = disableSelfPoint,
|
|
},
|
|
anchorFrameType = {
|
|
type = "select",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Anchored To"],
|
|
order = 72,
|
|
hidden = function()
|
|
return IsParentDynamicGroup() or IsGroupByFrame()
|
|
end,
|
|
values = (data.regionType == "group" or data.regionType == "dynamicgroup") and OptionsPrivate.Private.anchor_frame_types_group or OptionsPrivate.Private.anchor_frame_types,
|
|
},
|
|
-- Input field to select frame to anchor on
|
|
anchorFrameFrame = {
|
|
type = "input",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Frame"],
|
|
order = 72.2,
|
|
hidden = function()
|
|
if (IsParentDynamicGroup()) then
|
|
return true;
|
|
end
|
|
return not (data.anchorFrameType == "SELECTFRAME")
|
|
end
|
|
},
|
|
-- Button to select frame to anchor on
|
|
chooseAnchorFrameFrame = {
|
|
type = "execute",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Choose"],
|
|
order = 72.4,
|
|
hidden = function()
|
|
if (IsParentDynamicGroup()) then
|
|
return true;
|
|
end
|
|
return not (data.anchorFrameType == "SELECTFRAME")
|
|
end,
|
|
func = function()
|
|
OptionsPrivate.StartFrameChooser(data, {"anchorFrameFrame"});
|
|
end
|
|
},
|
|
anchorPoint = {
|
|
type = "select",
|
|
width = WeakAuras.normalWidth,
|
|
name = function()
|
|
if (data.anchorFrameType == "SCREEN") then
|
|
return L["To Screen's"]
|
|
elseif (data.anchorFrameType == "PRD") then
|
|
return L["To Personal Ressource Display's"];
|
|
else
|
|
return L["To Frame's"];
|
|
end
|
|
end,
|
|
order = 75,
|
|
hidden = function()
|
|
if (data.parent) then
|
|
if IsGroupByFrame() then
|
|
return false
|
|
end
|
|
return data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE";
|
|
else
|
|
return data.anchorFrameType == "MOUSE";
|
|
end
|
|
end,
|
|
values = OptionsPrivate.Private.point_types
|
|
},
|
|
anchorPointGroup = {
|
|
type = "select",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["To Group's"],
|
|
order = 76,
|
|
hidden = function()
|
|
if IsGroupByFrame() then
|
|
return true
|
|
end
|
|
if (data.anchorFrameType ~= "SCREEN") then
|
|
return true;
|
|
end
|
|
if (data.parent) then
|
|
return IsParentDynamicGroup();
|
|
end
|
|
return true;
|
|
end,
|
|
disabled = true,
|
|
values = {["CENTER"] = L["Anchor Point"]},
|
|
get = function() return "CENTER"; end
|
|
},
|
|
anchorFrameParent = {
|
|
type = "toggle",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Set Parent to Anchor"],
|
|
desc = L["Sets the anchored frame as the aura's parent, causing the aura to inherit attributes such as visibility and scale."],
|
|
order = 77,
|
|
get = function()
|
|
return data.anchorFrameParent or data.anchorFrameParent == nil;
|
|
end,
|
|
hidden = function()
|
|
return (data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE" or IsParentDynamicGroup());
|
|
end,
|
|
},
|
|
frameStrata = {
|
|
type = "select",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Frame Strata"],
|
|
order = 78,
|
|
values = OptionsPrivate.Private.frame_strata_types
|
|
},
|
|
anchorFrameSpace = {
|
|
type = "execute",
|
|
width = WeakAuras.normalWidth,
|
|
name = "",
|
|
order = 79,
|
|
image = function() return "", 0, 0 end,
|
|
hidden = function()
|
|
return not (data.anchorFrameType ~= "SCREEN" or IsParentDynamicGroup());
|
|
end
|
|
},
|
|
};
|
|
|
|
OptionsPrivate.commonOptions.AddCodeOption(positionOptions, data, L["Custom Anchor"], "custom_anchor", "https://github.com/WeakAuras/WeakAuras2/wiki/Custom-Code-Blocks#custom-anchor-function",
|
|
72.1, function() return not(data.anchorFrameType == "CUSTOM" and not IsParentDynamicGroup()) end, {"customAnchor"}, false, { setOnParent = group })
|
|
return positionOptions;
|
|
end
|
|
|
|
local function BorderOptions(id, data, showBackDropOptions, hiddenFunc, order)
|
|
local borderOptions = {
|
|
borderHeader = {
|
|
type = "header",
|
|
order = order,
|
|
name = L["Border Settings"],
|
|
hidden = hiddenFunc,
|
|
},
|
|
border = {
|
|
type = "toggle",
|
|
width = WeakAuras.doubleWidth,
|
|
name = L["Show Border"],
|
|
order = order + 0.1,
|
|
hidden = hiddenFunc,
|
|
},
|
|
borderEdge = {
|
|
type = "select",
|
|
width = WeakAuras.normalWidth,
|
|
dialogControl = "LSM30_Border",
|
|
name = L["Border Style"],
|
|
order = order + 0.2,
|
|
values = AceGUIWidgetLSMlists.border,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border end,
|
|
},
|
|
borderBackdrop = {
|
|
type = "select",
|
|
width = WeakAuras.normalWidth,
|
|
dialogControl = "LSM30_Background",
|
|
name = L["Backdrop Style"],
|
|
order = order + 0.3,
|
|
values = AceGUIWidgetLSMlists.background,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border end,
|
|
},
|
|
borderOffset = {
|
|
type = "range",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Border Offset"],
|
|
order = order + 0.3,
|
|
softMin = 0,
|
|
softMax = 32,
|
|
bigStep = 1,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border end,
|
|
},
|
|
borderSize = {
|
|
type = "range",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Border Size"],
|
|
order = order + 0.4,
|
|
min = 1,
|
|
softMax = 64,
|
|
bigStep = 1,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border end,
|
|
},
|
|
borderInset = {
|
|
type = "range",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Border Inset"],
|
|
order = order + 0.5,
|
|
softMin = 1,
|
|
softMax = 32,
|
|
bigStep = 1,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border end,
|
|
},
|
|
border_spacer = {
|
|
type = "description",
|
|
name = "",
|
|
width = WeakAuras.normalWidth,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border end,
|
|
order = order + 0.6
|
|
},
|
|
borderColor = {
|
|
type = "color",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Border Color"],
|
|
hasAlpha = true,
|
|
order = order + 0.7,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border end,
|
|
},
|
|
borderInFront = {
|
|
type = "toggle",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Border in Front"],
|
|
order = order + 0.8,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border or not showBackDropOptions end,
|
|
},
|
|
backdropColor = {
|
|
type = "color",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Backdrop Color"],
|
|
hasAlpha = true,
|
|
order = order + 0.9,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border end,
|
|
},
|
|
backdropInFront = {
|
|
type = "toggle",
|
|
width = WeakAuras.normalWidth,
|
|
name = L["Backdrop in Front"],
|
|
order = order + 1,
|
|
hidden = function() return hiddenFunc and hiddenFunc() or not data.border or not showBackDropOptions end,
|
|
},
|
|
}
|
|
|
|
return borderOptions;
|
|
end
|
|
|
|
local function noop()
|
|
end
|
|
|
|
local function GetCustomCode(data, path)
|
|
for _, key in ipairs(path) do
|
|
if (not data or not data[key]) then
|
|
return nil;
|
|
end
|
|
data = data[key];
|
|
end
|
|
return data;
|
|
end
|
|
|
|
local function AddCodeOption(args, data, name, prefix, url, order, hiddenFunc, path, encloseInFunction, options)
|
|
options = options and CopyTable(options) or {}
|
|
options.extraFunctions = options.extraFunctions or {};
|
|
tinsert(options.extraFunctions, 1, {
|
|
buttonLabel = L["Expand"],
|
|
func = function()
|
|
OptionsPrivate.OpenTextEditor(OptionsPrivate.GetPickedDisplay(), path, encloseInFunction, options.multipath, options.reloadOptions, options.setOnParent, url, options.validator)
|
|
end
|
|
});
|
|
|
|
args[prefix .. "_custom"] = {
|
|
type = "input",
|
|
width = WeakAuras.doubleWidth,
|
|
name = name,
|
|
order = order,
|
|
multiline = true,
|
|
hidden = hiddenFunc,
|
|
control = "WeakAurasMultiLineEditBox",
|
|
arg = {
|
|
extraFunctions = options.extraFunctions,
|
|
},
|
|
set = function(info, v)
|
|
local subdata = data;
|
|
for i = 1, #path -1 do
|
|
local key = path[i];
|
|
subdata[key] = subdata[key] or {};
|
|
subdata = subdata[key];
|
|
end
|
|
|
|
subdata[path[#path]] = v;
|
|
WeakAuras.Add(data);
|
|
if (options.extraSetFunction) then
|
|
options.extraSetFunction();
|
|
end
|
|
if (options.reloadOptions) then
|
|
OptionsPrivate.ClearOptions(data.id)
|
|
end
|
|
end,
|
|
get = function(info)
|
|
return GetCustomCode(data, path);
|
|
end
|
|
};
|
|
|
|
args[prefix .. "_customError"] = {
|
|
type = "description",
|
|
name = function()
|
|
if hiddenFunc() then
|
|
return "";
|
|
end
|
|
|
|
local code = GetCustomCode(data, path);
|
|
|
|
if (not code or code:trim() == "") then
|
|
return ""
|
|
end
|
|
|
|
if (encloseInFunction) then
|
|
code = "function() "..code.."\n end";
|
|
end
|
|
|
|
code = "return " .. code;
|
|
|
|
local loadedFunction, errorString = loadstring(code);
|
|
|
|
if not errorString then
|
|
if options.validator then
|
|
local ok, validate = xpcall(loadedFunction, function(err) errorString = err end)
|
|
if ok then
|
|
errorString = options.validator(validate)
|
|
end
|
|
end
|
|
end
|
|
return errorString and "|cFFFF0000"..errorString or "";
|
|
end,
|
|
width = WeakAuras.doubleWidth,
|
|
order = order + 0.002,
|
|
hidden = function()
|
|
if (hiddenFunc()) then
|
|
return true;
|
|
end
|
|
|
|
local code = GetCustomCode(data, path);
|
|
if (not code or code:trim() == "") then
|
|
return true;
|
|
end
|
|
|
|
if (encloseInFunction) then
|
|
code = "function() "..code.."\n end";
|
|
end
|
|
|
|
code = "return " .. code;
|
|
|
|
local loadedFunction, errorString = loadstring(code);
|
|
if(errorString and not loadedFunction) then
|
|
return false;
|
|
else
|
|
if options.validator then
|
|
local ok, validate = xpcall(loadedFunction, noop)
|
|
if ok then
|
|
return options.validator(validate)
|
|
end
|
|
return false
|
|
end
|
|
return true;
|
|
end
|
|
end
|
|
};
|
|
end
|
|
|
|
local function AddCommonTriggerOptions(options, data, triggernum, doubleWidth)
|
|
local trigger = data.triggers[triggernum].trigger
|
|
|
|
local trigger_types = {};
|
|
for type, triggerSystem in pairs(OptionsPrivate.Private.triggerTypes) do
|
|
trigger_types[type] = triggerSystem.GetName(type);
|
|
end
|
|
|
|
options.type = {
|
|
type = "select",
|
|
width = doubleWidth and WeakAuras.doubleWidth or WeakAuras.normalWidth,
|
|
name = L["Type"],
|
|
desc = L["The type of trigger"],
|
|
order = 1.1,
|
|
values = trigger_types,
|
|
get = function()
|
|
return trigger.type
|
|
end,
|
|
set = function(info, v)
|
|
trigger.type = v;
|
|
local prototype = trigger.event and OptionsPrivate.Private.event_prototypes[trigger.event];
|
|
if OptionsPrivate.Private.event_categories[v] and OptionsPrivate.Private.event_categories[v].default then
|
|
if not prototype or prototype.type ~= v then
|
|
trigger.event = OptionsPrivate.Private.event_categories[v].default
|
|
end
|
|
end
|
|
WeakAuras.Add(data);
|
|
WeakAuras.UpdateThumbnail(data);
|
|
WeakAuras.ClearAndUpdateOptions(data.id);
|
|
end,
|
|
control = "WeakAurasSortedDropdown"
|
|
}
|
|
end
|
|
|
|
-- Adds setters/getters to trigger options
|
|
-- This is used by both aura triggers
|
|
local function AddTriggerGetterSetter(options, data, triggernum)
|
|
local trigger = data.triggers[triggernum].trigger
|
|
for key, option in pairs(options) do
|
|
if type(option) == "table" and not option.get then
|
|
if option.type == "multiselect" then
|
|
option.get = function(info, index)
|
|
return trigger[key] and trigger[key][index]
|
|
end
|
|
else
|
|
option.get = function(info)
|
|
return trigger[key]
|
|
end
|
|
end
|
|
end
|
|
if type(option) == "table" and not option.set then
|
|
if option.type == "multiselect" then
|
|
option.set = function(info, index, value)
|
|
if type(trigger[key]) ~= "table" then
|
|
trigger[key] = {}
|
|
end
|
|
if value ~= nil then
|
|
if value then
|
|
trigger[key][index] = true
|
|
else
|
|
trigger[key][index] = nil
|
|
end
|
|
else
|
|
if trigger[key][index] then
|
|
trigger[key][index] = nil
|
|
else
|
|
trigger[key][index] = true
|
|
end
|
|
end
|
|
if next(trigger[key]) == nil then
|
|
trigger[key] = nil
|
|
end
|
|
|
|
WeakAuras.Add(data)
|
|
WeakAuras.ClearAndUpdateOptions(data.id)
|
|
end
|
|
else
|
|
option.set = function(info, v)
|
|
trigger[key] = v
|
|
WeakAuras.Add(data)
|
|
WeakAuras.ClearAndUpdateOptions(data.id)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
OptionsPrivate.commonOptions = {}
|
|
OptionsPrivate.commonOptions.parsePrefix = parsePrefix
|
|
OptionsPrivate.commonOptions.flattenRegionOptions = flattenRegionOptions
|
|
OptionsPrivate.commonOptions.fixMetaOrders = fixMetaOrders
|
|
OptionsPrivate.commonOptions.removeFuncs = removeFuncs
|
|
OptionsPrivate.commonOptions.CreateHiddenAll = CreateHiddenAll
|
|
OptionsPrivate.commonOptions.CreateDisabledAll = CreateDisabledAll
|
|
OptionsPrivate.commonOptions.replaceNameDescFuncs = replaceNameDescFuncs
|
|
OptionsPrivate.commonOptions.replaceImageFuncs = replaceImageFuncs
|
|
OptionsPrivate.commonOptions.replaceValuesFuncs = replaceValuesFuncs
|
|
OptionsPrivate.commonOptions.CreateGetAll = CreateGetAll
|
|
OptionsPrivate.commonOptions.CreateSetAll = CreateSetAll
|
|
OptionsPrivate.commonOptions.CreateExecuteAll = CreateExecuteAll
|
|
|
|
OptionsPrivate.commonOptions.PositionOptions = PositionOptions
|
|
OptionsPrivate.commonOptions.BorderOptions = BorderOptions
|
|
OptionsPrivate.commonOptions.AddCodeOption = AddCodeOption
|
|
|
|
OptionsPrivate.commonOptions.AddCommonTriggerOptions = AddCommonTriggerOptions
|
|
OptionsPrivate.commonOptions.AddTriggerGetterSetter = AddTriggerGetterSetter
|
|
|