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.
1867 lines
54 KiB
1867 lines
54 KiB
|
5 years ago
|
if not WeakAuras.IsCorrectVersion() then return end
|
||
|
|
local AddonName, OptionsPrivate = ...
|
||
|
|
|
||
|
|
-- Lua APIs
|
||
|
|
local tinsert, tremove, wipe = table.insert, table.remove, wipe
|
||
|
|
local pairs, type, unpack = pairs, type, unpack
|
||
|
|
local loadstring, error = loadstring, error
|
||
|
|
local coroutine = coroutine
|
||
|
|
local _G = _G
|
||
|
|
|
||
|
|
-- WoW APIs
|
||
|
|
local InCombatLockdown = InCombatLockdown
|
||
|
|
local CreateFrame, IsAddOnLoaded, LoadAddOn = CreateFrame, IsAddOnLoaded, LoadAddOn
|
||
|
|
|
||
|
|
local AceGUI = LibStub("AceGUI-3.0")
|
||
|
|
|
||
|
|
local WeakAuras = WeakAuras
|
||
|
|
local L = WeakAuras.L
|
||
|
|
local ADDON_NAME = "WeakAurasOptions";
|
||
|
|
|
||
|
|
local displayButtons = {};
|
||
|
|
WeakAuras.displayButtons = displayButtons;
|
||
|
|
|
||
|
|
local spellCache = WeakAuras.spellCache;
|
||
|
|
local savedVars = {};
|
||
|
|
OptionsPrivate.savedVars = savedVars;
|
||
|
|
|
||
|
|
OptionsPrivate.expanderAnchors = {}
|
||
|
|
OptionsPrivate.expanderButtons = {}
|
||
|
|
|
||
|
|
local collapsedOptions = {}
|
||
|
|
local collapsed = {} -- magic value
|
||
|
|
|
||
|
|
local tempGroup = {
|
||
|
|
id = {"tempGroup"},
|
||
|
|
regionType = "group",
|
||
|
|
controlledChildren = {},
|
||
|
|
load = {},
|
||
|
|
triggers = {{}},
|
||
|
|
config = {},
|
||
|
|
authorOptions = {},
|
||
|
|
anchorPoint = "CENTER",
|
||
|
|
anchorFrameType = "SCREEN",
|
||
|
|
xOffset = 0,
|
||
|
|
yOffset = 0
|
||
|
|
};
|
||
|
|
OptionsPrivate.tempGroup = tempGroup;
|
||
|
|
|
||
|
|
function OptionsPrivate.DuplicateAura(data, newParent, massEdit)
|
||
|
|
local base_id = data.id .. " "
|
||
|
|
local num = 2
|
||
|
|
|
||
|
|
-- if the old id ends with a number increment the number
|
||
|
|
local matchName, matchNumber = string.match(data.id, "^(.-)(%d*)$")
|
||
|
|
matchNumber = tonumber(matchNumber)
|
||
|
|
if (matchName ~= "" and matchNumber ~= nil) then
|
||
|
|
base_id = matchName
|
||
|
|
num = matchNumber + 1
|
||
|
|
end
|
||
|
|
|
||
|
|
local new_id = base_id .. num
|
||
|
|
while(WeakAuras.GetData(new_id)) do
|
||
|
|
new_id = base_id .. num
|
||
|
|
num = num + 1
|
||
|
|
end
|
||
|
|
|
||
|
|
local newData = CopyTable(data)
|
||
|
|
newData.id = new_id
|
||
|
|
newData.parent = nil
|
||
|
|
newData.uid = WeakAuras.GenerateUniqueID()
|
||
|
|
if newData.controlledChildren then
|
||
|
|
newData.controlledChildren = {}
|
||
|
|
end
|
||
|
|
WeakAuras.Add(newData)
|
||
|
|
WeakAuras.NewDisplayButton(newData, massEdit)
|
||
|
|
if(newParent or data.parent) then
|
||
|
|
local parentId = newParent or data.parent
|
||
|
|
local parentData = WeakAuras.GetData(parentId)
|
||
|
|
local index
|
||
|
|
if newParent then
|
||
|
|
index = #parentData.controlledChildren
|
||
|
|
else
|
||
|
|
index = tIndexOf(parentData.controlledChildren, data.id)
|
||
|
|
end
|
||
|
|
if(index) then
|
||
|
|
tinsert(parentData.controlledChildren, index + 1, newData.id)
|
||
|
|
newData.parent = parentId
|
||
|
|
WeakAuras.Add(newData)
|
||
|
|
WeakAuras.Add(parentData)
|
||
|
|
OptionsPrivate.Private.AddParents(parentData)
|
||
|
|
|
||
|
|
for index, id in pairs(parentData.controlledChildren) do
|
||
|
|
local childButton = WeakAuras.GetDisplayButton(id)
|
||
|
|
childButton:SetGroup(parentData.id, parentData.regionType == "dynamicgroup")
|
||
|
|
childButton:SetGroupOrder(index, #parentData.controlledChildren)
|
||
|
|
end
|
||
|
|
|
||
|
|
if not massEdit then
|
||
|
|
local button = WeakAuras.GetDisplayButton(parentData.id)
|
||
|
|
button.callbacks.UpdateExpandButton()
|
||
|
|
WeakAuras.UpdateDisplayButton(parentData)
|
||
|
|
end
|
||
|
|
OptionsPrivate.ClearOptions(parentData.id)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return newData
|
||
|
|
end
|
||
|
|
|
||
|
|
AceGUI:RegisterLayout("AbsoluteList", function(content, children)
|
||
|
|
local yOffset = 0;
|
||
|
|
for i = 1, #children do
|
||
|
|
local child = children[i]
|
||
|
|
|
||
|
|
local frame = child.frame;
|
||
|
|
frame:ClearAllPoints();
|
||
|
|
frame:Show();
|
||
|
|
|
||
|
|
frame:SetPoint("LEFT", content);
|
||
|
|
frame:SetPoint("RIGHT", content);
|
||
|
|
frame:SetPoint("TOP", content, "TOP", 0, yOffset)
|
||
|
|
|
||
|
|
if child.DoLayout then
|
||
|
|
child:DoLayout()
|
||
|
|
end
|
||
|
|
|
||
|
|
yOffset = yOffset - ((frame.height or frame:GetHeight() or 0) + 2);
|
||
|
|
end
|
||
|
|
if(content.obj.LayoutFinished) then
|
||
|
|
content.obj:LayoutFinished(nil, yOffset * -1);
|
||
|
|
end
|
||
|
|
end);
|
||
|
|
|
||
|
|
AceGUI:RegisterLayout("ButtonsScrollLayout", function(content, children, skipLayoutFinished)
|
||
|
|
local yOffset = 0
|
||
|
|
local scrollTop, scrollBottom = content.obj:GetScrollPos()
|
||
|
|
for i = 1, #children do
|
||
|
|
local child = children[i]
|
||
|
|
local frame = child.frame;
|
||
|
|
|
||
|
|
if not child.dragging then
|
||
|
|
local frameHeight = (frame.height or frame:GetHeight() or 0);
|
||
|
|
frame:ClearAllPoints();
|
||
|
|
if (-yOffset + frameHeight > scrollTop and -yOffset - frameHeight < scrollBottom) then
|
||
|
|
frame:Show();
|
||
|
|
frame:SetPoint("LEFT", content);
|
||
|
|
frame:SetPoint("RIGHT", content);
|
||
|
|
frame:SetPoint("TOP", content, "TOP", 0, yOffset)
|
||
|
|
else
|
||
|
|
frame:Hide();
|
||
|
|
frame.yOffset = yOffset
|
||
|
|
end
|
||
|
|
yOffset = yOffset - (frameHeight + 2);
|
||
|
|
end
|
||
|
|
|
||
|
|
if child.DoLayout then
|
||
|
|
child:DoLayout()
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
if(content.obj.LayoutFinished and not skipLayoutFinished) then
|
||
|
|
content.obj:LayoutFinished(nil, yOffset * -1)
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
function OptionsPrivate.MultipleDisplayTooltipDesc()
|
||
|
|
local desc = {{L["Multiple Displays"], L["Temporary Group"]}};
|
||
|
|
for index, id in pairs(tempGroup.controlledChildren) do
|
||
|
|
desc[index + 1] = {" ", id};
|
||
|
|
end
|
||
|
|
desc[2][1] = L["Children:"]
|
||
|
|
tinsert(desc, " ");
|
||
|
|
tinsert(desc, {" ", "|cFF00FFFF"..L["Right-click for more options"]});
|
||
|
|
tinsert(desc, {" ", "|cFF00FFFF"..L["Drag to move"]});
|
||
|
|
return desc;
|
||
|
|
end
|
||
|
|
|
||
|
|
local frame;
|
||
|
|
local db;
|
||
|
|
local odb;
|
||
|
|
local reopenAfterCombat = false;
|
||
|
|
local loadedFrame = CreateFrame("FRAME");
|
||
|
|
loadedFrame:RegisterEvent("ADDON_LOADED");
|
||
|
|
loadedFrame:RegisterEvent("PLAYER_REGEN_ENABLED");
|
||
|
|
loadedFrame:RegisterEvent("PLAYER_REGEN_DISABLED");
|
||
|
|
loadedFrame:SetScript("OnEvent", function(self, event, addon)
|
||
|
|
if (event == "ADDON_LOADED") then
|
||
|
|
if(addon == ADDON_NAME) then
|
||
|
|
db = WeakAurasSaved;
|
||
|
|
WeakAurasOptionsSaved = WeakAurasOptionsSaved or {};
|
||
|
|
|
||
|
|
odb = WeakAurasOptionsSaved;
|
||
|
|
|
||
|
|
-- Remove icon and id cache (replaced with spellCache)
|
||
|
|
if (odb.iconCache) then
|
||
|
|
odb.iconCache = nil;
|
||
|
|
end
|
||
|
|
if (odb.idCache) then
|
||
|
|
odb.idCache = nil;
|
||
|
|
end
|
||
|
|
odb.spellCache = odb.spellCache or {};
|
||
|
|
spellCache.Load(odb);
|
||
|
|
|
||
|
|
if odb.magnetAlign == nil then
|
||
|
|
odb.magnetAlign = true
|
||
|
|
end
|
||
|
|
|
||
|
|
if db.import_disabled then
|
||
|
|
db.import_disabled = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
savedVars.db = db;
|
||
|
|
savedVars.odb = odb;
|
||
|
|
end
|
||
|
|
elseif (event == "PLAYER_REGEN_DISABLED") then
|
||
|
|
if(frame and frame:IsVisible()) then
|
||
|
|
reopenAfterCombat = true;
|
||
|
|
WeakAuras.HideOptions();
|
||
|
|
end
|
||
|
|
elseif (event == "PLAYER_REGEN_ENABLED") then
|
||
|
|
if (reopenAfterCombat) then
|
||
|
|
reopenAfterCombat = nil;
|
||
|
|
WeakAuras.ShowOptions()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end);
|
||
|
|
|
||
|
|
local function addParents(hash, data)
|
||
|
|
local parent = data.parent
|
||
|
|
if parent then
|
||
|
|
hash[parent] = true
|
||
|
|
local parentData = WeakAuras.GetData(parent)
|
||
|
|
if parentData then
|
||
|
|
addParents(hash, parentData)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.MultipleDisplayTooltipMenu()
|
||
|
|
local frame = frame;
|
||
|
|
local menu = {
|
||
|
|
{
|
||
|
|
text = L["Add to new Group"],
|
||
|
|
notCheckable = 1,
|
||
|
|
func = function()
|
||
|
|
local data = {
|
||
|
|
id = WeakAuras.FindUnusedId(tempGroup.controlledChildren[1].." Group"),
|
||
|
|
regionType = "group",
|
||
|
|
};
|
||
|
|
|
||
|
|
WeakAuras.DeepMixin(data, WeakAuras.data_stub)
|
||
|
|
data.internalVersion = WeakAuras.InternalVersion()
|
||
|
|
WeakAuras.Add(data);
|
||
|
|
WeakAuras.NewDisplayButton(data);
|
||
|
|
|
||
|
|
for index, childId in pairs(tempGroup.controlledChildren) do
|
||
|
|
local childData = WeakAuras.GetData(childId);
|
||
|
|
tinsert(data.controlledChildren, childId);
|
||
|
|
childData.parent = data.id;
|
||
|
|
WeakAuras.Add(data);
|
||
|
|
WeakAuras.Add(childData);
|
||
|
|
OptionsPrivate.ClearOptions(childData.id)
|
||
|
|
end
|
||
|
|
|
||
|
|
for index, id in pairs(data.controlledChildren) do
|
||
|
|
local childButton = WeakAuras.GetDisplayButton(id);
|
||
|
|
childButton:SetGroup(data.id, data.regionType == "dynamicgroup");
|
||
|
|
childButton:SetGroupOrder(index, #data.controlledChildren);
|
||
|
|
end
|
||
|
|
|
||
|
|
local button = WeakAuras.GetDisplayButton(data.id);
|
||
|
|
button.callbacks.UpdateExpandButton();
|
||
|
|
WeakAuras.UpdateDisplayButton(data);
|
||
|
|
OptionsPrivate.SortDisplayButtons();
|
||
|
|
button:Expand();
|
||
|
|
end
|
||
|
|
},
|
||
|
|
{
|
||
|
|
text = L["Add to new Dynamic Group"],
|
||
|
|
notCheckable = 1,
|
||
|
|
func = function()
|
||
|
|
local data = {
|
||
|
|
id = WeakAuras.FindUnusedId(tempGroup.controlledChildren[1].." Group"),
|
||
|
|
regionType = "dynamicgroup",
|
||
|
|
};
|
||
|
|
|
||
|
|
WeakAuras.DeepMixin(data, WeakAuras.data_stub)
|
||
|
|
data.internalVersion = WeakAuras.InternalVersion()
|
||
|
|
WeakAuras.Add(data);
|
||
|
|
WeakAuras.NewDisplayButton(data);
|
||
|
|
|
||
|
|
for index, childId in pairs(tempGroup.controlledChildren) do
|
||
|
|
local childData = WeakAuras.GetData(childId);
|
||
|
|
tinsert(data.controlledChildren, childId);
|
||
|
|
childData.parent = data.id;
|
||
|
|
childData.xOffset = 0;
|
||
|
|
childData.yOffset = 0;
|
||
|
|
WeakAuras.Add(data);
|
||
|
|
WeakAuras.Add(childData);
|
||
|
|
end
|
||
|
|
|
||
|
|
for index, id in pairs(data.controlledChildren) do
|
||
|
|
local childButton = WeakAuras.GetDisplayButton(id);
|
||
|
|
childButton:SetGroup(data.id, data.regionType == "dynamicgroup");
|
||
|
|
childButton:SetGroupOrder(index, #data.controlledChildren);
|
||
|
|
end
|
||
|
|
|
||
|
|
local button = WeakAuras.GetDisplayButton(data.id);
|
||
|
|
button.callbacks.UpdateExpandButton();
|
||
|
|
WeakAuras.UpdateDisplayButton(data);
|
||
|
|
OptionsPrivate.SortDisplayButtons();
|
||
|
|
button:Expand();
|
||
|
|
WeakAuras.PickDisplay(data.id);
|
||
|
|
end
|
||
|
|
},
|
||
|
|
{
|
||
|
|
text = L["Duplicate All"],
|
||
|
|
notCheckable = 1,
|
||
|
|
func = function()
|
||
|
|
local duplicated = {};
|
||
|
|
for child in OptionsPrivate.Private.TraverseAllChildren(tempGroup) do
|
||
|
|
local newData = OptionsPrivate.DuplicateAura(child)
|
||
|
|
tinsert(duplicated, newData.id);
|
||
|
|
end
|
||
|
|
|
||
|
|
OptionsPrivate.ClearPicks();
|
||
|
|
frame:PickDisplayBatch(duplicated);
|
||
|
|
end
|
||
|
|
},
|
||
|
|
{
|
||
|
|
text = " ",
|
||
|
|
notCheckable = 1,
|
||
|
|
notClickable = 1
|
||
|
|
},
|
||
|
|
{
|
||
|
|
text = L["Delete all"],
|
||
|
|
notCheckable = 1,
|
||
|
|
func = function()
|
||
|
|
local toDelete = {};
|
||
|
|
local parents = {};
|
||
|
|
for child in OptionsPrivate.Private.TraverseAllChildren(tempGroup) do
|
||
|
|
tinsert(toDelete, child)
|
||
|
|
addParents(parents, child)
|
||
|
|
end
|
||
|
|
OptionsPrivate.ConfirmDelete(toDelete, parents)
|
||
|
|
end
|
||
|
|
},
|
||
|
|
{
|
||
|
|
text = " ",
|
||
|
|
notClickable = 1,
|
||
|
|
notCheckable = 1,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
text = L["Close"],
|
||
|
|
notCheckable = 1,
|
||
|
|
func = function() WeakAuras_DropDownMenu:Hide() end
|
||
|
|
}
|
||
|
|
};
|
||
|
|
local anyGrouped = false;
|
||
|
|
for index, id in pairs(tempGroup.controlledChildren) do
|
||
|
|
local childData = WeakAuras.GetData(id);
|
||
|
|
if(childData and childData.parent) then
|
||
|
|
anyGrouped = true;
|
||
|
|
break;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if(anyGrouped) then
|
||
|
|
menu[1].notClickable = 1;
|
||
|
|
menu[1].text = "|cFF777777"..menu[1].text;
|
||
|
|
menu[2].notClickable = 1;
|
||
|
|
menu[2].text = "|cFF777777"..menu[2].text;
|
||
|
|
end
|
||
|
|
return menu;
|
||
|
|
end
|
||
|
|
|
||
|
|
StaticPopupDialogs["WEAKAURAS_CONFIRM_DELETE"] = {
|
||
|
|
text = "",
|
||
|
|
button1 = L["Delete"],
|
||
|
|
button2 = L["Cancel"],
|
||
|
|
OnAccept = function(self)
|
||
|
|
if self.data then
|
||
|
|
OptionsPrivate.Private.PauseAllDynamicGroups()
|
||
|
|
OptionsPrivate.massDelete = true
|
||
|
|
for _, auraData in pairs(self.data.toDelete) do
|
||
|
|
WeakAuras.Delete(auraData)
|
||
|
|
end
|
||
|
|
OptionsPrivate.massDelete = false
|
||
|
|
|
||
|
|
if self.data.parents then
|
||
|
|
for id in pairs(self.data.parents) do
|
||
|
|
local parentData = WeakAuras.GetData(id)
|
||
|
|
local parentButton = WeakAuras.GetDisplayButton(id)
|
||
|
|
WeakAuras.UpdateGroupOrders(parentData)
|
||
|
|
if(#parentData.controlledChildren == 0) then
|
||
|
|
parentButton:DisableExpand()
|
||
|
|
else
|
||
|
|
parentButton:EnableExpand()
|
||
|
|
end
|
||
|
|
parentButton:SetNormalTooltip()
|
||
|
|
WeakAuras.Add(parentData)
|
||
|
|
WeakAuras.ClearAndUpdateOptions(parentData.id)
|
||
|
|
WeakAuras.UpdateDisplayButton(parentData)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
OptionsPrivate.Private.ResumeAllDynamicGroups()
|
||
|
|
OptionsPrivate.SortDisplayButtons(nil, true)
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
OnCancel = function(self)
|
||
|
|
if self.data.parents then
|
||
|
|
for id in pairs(self.data.parents) do
|
||
|
|
local parentRegion = WeakAuras.GetRegion(id)
|
||
|
|
if parentRegion.Resume then
|
||
|
|
parentRegion:Resume()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
self.data = nil
|
||
|
|
end,
|
||
|
|
showAlert = true,
|
||
|
|
whileDead = true,
|
||
|
|
preferredindex = STATICPOPUP_NUMDIALOGS,
|
||
|
|
}
|
||
|
|
|
||
|
|
StaticPopupDialogs["WEAKAURAS_CONFIRM_IGNORE_UPDATES"] = {
|
||
|
|
text = L["Do you want to ignore all future updates for this aura"],
|
||
|
|
button1 = L["Yes"],
|
||
|
|
button2 = L["Cancel"],
|
||
|
|
OnAccept = function(self)
|
||
|
|
if self.data then
|
||
|
|
local auraData = WeakAuras.GetData(self.data)
|
||
|
|
if auraData then
|
||
|
|
for child in OptionsPrivate.Private.TraverseAll(auraData) do
|
||
|
|
child.ignoreWagoUpdate = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
OptionsPrivate.SortDisplayButtons(nil, true)
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
OnCancel = function(self) end,
|
||
|
|
whileDead = true,
|
||
|
|
preferredindex = STATICPOPUP_NUMDIALOGS,
|
||
|
|
}
|
||
|
|
|
||
|
|
function OptionsPrivate.ConfirmDelete(toDelete, parents)
|
||
|
|
if toDelete then
|
||
|
|
local warningForm = L["You are about to delete %d aura(s). |cFFFF0000This cannot be undone!|r Would you like to continue?"]
|
||
|
|
StaticPopupDialogs["WEAKAURAS_CONFIRM_DELETE"].text = warningForm:format(#toDelete)
|
||
|
|
StaticPopup_Show("WEAKAURAS_CONFIRM_DELETE", "", "", {toDelete = toDelete, parents = parents})
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.OptionsFrame()
|
||
|
|
if(frame) then
|
||
|
|
return frame;
|
||
|
|
else
|
||
|
|
return nil;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function AfterScanForLoads()
|
||
|
|
if(frame) then
|
||
|
|
if (frame:IsVisible()) then
|
||
|
|
OptionsPrivate.SortDisplayButtons(nil, true);
|
||
|
|
else
|
||
|
|
frame.needsSort = true;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function OnAboutToDelete(event, uid, id, parentUid, parentId)
|
||
|
|
local data = OptionsPrivate.Private.GetDataByUID(uid)
|
||
|
|
if(data.controlledChildren) then
|
||
|
|
for index, childId in pairs(data.controlledChildren) do
|
||
|
|
local childButton = displayButtons[childId];
|
||
|
|
if(childButton) then
|
||
|
|
childButton:SetGroup();
|
||
|
|
end
|
||
|
|
local childData = db.displays[childId];
|
||
|
|
if(childData) then
|
||
|
|
childData.parent = nil;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
OptionsPrivate.Private.CollapseAllClones(id);
|
||
|
|
OptionsPrivate.ClearOptions(id)
|
||
|
|
|
||
|
|
frame:ClearPicks();
|
||
|
|
|
||
|
|
if(displayButtons[id])then
|
||
|
|
frame.buttonsScroll:DeleteChild(displayButtons[id]);
|
||
|
|
displayButtons[id] = nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
collapsedOptions[id] = nil
|
||
|
|
end
|
||
|
|
|
||
|
|
local function OnDelete(event, uid, id, parentUid, parentId)
|
||
|
|
local parentData = OptionsPrivate.Private.GetDataByUID(parentUid)
|
||
|
|
if(parentData and parentData.controlledChildren and not OptionsPrivate.massDelete) then
|
||
|
|
for index, childId in pairs(parentData.controlledChildren) do
|
||
|
|
local childButton = displayButtons[childId];
|
||
|
|
if(childButton) then
|
||
|
|
childButton:SetGroupOrder(index, #parentData.controlledChildren)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
WeakAuras.ClearAndUpdateOptions(parentData.id)
|
||
|
|
WeakAuras.UpdateDisplayButton(parentData)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function OnRename(event, uid, oldid, newid)
|
||
|
|
local data = OptionsPrivate.Private.GetDataByUID(uid)
|
||
|
|
|
||
|
|
WeakAuras.displayButtons[newid] = WeakAuras.displayButtons[oldid];
|
||
|
|
WeakAuras.displayButtons[newid]:SetData(data)
|
||
|
|
WeakAuras.displayButtons[oldid] = nil;
|
||
|
|
OptionsPrivate.ClearOptions(oldid)
|
||
|
|
|
||
|
|
WeakAuras.displayButtons[newid]:SetTitle(newid);
|
||
|
|
|
||
|
|
collapsedOptions[newid] = collapsedOptions[oldid]
|
||
|
|
collapsedOptions[oldid] = nil
|
||
|
|
|
||
|
|
if(data.controlledChildren) then
|
||
|
|
for index, childId in pairs(data.controlledChildren) do
|
||
|
|
WeakAuras.displayButtons[childId]:SetGroup(newid)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
OptionsPrivate.SetGrouping()
|
||
|
|
OptionsPrivate.SortDisplayButtons()
|
||
|
|
WeakAuras.PickDisplay(newid)
|
||
|
|
|
||
|
|
local parent = data.parent
|
||
|
|
while parent do
|
||
|
|
OptionsPrivate.ClearOptions(parent)
|
||
|
|
local parentData = WeakAuras.GetData(parent)
|
||
|
|
parent = parentData.parent
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.ToggleOptions(msg, Private)
|
||
|
|
if not Private then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
if not OptionsPrivate.Private then
|
||
|
|
OptionsPrivate.Private = Private
|
||
|
|
OptionsPrivate.Private:RegisterCallback("AuraWarningsUpdated", function(event, uid)
|
||
|
|
local id = OptionsPrivate.Private.UIDtoID(uid)
|
||
|
|
if displayButtons[id] then
|
||
|
|
-- The button does not yet exists if a new aura is created
|
||
|
|
displayButtons[id]:UpdateWarning()
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
OptionsPrivate.Private:RegisterCallback("ScanForLoads", AfterScanForLoads)
|
||
|
|
OptionsPrivate.Private:RegisterCallback("AboutToDelete", OnAboutToDelete)
|
||
|
|
OptionsPrivate.Private:RegisterCallback("Rename", OnRename)
|
||
|
|
end
|
||
|
|
|
||
|
|
if(frame and frame:IsVisible()) then
|
||
|
|
WeakAuras.HideOptions();
|
||
|
|
elseif (InCombatLockdown()) then
|
||
|
|
WeakAuras.prettyPrint(L["Options will open after combat ends."])
|
||
|
|
reopenAfterCombat = true;
|
||
|
|
else
|
||
|
|
WeakAuras.ShowOptions(msg);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.HideOptions()
|
||
|
|
if(frame) then
|
||
|
|
frame:Hide()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.IsOptionsOpen()
|
||
|
|
if(frame and frame:IsVisible()) then
|
||
|
|
return true;
|
||
|
|
else
|
||
|
|
return false;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function EnsureDisplayButton(data)
|
||
|
|
local id = data.id;
|
||
|
|
if not(displayButtons[id]) then
|
||
|
|
displayButtons[id] = AceGUI:Create("WeakAurasDisplayButton");
|
||
|
|
if(displayButtons[id]) then
|
||
|
|
displayButtons[id]:SetData(data);
|
||
|
|
displayButtons[id]:Initialize();
|
||
|
|
displayButtons[id]:UpdateWarning()
|
||
|
|
else
|
||
|
|
print("|cFF8800FFWeakAuras|r: Error creating button for", id);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function GetSortedOptionsLists()
|
||
|
|
local loadedSorted, unloadedSorted = {}, {};
|
||
|
|
local to_sort = {};
|
||
|
|
for id, data in pairs(db.displays) do
|
||
|
|
if(data.parent) then
|
||
|
|
-- Do nothing; children will be added later
|
||
|
|
elseif(OptionsPrivate.Private.loaded[id]) then
|
||
|
|
tinsert(to_sort, id);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
table.sort(to_sort, function(a, b) return a < b end);
|
||
|
|
for _, id in ipairs(to_sort) do
|
||
|
|
local data = WeakAuras.GetData(id);
|
||
|
|
for child in OptionsPrivate.Private.TraverseAll(data) do
|
||
|
|
tinsert(loadedSorted, child.id)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
wipe(to_sort);
|
||
|
|
for id, data in pairs(db.displays) do
|
||
|
|
if(data.parent) then
|
||
|
|
-- Do nothing; children will be added later
|
||
|
|
elseif not(OptionsPrivate.Private.loaded[id]) then
|
||
|
|
tinsert(to_sort, id);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
table.sort(to_sort, function(a, b) return a < b end);
|
||
|
|
for _, id in ipairs(to_sort) do
|
||
|
|
local data = WeakAuras.GetData(id);
|
||
|
|
for child in OptionsPrivate.Private.TraverseAll(data) do
|
||
|
|
tinsert(unloadedSorted, child.id)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return loadedSorted, unloadedSorted;
|
||
|
|
end
|
||
|
|
|
||
|
|
local function LayoutDisplayButtons(msg)
|
||
|
|
local total = 0;
|
||
|
|
for _,_ in pairs(db.displays) do
|
||
|
|
total = total + 1;
|
||
|
|
end
|
||
|
|
|
||
|
|
local loadedSorted, unloadedSorted = GetSortedOptionsLists();
|
||
|
|
|
||
|
|
frame:SetLoadProgressVisible(true)
|
||
|
|
--frame.buttonsScroll:AddChild(frame.newButton);
|
||
|
|
--if(frame.addonsButton) then
|
||
|
|
-- frame.buttonsScroll:AddChild(frame.addonsButton);
|
||
|
|
--end
|
||
|
|
if WeakAurasCompanion then
|
||
|
|
frame.buttonsScroll:AddChild(frame.pendingInstallButton);
|
||
|
|
frame.buttonsScroll:AddChild(frame.pendingUpdateButton);
|
||
|
|
end
|
||
|
|
frame.buttonsScroll:AddChild(frame.loadedButton);
|
||
|
|
frame.buttonsScroll:AddChild(frame.unloadedButton);
|
||
|
|
|
||
|
|
local func2 = function()
|
||
|
|
local num = frame.loadProgressNum or 0;
|
||
|
|
for index, id in pairs(unloadedSorted) do
|
||
|
|
local data = WeakAuras.GetData(id);
|
||
|
|
if(data) then
|
||
|
|
EnsureDisplayButton(data);
|
||
|
|
WeakAuras.UpdateDisplayButton(data);
|
||
|
|
|
||
|
|
frame.buttonsScroll:AddChild(displayButtons[data.id]);
|
||
|
|
|
||
|
|
if (num % 50 == 0) then
|
||
|
|
frame.buttonsScroll:ResumeLayout()
|
||
|
|
frame.buttonsScroll:PerformLayout()
|
||
|
|
frame.buttonsScroll:PauseLayout()
|
||
|
|
end
|
||
|
|
|
||
|
|
num = num + 1;
|
||
|
|
end
|
||
|
|
frame.loadProgress:SetText(L["Creating buttons: "]..num.."/"..total);
|
||
|
|
frame.loadProgressNum = num;
|
||
|
|
coroutine.yield();
|
||
|
|
end
|
||
|
|
|
||
|
|
frame.buttonsScroll:ResumeLayout()
|
||
|
|
frame.buttonsScroll:PerformLayout()
|
||
|
|
OptionsPrivate.SortDisplayButtons(msg);
|
||
|
|
|
||
|
|
OptionsPrivate.Private.PauseAllDynamicGroups();
|
||
|
|
if (WeakAuras.IsOptionsOpen()) then
|
||
|
|
for id, button in pairs(displayButtons) do
|
||
|
|
if(OptionsPrivate.Private.loaded[id] ~= nil) then
|
||
|
|
button:PriorityShow(1);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
OptionsPrivate.Private.ResumeAllDynamicGroups();
|
||
|
|
|
||
|
|
frame:SetLoadProgressVisible(false)
|
||
|
|
end
|
||
|
|
|
||
|
|
local func1 = function()
|
||
|
|
local num = frame.loadProgressNum or 0;
|
||
|
|
frame.buttonsScroll:PauseLayout()
|
||
|
|
for index, id in pairs(loadedSorted) do
|
||
|
|
local data = WeakAuras.GetData(id);
|
||
|
|
if(data) then
|
||
|
|
EnsureDisplayButton(data);
|
||
|
|
WeakAuras.UpdateDisplayButton(data);
|
||
|
|
|
||
|
|
local button = displayButtons[data.id]
|
||
|
|
frame.buttonsScroll:AddChild(button);
|
||
|
|
num = num + 1;
|
||
|
|
end
|
||
|
|
|
||
|
|
if (num % 50 == 0) then
|
||
|
|
frame.buttonsScroll:ResumeLayout()
|
||
|
|
frame.buttonsScroll:PerformLayout()
|
||
|
|
frame.buttonsScroll:PauseLayout()
|
||
|
|
end
|
||
|
|
|
||
|
|
frame.loadProgress:SetText(L["Creating buttons: "]..num.."/"..total);
|
||
|
|
frame.loadProgressNum = num;
|
||
|
|
coroutine.yield();
|
||
|
|
end
|
||
|
|
|
||
|
|
local co2 = coroutine.create(func2);
|
||
|
|
OptionsPrivate.Private.dynFrame:AddAction("LayoutDisplayButtons2", co2);
|
||
|
|
end
|
||
|
|
|
||
|
|
local co1 = coroutine.create(func1);
|
||
|
|
OptionsPrivate.Private.dynFrame:AddAction("LayoutDisplayButtons1", co1);
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.ShowOptions(msg)
|
||
|
|
local firstLoad = not(frame);
|
||
|
|
OptionsPrivate.Private.Pause();
|
||
|
|
OptionsPrivate.Private.SetFakeStates()
|
||
|
|
|
||
|
|
WeakAuras.spellCache.Build()
|
||
|
|
|
||
|
|
if (firstLoad) then
|
||
|
|
frame = OptionsPrivate.CreateFrame();
|
||
|
|
frame.buttonsScroll.frame:Show();
|
||
|
|
|
||
|
|
LayoutDisplayButtons(msg);
|
||
|
|
end
|
||
|
|
|
||
|
|
if (frame:GetWidth() > GetScreenWidth()) then
|
||
|
|
frame:SetWidth(GetScreenWidth())
|
||
|
|
end
|
||
|
|
|
||
|
|
if (frame:GetHeight() > GetScreenHeight() - 50) then
|
||
|
|
frame:SetHeight(GetScreenHeight() - 50)
|
||
|
|
end
|
||
|
|
|
||
|
|
frame.buttonsScroll.frame:Show();
|
||
|
|
|
||
|
|
if (frame.needsSort) then
|
||
|
|
OptionsPrivate.SortDisplayButtons();
|
||
|
|
frame.needsSort = nil;
|
||
|
|
end
|
||
|
|
|
||
|
|
frame:Show();
|
||
|
|
|
||
|
|
if (OptionsPrivate.Private.mouseFrame) then
|
||
|
|
OptionsPrivate.Private.mouseFrame:OptionsOpened();
|
||
|
|
end
|
||
|
|
|
||
|
|
if (OptionsPrivate.Private.personalRessourceDisplayFrame) then
|
||
|
|
OptionsPrivate.Private.personalRessourceDisplayFrame:OptionsOpened();
|
||
|
|
end
|
||
|
|
|
||
|
|
if not(firstLoad) then
|
||
|
|
-- Show what was last shown
|
||
|
|
OptionsPrivate.Private.PauseAllDynamicGroups();
|
||
|
|
for id, button in pairs(displayButtons) do
|
||
|
|
if (button:GetVisibility() > 0) then
|
||
|
|
button:PriorityShow(button:GetVisibility());
|
||
|
|
end
|
||
|
|
end
|
||
|
|
OptionsPrivate.Private.ResumeAllDynamicGroups();
|
||
|
|
end
|
||
|
|
|
||
|
|
if (frame.pickedDisplay) then
|
||
|
|
if (OptionsPrivate.IsPickedMultiple()) then
|
||
|
|
local children = {}
|
||
|
|
for k,v in pairs(tempGroup.controlledChildren) do
|
||
|
|
children[k] = v
|
||
|
|
end
|
||
|
|
frame:PickDisplayBatch(children);
|
||
|
|
else
|
||
|
|
WeakAuras.PickDisplay(frame.pickedDisplay);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
frame:NewAura();
|
||
|
|
end
|
||
|
|
|
||
|
|
if (frame.window == "codereview") then
|
||
|
|
frame.codereview:Close();
|
||
|
|
end
|
||
|
|
|
||
|
|
if firstLoad then
|
||
|
|
frame:ShowTip()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.UpdateOptions()
|
||
|
|
frame:UpdateOptions()
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.ClearAndUpdateOptions(id, clearChildren)
|
||
|
|
frame:ClearAndUpdateOptions(id, clearChildren)
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.ClearOptions(id)
|
||
|
|
frame:ClearOptions(id)
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.FillOptions()
|
||
|
|
frame:FillOptions()
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.EnsureOptions(data, subOption)
|
||
|
|
return frame:EnsureOptions(data, subOption)
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.GetPickedDisplay()
|
||
|
|
return frame:GetPickedDisplay()
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.OpenTextEditor(...)
|
||
|
|
frame.texteditor:Open(...);
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.ExportToString(id)
|
||
|
|
frame.importexport:Open("export", id);
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.ExportToTable(id)
|
||
|
|
frame.importexport:Open("table", id);
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.ImportFromString()
|
||
|
|
frame.importexport:Open("import");
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.CloseImportExport()
|
||
|
|
frame.codereview:Close();
|
||
|
|
frame.importexport:Close();
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.ConvertDisplay(data, newType)
|
||
|
|
local id = data.id;
|
||
|
|
local visibility = displayButtons[id]:GetVisibility();
|
||
|
|
displayButtons[id]:PriorityHide(0);
|
||
|
|
|
||
|
|
WeakAuras.regions[id].region:Collapse();
|
||
|
|
OptionsPrivate.Private.CollapseAllClones(id);
|
||
|
|
|
||
|
|
OptionsPrivate.Private.Convert(data, newType);
|
||
|
|
displayButtons[id]:SetViewRegion(WeakAuras.regions[id].region);
|
||
|
|
displayButtons[id]:Initialize();
|
||
|
|
displayButtons[id]:PriorityShow(visibility);
|
||
|
|
frame:ClearOptions(id)
|
||
|
|
frame:FillOptions();
|
||
|
|
WeakAuras.UpdateDisplayButton(data);
|
||
|
|
WeakAuras.SetMoverSizer(id)
|
||
|
|
OptionsPrivate.ResetMoverSizer();
|
||
|
|
OptionsPrivate.SortDisplayButtons()
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.NewDisplayButton(data, massEdit)
|
||
|
|
local id = data.id;
|
||
|
|
OptionsPrivate.Private.ScanForLoads({[id] = true});
|
||
|
|
EnsureDisplayButton(db.displays[id]);
|
||
|
|
WeakAuras.UpdateDisplayButton(db.displays[id]);
|
||
|
|
frame.buttonsScroll:AddChild(displayButtons[id]);
|
||
|
|
if not massEdit then
|
||
|
|
OptionsPrivate.SortDisplayButtons()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.UpdateGroupOrders(data)
|
||
|
|
if(data.controlledChildren) then
|
||
|
|
local total = #data.controlledChildren;
|
||
|
|
for index, id in pairs(data.controlledChildren) do
|
||
|
|
local button = WeakAuras.GetDisplayButton(id);
|
||
|
|
button:SetGroupOrder(index, total);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.UpdateButtonsScroll()
|
||
|
|
if OptionsPrivate.Private.IsOptionsProcessingPaused() then return end
|
||
|
|
frame.buttonsScroll:DoLayout()
|
||
|
|
end
|
||
|
|
|
||
|
|
local function addChildButtons(button, children, visible)
|
||
|
|
local controlledChildren = children[button:GetTitle()];
|
||
|
|
if(controlledChildren) then
|
||
|
|
table.sort(controlledChildren, function(a, b) return displayButtons[a]:GetGroupOrder() < displayButtons[b]:GetGroupOrder(); end);
|
||
|
|
for _, groupchild in ipairs(controlledChildren) do
|
||
|
|
if(button:GetExpanded()) then
|
||
|
|
displayButtons[groupchild].frame:Show();
|
||
|
|
if displayButtons[groupchild].AcquireThumbnail then
|
||
|
|
displayButtons[groupchild]:AcquireThumbnail()
|
||
|
|
end
|
||
|
|
tinsert(frame.buttonsScroll.children, displayButtons[groupchild]);
|
||
|
|
visible[displayButtons[groupchild]] = true
|
||
|
|
|
||
|
|
addChildButtons(displayButtons[groupchild], children, visible)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function anyParentLoaded(parentId)
|
||
|
|
if(parentId) then
|
||
|
|
if(OptionsPrivate.Private.loaded[parentId]) then
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
local parentData = WeakAuras.GetData(parentId)
|
||
|
|
if parentData then
|
||
|
|
return anyParentLoaded(parentData.parent)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
local previousFilter;
|
||
|
|
local pendingUpdateButtons = {}
|
||
|
|
local pendingInstallButtons = {}
|
||
|
|
function OptionsPrivate.SortDisplayButtons(filter, overrideReset, id)
|
||
|
|
if (OptionsPrivate.Private.IsOptionsProcessingPaused()) then
|
||
|
|
return;
|
||
|
|
end
|
||
|
|
|
||
|
|
local recenter = false;
|
||
|
|
filter = filter or (overrideReset and previousFilter or "");
|
||
|
|
if(frame.filterInput:GetText() ~= filter) then
|
||
|
|
frame.filterInput:SetText(filter);
|
||
|
|
end
|
||
|
|
if(previousFilter and previousFilter ~= "" and (filter == "" or not filter)) then
|
||
|
|
recenter = true;
|
||
|
|
end
|
||
|
|
previousFilter = filter;
|
||
|
|
filter = filter:lower();
|
||
|
|
|
||
|
|
wipe(frame.buttonsScroll.children);
|
||
|
|
|
||
|
|
local pendingInstallButtonShown = false
|
||
|
|
local CompanionData = WeakAurasCompanion and WeakAurasCompanion.WeakAuras or WeakAurasCompanion
|
||
|
|
if CompanionData and CompanionData.stash then
|
||
|
|
for id, companionData in pairs(CompanionData.stash) do
|
||
|
|
if not pendingInstallButtonShown then
|
||
|
|
tinsert(frame.buttonsScroll.children, frame.pendingInstallButton)
|
||
|
|
pendingInstallButtonShown = true
|
||
|
|
end
|
||
|
|
local child = pendingInstallButtons[id]
|
||
|
|
if frame.pendingInstallButton:GetExpanded() then
|
||
|
|
if not child then
|
||
|
|
child = AceGUI:Create("WeakAurasPendingInstallButton")
|
||
|
|
pendingInstallButtons[id] = child
|
||
|
|
child:Initialize(id, companionData)
|
||
|
|
if companionData.logo then
|
||
|
|
child:SetLogo(companionData.logo)
|
||
|
|
end
|
||
|
|
if companionData.refreshLogo then
|
||
|
|
child:SetRefreshLogo(companionData.refreshLogo)
|
||
|
|
end
|
||
|
|
child.frame:Show()
|
||
|
|
child:AcquireThumbnail()
|
||
|
|
frame.buttonsScroll:AddChild(child)
|
||
|
|
end
|
||
|
|
if not child.frame:IsShown() then
|
||
|
|
child.frame:Show()
|
||
|
|
child:AcquireThumbnail()
|
||
|
|
end
|
||
|
|
tinsert(frame.buttonsScroll.children, child)
|
||
|
|
elseif child then
|
||
|
|
child.frame:Hide()
|
||
|
|
if child.ReleaseThumbnail then
|
||
|
|
child:ReleaseThumbnail()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if not pendingInstallButtonShown and frame.pendingInstallButton then
|
||
|
|
frame.pendingInstallButton.frame:Hide()
|
||
|
|
end
|
||
|
|
|
||
|
|
local pendingUpdateButtonShown = false
|
||
|
|
if CompanionData then
|
||
|
|
local buttonsShown = {}
|
||
|
|
for _, button in pairs(pendingUpdateButtons) do
|
||
|
|
button:ResetLinkedAuras()
|
||
|
|
end
|
||
|
|
for id, aura in pairs(WeakAurasSaved.displays) do
|
||
|
|
if not aura.ignoreWagoUpdate and aura.url and aura.url ~= "" then
|
||
|
|
local slug, version = aura.url:match("wago.io/([^/]+)/([0-9]+)")
|
||
|
|
if not slug and not version then
|
||
|
|
slug = aura.url:match("wago.io/([^/]+)$")
|
||
|
|
version = 1
|
||
|
|
end
|
||
|
|
if slug and version then
|
||
|
|
local auraData = CompanionData.slugs and CompanionData.slugs[slug]
|
||
|
|
if auraData and auraData.wagoVersion then
|
||
|
|
if tonumber(auraData.wagoVersion) > tonumber(version) then
|
||
|
|
-- there is an update for this aura
|
||
|
|
if not pendingUpdateButtonShown then
|
||
|
|
tinsert(frame.buttonsScroll.children, frame.pendingUpdateButton)
|
||
|
|
pendingUpdateButtonShown = true
|
||
|
|
end
|
||
|
|
if frame.pendingUpdateButton:GetExpanded() then
|
||
|
|
local child = pendingUpdateButtons[slug]
|
||
|
|
if not child then
|
||
|
|
child = AceGUI:Create("WeakAurasPendingUpdateButton")
|
||
|
|
pendingUpdateButtons[slug] = child
|
||
|
|
child:Initialize(slug, auraData)
|
||
|
|
if auraData.logo then
|
||
|
|
child:SetLogo(auraData.logo)
|
||
|
|
end
|
||
|
|
if auraData.refreshLogo then
|
||
|
|
child:SetRefreshLogo(auraData.refreshLogo)
|
||
|
|
end
|
||
|
|
child.frame:Show()
|
||
|
|
child:AcquireThumbnail()
|
||
|
|
frame.buttonsScroll:AddChild(child)
|
||
|
|
end
|
||
|
|
if not child.frame:IsShown() then
|
||
|
|
child.frame:Show()
|
||
|
|
child:AcquireThumbnail()
|
||
|
|
end
|
||
|
|
if not buttonsShown[slug] then
|
||
|
|
tinsert(frame.buttonsScroll.children, child)
|
||
|
|
buttonsShown[slug] = true
|
||
|
|
end
|
||
|
|
child:MarkLinkedAura(id)
|
||
|
|
for childData in OptionsPrivate.Private.TraverseAllChildren(aura) do
|
||
|
|
child:MarkLinkedChildren(childData.id)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
-- hide all buttons not marked as shown
|
||
|
|
for slug, button in pairs(pendingUpdateButtons) do
|
||
|
|
if not buttonsShown[slug] then
|
||
|
|
if button and button.frame:IsShown() then
|
||
|
|
button.frame:Hide()
|
||
|
|
if button.ReleaseThumbnail then
|
||
|
|
button:ReleaseThumbnail()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if not pendingUpdateButtonShown and frame.pendingUpdateButton then
|
||
|
|
frame.pendingUpdateButton.frame:Hide()
|
||
|
|
end
|
||
|
|
|
||
|
|
tinsert(frame.buttonsScroll.children, frame.loadedButton);
|
||
|
|
-- First handle loaded auras
|
||
|
|
local numLoaded = 0;
|
||
|
|
local to_sort = {};
|
||
|
|
local children = {};
|
||
|
|
local containsFilter = false;
|
||
|
|
|
||
|
|
local visible = {}
|
||
|
|
|
||
|
|
for id, child in pairs(displayButtons) do
|
||
|
|
containsFilter = not filter or filter == "";
|
||
|
|
local data = WeakAuras.GetData(id);
|
||
|
|
if not(data) then
|
||
|
|
print("|cFF8800FFWeakAuras|r: No data for", id);
|
||
|
|
else
|
||
|
|
if(not containsFilter and data.controlledChildren) then
|
||
|
|
for child in OptionsPrivate.Private.TraverseAllChildren(data) do
|
||
|
|
if(child.id:lower():find(filter, 1, true)) then
|
||
|
|
containsFilter = true;
|
||
|
|
break;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if(
|
||
|
|
frame.loadedButton:GetExpanded()
|
||
|
|
and (not filter or id:lower():find(filter, 1, true) or containsFilter)
|
||
|
|
) then
|
||
|
|
|
||
|
|
local group = child:GetGroup();
|
||
|
|
if(group) then
|
||
|
|
-- In a Group
|
||
|
|
if anyParentLoaded(group) then
|
||
|
|
if(OptionsPrivate.Private.loaded[id]) then
|
||
|
|
child:EnableLoaded();
|
||
|
|
else
|
||
|
|
child:DisableLoaded();
|
||
|
|
end
|
||
|
|
children[group] = children[group] or {};
|
||
|
|
tinsert(children[group], id);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
-- Top Level
|
||
|
|
if(OptionsPrivate.Private.loaded[id] ~= nil) then
|
||
|
|
if(OptionsPrivate.Private.loaded[id]) then
|
||
|
|
child:EnableLoaded();
|
||
|
|
else
|
||
|
|
child:DisableLoaded();
|
||
|
|
end
|
||
|
|
tinsert(to_sort, child);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
table.sort(to_sort, function(a, b) return a:GetTitle() < b:GetTitle() end);
|
||
|
|
|
||
|
|
for _, child in ipairs(to_sort) do
|
||
|
|
child.frame:Show();
|
||
|
|
if child.AcquireThumbnail then
|
||
|
|
child:AcquireThumbnail()
|
||
|
|
end
|
||
|
|
tinsert(frame.buttonsScroll.children, child);
|
||
|
|
visible[child] = true
|
||
|
|
addChildButtons(child, children, visible)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Now handle unloaded auras
|
||
|
|
tinsert(frame.buttonsScroll.children, frame.unloadedButton);
|
||
|
|
local numUnloaded = 0;
|
||
|
|
wipe(to_sort);
|
||
|
|
wipe(children);
|
||
|
|
|
||
|
|
for id, child in pairs(displayButtons) do
|
||
|
|
containsFilter = not filter or filter == "";
|
||
|
|
local data = WeakAuras.GetData(id);
|
||
|
|
if(not containsFilter and data.controlledChildren) then
|
||
|
|
for child in OptionsPrivate.Private.TraverseAllChildren(data) do
|
||
|
|
if(child.id:lower():find(filter, 1, true)) then
|
||
|
|
containsFilter = true;
|
||
|
|
break;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if(
|
||
|
|
frame.unloadedButton:GetExpanded()
|
||
|
|
and (not filter or id:lower():find(filter, 1, true) or containsFilter)
|
||
|
|
) then
|
||
|
|
local group = child:GetGroup();
|
||
|
|
if(group) then
|
||
|
|
if not anyParentLoaded(group) then
|
||
|
|
if(OptionsPrivate.Private.loaded[id]) then
|
||
|
|
child:EnableLoaded();
|
||
|
|
else
|
||
|
|
child:DisableLoaded();
|
||
|
|
end
|
||
|
|
children[group] = children[group] or {};
|
||
|
|
tinsert(children[group], id);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
if(OptionsPrivate.Private.loaded[id] == nil) then
|
||
|
|
child:DisableLoaded();
|
||
|
|
tinsert(to_sort, child);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
table.sort(to_sort, function(a, b) return a:GetTitle() < b:GetTitle() end);
|
||
|
|
|
||
|
|
for _, child in ipairs(to_sort) do
|
||
|
|
child.frame:Show();
|
||
|
|
if child.AcquireThumbnail then
|
||
|
|
child:AcquireThumbnail()
|
||
|
|
end
|
||
|
|
tinsert(frame.buttonsScroll.children, child);
|
||
|
|
visible[child] = true
|
||
|
|
addChildButtons(child, children, visible)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Hiding the other buttons
|
||
|
|
for id, child in pairs(displayButtons) do
|
||
|
|
if(not visible[child]) then
|
||
|
|
child.frame:Hide();
|
||
|
|
if child.ReleaseThumbnail then
|
||
|
|
child:ReleaseThumbnail()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
frame.buttonsScroll:DoLayout();
|
||
|
|
if(recenter) then
|
||
|
|
frame:CenterOnPicked();
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
function OptionsPrivate.IsPickedMultiple()
|
||
|
|
if(frame.pickedDisplay == tempGroup) then
|
||
|
|
return true;
|
||
|
|
else
|
||
|
|
return false;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.IsDisplayPicked(id)
|
||
|
|
if(frame.pickedDisplay == tempGroup) then
|
||
|
|
for child in OptionsPrivate.Private.TraverseLeafs(tempGroup) do
|
||
|
|
if(id == child.id) then
|
||
|
|
return true;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return false;
|
||
|
|
else
|
||
|
|
return frame.pickedDisplay == id;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.PickDisplay(id, tab, noHide)
|
||
|
|
frame:PickDisplay(id, tab, noHide)
|
||
|
|
OptionsPrivate.UpdateButtonsScroll()
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.PickAndEditDisplay(id)
|
||
|
|
frame:PickDisplay(id);
|
||
|
|
displayButtons[id].callbacks.OnRenameClick();
|
||
|
|
OptionsPrivate.UpdateButtonsScroll()
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.ClearPick(id)
|
||
|
|
frame:ClearPick(id);
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.ClearPicks()
|
||
|
|
frame:ClearPicks();
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.PickDisplayMultiple(id)
|
||
|
|
frame:PickDisplayMultiple(id);
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.PickDisplayMultipleShift(target)
|
||
|
|
if (frame.pickedDisplay) then
|
||
|
|
-- get first aura selected
|
||
|
|
local first;
|
||
|
|
if (OptionsPrivate.IsPickedMultiple()) then
|
||
|
|
first = tempGroup.controlledChildren[#tempGroup.controlledChildren];
|
||
|
|
else
|
||
|
|
first = frame.pickedDisplay;
|
||
|
|
end
|
||
|
|
if (first and first ~= target) then
|
||
|
|
-- check if target and first are in same group and are not a group
|
||
|
|
local firstData = WeakAuras.GetData(first);
|
||
|
|
local targetData = WeakAuras.GetData(target);
|
||
|
|
if (firstData.parent == targetData.parent and not targetData.controlledChildren and not firstData.controlledChildren) then
|
||
|
|
local batchSelection = {};
|
||
|
|
-- in a group
|
||
|
|
if (firstData.parent) then
|
||
|
|
local group = WeakAuras.GetData(targetData.parent);
|
||
|
|
for index, child in ipairs(group.controlledChildren) do
|
||
|
|
-- 1st button
|
||
|
|
if (child == target or child == first) then
|
||
|
|
table.insert(batchSelection, child);
|
||
|
|
for i = index + 1, #group.controlledChildren do
|
||
|
|
local current = group.controlledChildren[i];
|
||
|
|
table.insert(batchSelection, current);
|
||
|
|
-- last button: stop selection
|
||
|
|
if (current == target or current == first) then
|
||
|
|
break;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
break;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
elseif (firstData.parent == nil and targetData.parent == nil) then
|
||
|
|
-- top-level
|
||
|
|
for index, button in ipairs(frame.buttonsScroll.children) do
|
||
|
|
local data = button.data;
|
||
|
|
-- 1st button
|
||
|
|
if (data and (data.id == target or data.id == first)) then
|
||
|
|
table.insert(batchSelection, data.id);
|
||
|
|
for i = index + 1, #frame.buttonsScroll.children do
|
||
|
|
local current = frame.buttonsScroll.children[i];
|
||
|
|
local currentData = current.data;
|
||
|
|
if currentData and not currentData.parent and not currentData.controlledChildren then
|
||
|
|
table.insert(batchSelection, currentData.id);
|
||
|
|
-- last button: stop selection
|
||
|
|
if (currentData.id == target or currentData.id == first) then
|
||
|
|
break;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
break;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if #batchSelection > 0 then
|
||
|
|
frame:PickDisplayBatch(batchSelection);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
WeakAuras.PickDisplay(target);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.GetDisplayButton(id)
|
||
|
|
if(id and displayButtons[id]) then
|
||
|
|
return displayButtons[id];
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.AddDisplayButton(data)
|
||
|
|
EnsureDisplayButton(data);
|
||
|
|
WeakAuras.UpdateDisplayButton(data);
|
||
|
|
frame.buttonsScroll:AddChild(displayButtons[data.id]);
|
||
|
|
if(WeakAuras.regions[data.id] and WeakAuras.regions[data.id].region.SetStacks) then
|
||
|
|
WeakAuras.regions[data.id].region:SetStacks(1);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.SetGrouping(data)
|
||
|
|
if (frame.pickedDisplay == tempGroup and #tempGroup.controlledChildren > 0 and data) then
|
||
|
|
local children = {};
|
||
|
|
-- set grouping for selected buttons
|
||
|
|
for index, childId in ipairs(tempGroup.controlledChildren) do
|
||
|
|
local button = WeakAuras.GetDisplayButton(childId);
|
||
|
|
button:SetGrouping(tempGroup.controlledChildren, true);
|
||
|
|
children[childId] = true;
|
||
|
|
end
|
||
|
|
-- set grouping for non selected buttons
|
||
|
|
for id, button in pairs(displayButtons) do
|
||
|
|
if not children[button.data.id] then
|
||
|
|
button:SetGrouping(tempGroup.controlledChildren);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
for id, button in pairs(displayButtons) do
|
||
|
|
button:SetGrouping(data);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.Ungroup(data)
|
||
|
|
if (frame.pickedDisplay == tempGroup and #tempGroup.controlledChildren > 0) then
|
||
|
|
for index, childId in ipairs(tempGroup.controlledChildren) do
|
||
|
|
local button = WeakAuras.GetDisplayButton(childId);
|
||
|
|
button:Ungroup(data);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
local button = WeakAuras.GetDisplayButton(data.id);
|
||
|
|
button:Ungroup(data);
|
||
|
|
end
|
||
|
|
WeakAuras.FillOptions()
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.DragReset()
|
||
|
|
for id, button in pairs(displayButtons) do
|
||
|
|
button:DragReset();
|
||
|
|
end
|
||
|
|
OptionsPrivate.UpdateButtonsScroll()
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.Drop(mainAura, target, action)
|
||
|
|
WeakAuras_DropDownMenu:Hide()
|
||
|
|
|
||
|
|
local mode = ""
|
||
|
|
if (frame.pickedDisplay == tempGroup and #tempGroup.controlledChildren > 0) then
|
||
|
|
mode = "MULTI"
|
||
|
|
elseif mainAura.controlledChildren then
|
||
|
|
mode = "GROUP"
|
||
|
|
else
|
||
|
|
mode = "SINGLE"
|
||
|
|
end
|
||
|
|
|
||
|
|
for id, button in pairs(displayButtons) do
|
||
|
|
button:Drop(mode, mainAura, target, action);
|
||
|
|
end
|
||
|
|
OptionsPrivate.SortDisplayButtons()
|
||
|
|
OptionsPrivate.UpdateButtonsScroll()
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.StartDrag(mainAura)
|
||
|
|
WeakAuras_DropDownMenu:Hide()
|
||
|
|
|
||
|
|
if (frame.pickedDisplay == tempGroup and #tempGroup.controlledChildren > 0) then
|
||
|
|
-- Multi selection
|
||
|
|
local children = {};
|
||
|
|
local size = #tempGroup.controlledChildren;
|
||
|
|
-- set dragging for selected buttons in reverse for ordering
|
||
|
|
|
||
|
|
for child in OptionsPrivate.Private.TraverseAllChildren(tempGroup) do
|
||
|
|
local button = WeakAuras.GetDisplayButton(child.id);
|
||
|
|
button:DragStart("MULTI", true, mainAura, size)
|
||
|
|
children[child.id] = true
|
||
|
|
end
|
||
|
|
-- set dragging for non selected buttons
|
||
|
|
for id, button in pairs(displayButtons) do
|
||
|
|
if not children[button.data.id] then
|
||
|
|
button:DragStart("MULTI", false, mainAura);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
if mainAura.controlledChildren then
|
||
|
|
else
|
||
|
|
for id, button in pairs(displayButtons) do
|
||
|
|
button:DragStart("SINGLE", id == mainAura.id, mainAura);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.DropIndicator()
|
||
|
|
local indicator = frame.dropIndicator
|
||
|
|
if not indicator then
|
||
|
|
indicator = CreateFrame("Frame", "WeakAuras_DropIndicator")
|
||
|
|
indicator:SetHeight(4)
|
||
|
|
indicator:SetFrameStrata("FULLSCREEN")
|
||
|
|
|
||
|
|
local groupTexture = indicator:CreateTexture(nil, "ARTWORK")
|
||
|
|
groupTexture:SetBlendMode("ADD")
|
||
|
|
groupTexture:SetTexture("Interface\\AddOns\\WeakAuras\\Media\\Textures\\Square_FullWhite")
|
||
|
|
|
||
|
|
local lineTexture = indicator:CreateTexture(nil, "ARTWORK")
|
||
|
|
lineTexture:SetBlendMode("ADD")
|
||
|
|
lineTexture:SetAllPoints(indicator)
|
||
|
|
lineTexture:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
|
||
|
|
|
||
|
|
indicator.lineTexture = lineTexture
|
||
|
|
indicator.groupTexture = groupTexture
|
||
|
|
frame.dropIndicator = indicator
|
||
|
|
indicator:Hide()
|
||
|
|
|
||
|
|
function indicator:ShowAction(target, action)
|
||
|
|
self:Show()
|
||
|
|
self:ClearAllPoints()
|
||
|
|
if action == "GROUP" then
|
||
|
|
self.groupTexture:ClearAllPoints()
|
||
|
|
self.groupTexture:SetVertexColor(0.4, 0.7, 1, 0.7)
|
||
|
|
self.groupTexture:Show()
|
||
|
|
self.groupTexture:SetPoint("TOPLEFT", target.icon, "TOPRIGHT", 2, -1)
|
||
|
|
self.groupTexture:SetPoint("BOTTOMRIGHT", target.frame, "BOTTOMRIGHT", 0, 1)
|
||
|
|
else
|
||
|
|
self.groupTexture:Hide()
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Position line texture, if needed
|
||
|
|
if action == "BEFORE" then
|
||
|
|
self.lineTexture:Show()
|
||
|
|
self:SetPoint("BOTTOMLEFT", target.frame, "TOPLEFT", 0, -1)
|
||
|
|
self:SetPoint("BOTTOMRIGHT", target.frame, "TOPRIGHT", 0, -1)
|
||
|
|
self:SetHeight(4)
|
||
|
|
elseif action == "AFTER" then
|
||
|
|
self.lineTexture:Show()
|
||
|
|
self:SetPoint("TOPLEFT", target.frame, "BOTTOMLEFT", 0, 1)
|
||
|
|
self:SetPoint("TOPRIGHT", target.frame, "BOTTOMRIGHT", 0, 1)
|
||
|
|
self:SetHeight(4)
|
||
|
|
else
|
||
|
|
self.lineTexture:Hide()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
return indicator
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.UpdateDisplayButton(data)
|
||
|
|
local id = data.id;
|
||
|
|
local button = displayButtons[id];
|
||
|
|
if (button) then
|
||
|
|
button:UpdateThumbnail()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.UpdateThumbnail(data)
|
||
|
|
local id = data.id
|
||
|
|
local button = displayButtons[id]
|
||
|
|
if (not button) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
button:UpdateThumbnail()
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.OpenTexturePicker(baseObject, path, properties, textures, SetTextureFunc)
|
||
|
|
frame.texturePicker:Open(baseObject, path, properties, textures, SetTextureFunc)
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.OpenIconPicker(baseObject, paths, groupIcon)
|
||
|
|
frame.iconPicker:Open(baseObject, paths, groupIcon)
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.OpenModelPicker(baseObject, path)
|
||
|
|
if not(IsAddOnLoaded("WeakAurasModelPaths")) then
|
||
|
|
local loaded, reason = LoadAddOn("WeakAurasModelPaths");
|
||
|
|
if not(loaded) then
|
||
|
|
reason = string.lower("|cffff2020" .. _G["ADDON_" .. reason] .. "|r.")
|
||
|
|
WeakAuras.prettyPrint("ModelPaths could not be loaded, the addon is " .. reason);
|
||
|
|
WeakAuras.ModelPaths = {};
|
||
|
|
end
|
||
|
|
frame.modelPicker.modelTree:SetTree(WeakAuras.ModelPaths);
|
||
|
|
end
|
||
|
|
frame.modelPicker:Open(baseObject, path);
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.OpenCodeReview(data)
|
||
|
|
frame.codereview:Open(data);
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.CloseCodeReview(data)
|
||
|
|
frame.codereview:Close();
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.OpenTriggerTemplate(data, targetId)
|
||
|
|
if not(IsAddOnLoaded("WeakAurasTemplates")) then
|
||
|
|
local loaded, reason = LoadAddOn("WeakAurasTemplates");
|
||
|
|
if not(loaded) then
|
||
|
|
reason = string.lower("|cffff2020" .. _G["ADDON_" .. reason] .. "|r.")
|
||
|
|
WeakAuras.prettyPrint("Templates could not be loaded, the addon is " .. reason);
|
||
|
|
return;
|
||
|
|
end
|
||
|
|
frame.newView = WeakAuras.CreateTemplateView(OptionsPrivate.Private, frame);
|
||
|
|
end
|
||
|
|
-- This is called multiple times if a group is selected
|
||
|
|
if frame.window ~= "newView" then
|
||
|
|
frame.newView:Open(data, targetId);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.ResetMoverSizer()
|
||
|
|
if(frame and frame.mover and frame.moversizer and frame.mover.moving.region and frame.mover.moving.data) then
|
||
|
|
frame.moversizer:SetToRegion(frame.mover.moving.region, frame.mover.moving.data);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.SetMoverSizer(id)
|
||
|
|
if WeakAuras.regions[id].region.toShow then
|
||
|
|
frame.moversizer:SetToRegion(WeakAuras.regions[id].region, db.displays[id])
|
||
|
|
else
|
||
|
|
if WeakAuras.clones[id] then
|
||
|
|
local cloneId, clone = next(WeakAuras.clones[id])
|
||
|
|
if clone then
|
||
|
|
frame.moversizer:SetToRegion(clone, db.displays[id])
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.GetMoverSizerId()
|
||
|
|
return frame.moversizer:GetCurrentId()
|
||
|
|
end
|
||
|
|
|
||
|
|
local function AddDefaultSubRegions(data)
|
||
|
|
data.subRegions = data.subRegions or {}
|
||
|
|
for type, subRegionData in pairs(OptionsPrivate.Private.subRegionTypes) do
|
||
|
|
if subRegionData.addDefaultsForNewAura then
|
||
|
|
subRegionData.addDefaultsForNewAura(data)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function WeakAuras.NewAura(sourceData, regionType, targetId)
|
||
|
|
local function ensure(t, k, v)
|
||
|
|
return t and k and v and t[k] == v
|
||
|
|
end
|
||
|
|
local new_id = WeakAuras.FindUnusedId("New")
|
||
|
|
local data = {id = new_id, regionType = regionType, uid = WeakAuras.GenerateUniqueID()}
|
||
|
|
WeakAuras.DeepMixin(data, WeakAuras.data_stub);
|
||
|
|
if (sourceData) then
|
||
|
|
WeakAuras.DeepMixin(data, sourceData);
|
||
|
|
end
|
||
|
|
data.internalVersion = WeakAuras.InternalVersion();
|
||
|
|
WeakAuras.validate(data, WeakAuras.regionTypes[regionType].default);
|
||
|
|
|
||
|
|
AddDefaultSubRegions(data)
|
||
|
|
|
||
|
|
if (data.regionType ~= "group" and data.regionType ~= "dynamicgroup" and targetId) then
|
||
|
|
local target = WeakAuras.GetDisplayButton(targetId);
|
||
|
|
local group
|
||
|
|
if (target) then
|
||
|
|
if (target:IsGroup()) then
|
||
|
|
group = target;
|
||
|
|
else
|
||
|
|
group = WeakAuras.GetDisplayButton(target.data.parent);
|
||
|
|
end
|
||
|
|
if (group) then
|
||
|
|
local children = group.data.controlledChildren;
|
||
|
|
local index = target:GetGroupOrder();
|
||
|
|
if (ensure(children, index, target.data.id)) then
|
||
|
|
-- account for insert position
|
||
|
|
index = index + 1;
|
||
|
|
tinsert(children, index, data.id);
|
||
|
|
else
|
||
|
|
-- move source into group as the first child
|
||
|
|
tinsert(children, 1, data.id);
|
||
|
|
end
|
||
|
|
data.parent = group.data.id;
|
||
|
|
WeakAuras.Add(data);
|
||
|
|
WeakAuras.Add(group.data);
|
||
|
|
OptionsPrivate.Private.AddParents(group.data)
|
||
|
|
WeakAuras.NewDisplayButton(data);
|
||
|
|
WeakAuras.UpdateGroupOrders(group.data);
|
||
|
|
OptionsPrivate.ClearOptions(group.data.id);
|
||
|
|
WeakAuras.UpdateDisplayButton(group.data);
|
||
|
|
group.callbacks.UpdateExpandButton();
|
||
|
|
group:Expand();
|
||
|
|
group:ReloadTooltip();
|
||
|
|
OptionsPrivate.PickAndEditDisplay(data.id);
|
||
|
|
else
|
||
|
|
-- move source into the top-level list
|
||
|
|
WeakAuras.Add(data);
|
||
|
|
WeakAuras.NewDisplayButton(data);
|
||
|
|
OptionsPrivate.PickAndEditDisplay(data.id);
|
||
|
|
end
|
||
|
|
else
|
||
|
|
error("Calling 'WeakAuras.NewAura' with invalid groupId. Reload your UI to fix the display list.")
|
||
|
|
end
|
||
|
|
else
|
||
|
|
-- move source into the top-level list
|
||
|
|
WeakAuras.Add(data);
|
||
|
|
WeakAuras.NewDisplayButton(data);
|
||
|
|
OptionsPrivate.PickAndEditDisplay(data.id);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
function OptionsPrivate.ResetCollapsed(id, namespace)
|
||
|
|
if id then
|
||
|
|
if namespace and collapsedOptions[id] then
|
||
|
|
collapsedOptions[id][namespace] = nil
|
||
|
|
else
|
||
|
|
collapsedOptions[id] = nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.IsCollapsed(id, namespace, path, default)
|
||
|
|
local tmp = collapsedOptions[id]
|
||
|
|
if tmp == nil then return default end
|
||
|
|
|
||
|
|
tmp = tmp[namespace]
|
||
|
|
if tmp == nil then return default end
|
||
|
|
|
||
|
|
if type(path) ~= "table" then
|
||
|
|
tmp = tmp[path]
|
||
|
|
else
|
||
|
|
for _, key in ipairs(path) do
|
||
|
|
tmp = tmp[key]
|
||
|
|
if tmp == nil or tmp[collapsed] then
|
||
|
|
break
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if tmp == nil or tmp[collapsed] == nil then
|
||
|
|
return default
|
||
|
|
else
|
||
|
|
return tmp[collapsed]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.SetCollapsed(id, namespace, path, v)
|
||
|
|
collapsedOptions[id] = collapsedOptions[id] or {}
|
||
|
|
collapsedOptions[id][namespace] = collapsedOptions[id][namespace] or {}
|
||
|
|
if type(path) ~= "table" then
|
||
|
|
collapsedOptions[id][namespace][path] = collapsedOptions[id][namespace][path] or {}
|
||
|
|
collapsedOptions[id][namespace][path][collapsed] = v
|
||
|
|
else
|
||
|
|
local tmp = collapsedOptions[id][namespace] or {}
|
||
|
|
for _, key in ipairs(path) do
|
||
|
|
tmp[key] = tmp[key] or {}
|
||
|
|
tmp = tmp[key]
|
||
|
|
end
|
||
|
|
tmp[collapsed] = v
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.MoveCollapseDataUp(id, namespace, path)
|
||
|
|
collapsedOptions[id] = collapsedOptions[id] or {}
|
||
|
|
collapsedOptions[id][namespace] = collapsedOptions[id][namespace] or {}
|
||
|
|
if type(path) ~= "table" then
|
||
|
|
collapsedOptions[id][namespace][path], collapsedOptions[id][namespace][path - 1] = collapsedOptions[id][namespace][path - 1], collapsedOptions[id][namespace][path]
|
||
|
|
else
|
||
|
|
local tmp = collapsedOptions[id][namespace]
|
||
|
|
local lastKey = tremove(path)
|
||
|
|
for _, key in ipairs(path) do
|
||
|
|
tmp[key] = tmp[key] or {}
|
||
|
|
tmp = tmp[key]
|
||
|
|
end
|
||
|
|
tmp[lastKey], tmp[lastKey - 1] = tmp[lastKey - 1], tmp[lastKey]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.MoveCollapseDataDown(id, namespace, path)
|
||
|
|
collapsedOptions[id] = collapsedOptions[id] or {}
|
||
|
|
collapsedOptions[id][namespace] = collapsedOptions[id][namespace] or {}
|
||
|
|
if type(path) ~= "table" then
|
||
|
|
collapsedOptions[id][namespace][path], collapsedOptions[id][namespace][path + 1] = collapsedOptions[id][namespace][path + 1], collapsedOptions[id][namespace][path]
|
||
|
|
else
|
||
|
|
local tmp = collapsedOptions[id][namespace]
|
||
|
|
local lastKey = tremove(path)
|
||
|
|
for _, key in ipairs(path) do
|
||
|
|
tmp[key] = tmp[key] or {}
|
||
|
|
tmp = tmp[key]
|
||
|
|
end
|
||
|
|
tmp[lastKey], tmp[lastKey + 1] = tmp[lastKey + 1], tmp[lastKey]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.RemoveCollapsed(id, namespace, path)
|
||
|
|
local data = collapsedOptions[id] and collapsedOptions[id][namespace]
|
||
|
|
if not data then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
local index
|
||
|
|
local maxIndex = 0
|
||
|
|
if type(path) ~= "table" then
|
||
|
|
index = path
|
||
|
|
else
|
||
|
|
index = path[#path]
|
||
|
|
for i = 1, #path - 1 do
|
||
|
|
data = data[path[i]]
|
||
|
|
if not data then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
for k in pairs(data) do
|
||
|
|
if k ~= collapsed then
|
||
|
|
maxIndex = max(maxIndex, k)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
while index <= maxIndex do
|
||
|
|
data[index] = data[index + 1]
|
||
|
|
index = index + 1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.InsertCollapsed(id, namespace, path, value)
|
||
|
|
local data = collapsedOptions[id] and collapsedOptions[id][namespace]
|
||
|
|
if not data then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
local insertPoint
|
||
|
|
local maxIndex
|
||
|
|
if type(path) ~= "table" then
|
||
|
|
insertPoint = path
|
||
|
|
else
|
||
|
|
insertPoint = path[#path]
|
||
|
|
for i = 1, #path - 1 do
|
||
|
|
data = data[path[i]]
|
||
|
|
if not data then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
for k in pairs(data) do
|
||
|
|
if k ~= collapsed and k >= insertPoint then
|
||
|
|
if not maxIndex or k > maxIndex then
|
||
|
|
maxIndex = k
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if maxIndex then -- may be nil if insertPoint is greater than the max of anything else
|
||
|
|
for i = maxIndex, insertPoint, -1 do
|
||
|
|
data[i + 1] = data[i]
|
||
|
|
end
|
||
|
|
end
|
||
|
|
data[insertPoint] = {[collapsed] = value}
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.DuplicateCollapseData(id, namespace, path)
|
||
|
|
collapsedOptions[id] = collapsedOptions[id] or {}
|
||
|
|
collapsedOptions[id][namespace] = collapsedOptions[id][namespace] or {}
|
||
|
|
if type(path) ~= "table" then
|
||
|
|
if (collapsedOptions[id][namespace][path]) then
|
||
|
|
tinsert(collapsedOptions[id][namespace], path + 1, CopyTable(collapsedOptions[id][namespace][path]))
|
||
|
|
end
|
||
|
|
else
|
||
|
|
local tmp = collapsedOptions[id][namespace]
|
||
|
|
local lastKey = tremove(path)
|
||
|
|
for _, key in ipairs(path) do
|
||
|
|
tmp[key] = tmp[key] or {}
|
||
|
|
tmp = tmp[key]
|
||
|
|
end
|
||
|
|
|
||
|
|
if (tmp[lastKey]) then
|
||
|
|
tinsert(tmp, lastKey + 1, CopyTable(tmp[lastKey]))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function OptionsPrivate.AddTextFormatOption(input, withHeader, get, addOption, hidden, setHidden, index, total)
|
||
|
|
local headerOption
|
||
|
|
if withHeader and (not index or index == 1) then
|
||
|
|
headerOption = {
|
||
|
|
type = "execute",
|
||
|
|
control = "WeakAurasExpandSmall",
|
||
|
|
name = L["|cFFffcc00Format Options|r"],
|
||
|
|
width = WeakAuras.doubleWidth,
|
||
|
|
func = function(info, button)
|
||
|
|
setHidden(not hidden())
|
||
|
|
end,
|
||
|
|
image = function()
|
||
|
|
return hidden() and "collapsed" or "expanded"
|
||
|
|
end,
|
||
|
|
imageWidth = 15,
|
||
|
|
imageHeight = 15,
|
||
|
|
arg = {
|
||
|
|
expanderName = tostring(addOption)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
addOption("header", headerOption)
|
||
|
|
else
|
||
|
|
hidden = false
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
local seenSymbols = {}
|
||
|
|
OptionsPrivate.Private.ParseTextStr(input, function(symbol)
|
||
|
|
if not seenSymbols[symbol] then
|
||
|
|
local triggerNum, sym = string.match(symbol, "(.+)%.(.+)")
|
||
|
|
sym = sym or symbol
|
||
|
|
|
||
|
|
if sym == "c" or sym == "i" then
|
||
|
|
-- No special options for these
|
||
|
|
else
|
||
|
|
addOption(symbol .. "desc", {
|
||
|
|
type = "description",
|
||
|
|
name = L["Format for %s"]:format("%" .. symbol),
|
||
|
|
width = WeakAuras.normalWidth,
|
||
|
|
hidden = hidden
|
||
|
|
})
|
||
|
|
addOption(symbol .. "_format", {
|
||
|
|
type = "select",
|
||
|
|
name = L["Format"],
|
||
|
|
width = WeakAuras.normalWidth,
|
||
|
|
values = OptionsPrivate.Private.format_types_display,
|
||
|
|
hidden = hidden,
|
||
|
|
reloadOptions = true
|
||
|
|
})
|
||
|
|
|
||
|
|
local selectedFormat = get(symbol .. "_format")
|
||
|
|
if (OptionsPrivate.Private.format_types[selectedFormat]) then
|
||
|
|
OptionsPrivate.Private.format_types[selectedFormat].AddOptions(symbol, hidden, addOption, get)
|
||
|
|
end
|
||
|
|
seenSymbols[symbol] = true
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
|
||
|
|
if withHeader and (not index or index == total) then
|
||
|
|
addOption("header_anchor",
|
||
|
|
{
|
||
|
|
type = "description",
|
||
|
|
name = "",
|
||
|
|
control = "WeakAurasExpandAnchor",
|
||
|
|
arg = {
|
||
|
|
expanderName = tostring(addOption)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
)
|
||
|
|
end
|
||
|
|
|
||
|
|
if not next(seenSymbols) and headerOption and not index then
|
||
|
|
headerOption.hidden = true
|
||
|
|
end
|
||
|
|
|
||
|
|
return next(seenSymbols) ~= nil
|
||
|
|
end
|