Files
coa-weakauras/WeakAurasOptions/CommonOptions.lua
T
Bunny67 02c047002d beta
2020-09-16 23:03:25 +03:00

1470 lines
45 KiB
Lua

if not WeakAuras.IsCorrectVersion() then return end
local AddonName, OptionsPrivate = ...
local L = WeakAuras.L
local regionOptions = WeakAuras.regionOptions
local point_types = WeakAuras.point_types;
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 hiddenFunc = input.__hidden
local nooptions = input.__nooptions
local marginTop = input.__topLine
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,
}
options[key .. "collapseButton"] = {
type = "execute",
name = title,
order = order + 0.1,
width = titleWidth,
func = function(info, button, secondCall)
if not nooptions and not secondCall then
local isCollapsed = WeakAuras.IsCollapsed("collapse", "region", key, false)
WeakAuras.SetCollapsed("collapse", "region", key, not isCollapsed)
end
end,
image = function()
if nooptions then
return "Interface\\AddOns\\WeakAuras\\Media\\Textures\\bullet1", 18, 18
else
local isCollapsed = WeakAuras.IsCollapsed("collapse", "region", key, false)
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
if hiddenFunc then
return function()
return hiddenFunc() or WeakAuras.IsCollapsed("collapse", "region", key, false)
end
else
return function()
return WeakAuras.IsCollapsed("collapse", "region", key, false)
end
end
end
local function copyOptionTable(input, orderAdjustment, collapsedFunc)
local resultOption = {};
WeakAuras.DeepCopy(input, resultOption);
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 index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOptions = WeakAuras.EnsureOptions(childData, 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
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 index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOptions = WeakAuras.EnsureOptions(childData, 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
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 index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local values = getValueFor(WeakAuras.EnsureOptions(childData, 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
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 combinedValues = {};
local first = true;
local combinedKeys = combineKeys(info);
local isToggle = nil
for index, childId in ipairs(data.controlledChildren) do
if isToggle == nil then
local childData = WeakAuras.GetData(childId)
local childOption = getChildOption(WeakAuras.EnsureOptions(childData, subOption), info)
isToggle = childOption and childOption.type == "toggle"
end
local childData = WeakAuras.GetData(childId);
local regionType = regionPrefix(info[#info]);
if(childData and (not regionType or childData.regionType == regionType or regionType == "sub")) then
local childOptions = WeakAuras.EnsureOptions(childData, 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
return nil;
end
end
end
else
local values = {};
if (get) then
values = { get(info) };
local childOption = getChildOption(childOptions, 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
return nil;
end
end
end
end
end
return true;
end
local function nameAll(info)
local combinedName;
local first = true;
local foundNames = {};
for index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOption = getChildOption(WeakAuras.EnsureOptions(childData, subOption), info);
if (childOption) then
local name;
if(type(childOption.name) == "function") then
name = childOption.name(info);
else
name = childOption.name;
end
if (not name) then
-- Do nothing
elseif(first) then
if (combinedName ~= "") 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
end
return combinedName;
end
local function descAll(info)
local combinedDesc;
local first = true;
for index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOption = getChildOption(WeakAuras.EnsureOptions(childData, 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
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");
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 index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOptions = WeakAuras.EnsureOptions(childData, 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"..childId..": |r"..name);
elseif(tri) then
tinsert(values, "|cFFE0E000"..childId..": |r"..L["Ignored"]);
elseif(childOptionTable[i].get(info)) then
tinsert(values, "|cFFE0E000"..childId..": |r|cFF00FF00"..L["Enabled"]);
else
tinsert(values, "|cFFE0E000"..childId..": |r|cFFFF0000"..L["Disabled"]);
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"):format(r * 220 + 35, g * 220 + 35, b * 220 + 35, childId));
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"..childId..": |r" .. key);
else
tinsert(values, "|cFFE0E000"..childId..": |r"..display);
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"..childId..": |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"..childId..": |r"..display);
end
break;
end
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 index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOption = WeakAuras.EnsureOptions(childData, 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
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 index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOption = WeakAuras.EnsureOptions(childData, 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
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,
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 index, childId in ipairs(data.controlledChildren) do
if isToggle == nil then
local childData = WeakAuras.GetData(childId)
local childOptions = getChildOption(WeakAuras.EnsureOptions(childData, subOption), info)
isToggle = childOptions and childOptions.type == "toggle"
end
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOptions = WeakAuras.EnsureOptions(childData, 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].get) then
local values = {childOptionTable[i].get(info, ...)};
if isToggle and values[1] == nil then
values[1] = false
end
local sameAllChildren = allChildren:Set(values)
local sameEnabledChildren = enabledChildren:Set(values)
if not sameAllChildren and not sameEnabledChildren then
return nil;
end
break;
end
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, ...)
WeakAuras.pauseOptionsProcessing(true);
WeakAuras.PauseAllDynamicGroups()
local before = getAll(data, info, ...)
for index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOptions = WeakAuras.EnsureOptions(childData, 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
end
WeakAuras.ResumeAllDynamicGroups()
WeakAuras.pauseOptionsProcessing(false);
WeakAuras.ScanForLoads();
WeakAuras.SortDisplayButtons();
WeakAuras.UpdateOptions()
end
end
local function CreateExecuteAll(subOption)
return function(data, info, button)
local secondCall = nil
for index, childId in ipairs(data.controlledChildren) do
local childData = WeakAuras.GetData(childId);
if(childData) then
local childOptions = WeakAuras.EnsureOptions(childData, 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
end
WeakAuras.ClearAndUpdateOptions(data.id)
end
end
local function PositionOptions(id, data, _, hideWidthHeight, disableSelfPoint)
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 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,
bigStep = 1,
hidden = hideWidthHeight,
},
height = {
type = "range",
width = WeakAuras.normalWidth,
name = L["Height"],
order = 61,
min = 1,
softMax = screenHeight,
bigStep = 1,
hidden = hideWidthHeight,
},
xOffset = {
type = "range",
width = WeakAuras.normalWidth,
name = L["X Offset"],
order = 62,
softMin = (-1 * screenWidth),
softMax = screenWidth,
bigStep = 10,
get = function() return data.xOffset end,
set = function(info, v)
data.xOffset = v;
WeakAuras.Add(data);
WeakAuras.UpdateThumbnail(data);
WeakAuras.ResetMoverSizer();
if(data.parent) then
local parentData = WeakAuras.GetData(data.parent);
if(parentData) then
WeakAuras.Add(parentData);
end
end
end
},
yOffset = {
type = "range",
width = WeakAuras.normalWidth,
name = L["Y Offset"],
order = 63,
softMin = (-1 * screenHeight),
softMax = screenHeight,
bigStep = 10,
get = function() return data.yOffset end,
set = function(info, v)
data.yOffset = v;
WeakAuras.Add(data);
WeakAuras.UpdateThumbnail(data);
WeakAuras.ResetMoverSizer();
if(data.parent) then
local parentData = WeakAuras.GetData(data.parent);
if(parentData) then
WeakAuras.Add(parentData);
end
end
end
},
selfPoint = {
type = "select",
width = WeakAuras.normalWidth,
name = L["Anchor"],
order = 70,
hidden = IsParentDynamicGroup,
values = point_types,
disabled = disableSelfPoint,
},
anchorFrameType = {
type = "select",
width = WeakAuras.normalWidth,
name = L["Anchored To"],
order = 72,
hidden = IsParentDynamicGroup,
values = (data.regionType == "group" or data.regionType == "dynamicgroup") and WeakAuras.anchor_frame_types_group or WeakAuras.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()
WeakAuras.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 (IsParentDynamicGroup()) then
-- return true;
--end
return data.anchorFrameType == "SCREEN" or data.anchorFrameType == "MOUSE";
else
return data.anchorFrameType == "MOUSE";
end
end,
values = point_types
},
anchorPointGroup = {
type = "select",
width = WeakAuras.normalWidth,
name = L["To Group's"],
order = 76,
hidden = function()
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 = WeakAuras.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
},
};
WeakAuras.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"}, nil, nil, nil, nil, nil, true)
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 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
-- TODO: find a paradigm which doesn't have five million flags for AddCodeOption so that calls to it don't always go off the screen
-- a table of settings is the obvious option to pack the flags.
-- alternatively, we could create a "code" type option which then gets processed before sending to AceConfig
local function AddCodeOption(args, data, name, prefix, url, order, hiddenFunc, path, encloseInFunction, multipath, extraSetFunction, extraFunctions, reloadOptions, setOnParent)
extraFunctions = extraFunctions or {};
tinsert(extraFunctions, 1, {
buttonLabel = L["Expand"],
func = function(info)
WeakAuras.OpenTextEditor(WeakAuras.GetPickedDisplay(), path, encloseInFunction, multipath, reloadOptions, setOnParent, url)
end
});
args[prefix .. "_custom"] = {
type = "input",
width = WeakAuras.doubleWidth,
name = name,
order = order,
multiline = true,
hidden = hiddenFunc,
control = "WeakAurasMultiLineEditBox",
arg = {
extraFunctions = 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 (extraSetFunction) then
extraSetFunction();
end
if (reloadOptions) then
WeakAuras.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) then
return ""
end
if (encloseInFunction) then
code = "function() "..code.."\n end";
end
code = "return " .. code;
local _, errorString = loadstring(code);
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) 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
return true;
end
end
};
end
local function AddCommonTriggerOptions(options, data, triggernum)
local trigger = data.triggers[triggernum].trigger
local trigger_types = {};
for type, triggerSystem in pairs(WeakAuras.triggerTypes) do
trigger_types[type] = triggerSystem.GetName(type);
end
options.typedesc = {
type = "description",
width = WeakAuras.normalWidth,
name = L["Type"],
order = 1,
disabled = true,
get = function() return true end
}
options.type = {
type = "select",
width = WeakAuras.normalWidth,
name = L["Type"],
desc = L["The type of trigger"],
order = 1.1,
values = trigger_types,
get = function(info)
return trigger.type
end,
set = function(info, v)
trigger.type = v;
local prototype = trigger.event and WeakAuras.event_prototypes[trigger.event];
if v == "status" and (not prototype or prototype.type == "event") then
trigger.event = "Cooldown Progress (Spell)"
elseif v == "event" and (not prototype or prototype.type == "status") then
trigger.event = "Combat Log"
end
WeakAuras.Add(data);
WeakAuras.UpdateThumbnail(data);
WeakAuras.UpdateDisplayButton(data);
WeakAuras.ClearAndUpdateOptions(data.id);
end
}
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
WeakAuras.commonOptions = {}
WeakAuras.commonOptions.parsePrefix = parsePrefix
WeakAuras.commonOptions.flattenRegionOptions = flattenRegionOptions
WeakAuras.commonOptions.fixMetaOrders = fixMetaOrders
WeakAuras.commonOptions.removeFuncs = removeFuncs
WeakAuras.commonOptions.CreateHiddenAll = CreateHiddenAll
WeakAuras.commonOptions.CreateDisabledAll = CreateDisabledAll
WeakAuras.commonOptions.replaceNameDescFuncs = replaceNameDescFuncs
WeakAuras.commonOptions.replaceImageFuncs = replaceImageFuncs
WeakAuras.commonOptions.replaceValuesFuncs = replaceValuesFuncs
WeakAuras.commonOptions.CreateGetAll = CreateGetAll
WeakAuras.commonOptions.CreateSetAll = CreateSetAll
WeakAuras.commonOptions.CreateExecuteAll = CreateExecuteAll
WeakAuras.commonOptions.PositionOptions = PositionOptions
WeakAuras.commonOptions.BorderOptions = BorderOptions
WeakAuras.commonOptions.AddCodeOption = AddCodeOption
WeakAuras.commonOptions.AddCommonTriggerOptions = AddCommonTriggerOptions
WeakAuras.commonOptions.AddTriggerGetterSetter = AddTriggerGetterSetter