559 lines
16 KiB
Lua
559 lines
16 KiB
Lua
local E = unpack(ElvUI) --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
|
local D = E:GetModule("Distributor")
|
|
|
|
local _, Engine = ...
|
|
Engine[1] = {Blank = function() return '' end }
|
|
Engine[2] = E.Libs.ACL:GetLocale("ElvUI", E.global.general.locale or "enUS")
|
|
local C, L = Engine[1], Engine[2]
|
|
|
|
local format, strmatch, strsplit = string.format, string.match, string.split
|
|
local tconcat, tinsert, tremove = table.concat, table.insert, table.remove
|
|
local ipairs, gsub = ipairs, gsub
|
|
|
|
C.Values = {
|
|
FontFlags = {
|
|
["NONE"] = L["NONE"],
|
|
["OUTLINE"] = "OUTLINE",
|
|
["MONOCHROMEOUTLINE"] = "MONOCROMEOUTLINE",
|
|
["THICKOUTLINE"] = "THICKOUTLINE"
|
|
}
|
|
}
|
|
|
|
do
|
|
C.StateSwitchGetText = function(_, TEXT)
|
|
local friend, enemy = strmatch(TEXT, '^Friendly:([^,]*)'), strmatch(TEXT, '^Enemy:([^,]*)')
|
|
local text, blockB, blockS, blockT = friend or enemy or TEXT
|
|
local SF, localized = E.global.unitframe.specialFilters[text], L[text]
|
|
if SF and localized and text:match('^block') then blockB, blockS, blockT = localized:match('^%[(.-)](%s?)(.+)') end
|
|
local filterText = (blockB and format('|cFF999999%s|r%s%s', blockB, blockS, blockT)) or localized or text
|
|
return (friend and format('|cFF33FF33%s|r %s', _G.FRIEND, filterText)) or (enemy and format('|cFFFF3333%s|r %s', _G.ENEMY, filterText)) or filterText
|
|
end
|
|
|
|
local function filterMatch(s,v)
|
|
local m1, m2, m3, m4 = '^'..v..'$', '^'..v..',', ','..v..'$', ','..v..','
|
|
return (strmatch(s, m1) and m1) or (strmatch(s, m2) and m2) or (strmatch(s, m3) and m3) or (strmatch(s, m4) and v..',')
|
|
end
|
|
|
|
C.SetFilterPriority = function(db, groupName, auraType, value, remove, movehere, friendState)
|
|
if not auraType or not value then return end
|
|
local filter = db[groupName] and db[groupName][auraType] and db[groupName][auraType].priority
|
|
if not filter then return end
|
|
local found = filterMatch(filter, E:EscapeString(value))
|
|
if found and movehere then
|
|
local tbl, sv, sm = {strsplit(',',filter)}
|
|
for i in ipairs(tbl) do
|
|
if tbl[i] == value then sv = i elseif tbl[i] == movehere then sm = i end
|
|
if sv and sm then break end
|
|
end
|
|
tremove(tbl, sm)
|
|
tinsert(tbl, sv, movehere)
|
|
db[groupName][auraType].priority = tconcat(tbl,',')
|
|
elseif found and friendState then
|
|
local realValue = strmatch(value, '^Friendly:([^,]*)') or strmatch(value, '^Enemy:([^,]*)') or value
|
|
local friend = filterMatch(filter, E:EscapeString('Friendly:'..realValue))
|
|
local enemy = filterMatch(filter, E:EscapeString('Enemy:'..realValue))
|
|
local default = filterMatch(filter, E:EscapeString(realValue))
|
|
|
|
local state =
|
|
(friend and (not enemy) and format('%s%s','Enemy:',realValue)) --[x] friend [ ] enemy: > enemy
|
|
or ((not enemy and not friend) and format('%s%s','Friendly:',realValue)) --[ ] friend [ ] enemy: > friendly
|
|
or (enemy and (not friend) and default and format('%s%s','Friendly:',realValue)) --[ ] friend [x] enemy: (default exists) > friendly
|
|
or (enemy and (not friend) and strmatch(value, '^Enemy:') and realValue) --[ ] friend [x] enemy: (no default) > realvalue
|
|
or (friend and enemy and realValue) --[x] friend [x] enemy: > default
|
|
|
|
if state then
|
|
local stateFound = filterMatch(filter, E:EscapeString(state))
|
|
if not stateFound then
|
|
local tbl, sv = {strsplit(',',filter)}
|
|
for i in ipairs(tbl) do
|
|
if tbl[i] == value then
|
|
sv = i
|
|
break
|
|
end
|
|
end
|
|
tinsert(tbl, sv, state)
|
|
tremove(tbl, sv+1)
|
|
db[groupName][auraType].priority = tconcat(tbl,',')
|
|
end
|
|
end
|
|
elseif found and remove then
|
|
db[groupName][auraType].priority = gsub(filter, found, '')
|
|
elseif not found and not remove then
|
|
db[groupName][auraType].priority = (filter == '' and value) or (filter..','..value)
|
|
end
|
|
end
|
|
end
|
|
|
|
E:AddLib("AceGUI", "AceGUI-3.0")
|
|
E:AddLib("AceConfig", "AceConfig-3.0-ElvUI")
|
|
E:AddLib("AceConfigDialog", "AceConfigDialog-3.0-ElvUI")
|
|
E:AddLib("AceConfigRegistry", "AceConfigRegistry-3.0-ElvUI")
|
|
E:AddLib("AceDBOptions", "AceDBOptions-3.0")
|
|
E:AddLib('ACH', 'LibAceConfigHelper')
|
|
|
|
local UnitName = UnitName
|
|
local UnitExists = UnitExists
|
|
local UnitIsUnit = UnitIsUnit
|
|
local UnitIsFriend = UnitIsFriend
|
|
local UnitIsPlayer = UnitIsPlayer
|
|
local GameTooltip_Hide = GameTooltip_Hide
|
|
local GameFontHighlightSmall = _G.GameFontHighlightSmall
|
|
|
|
--Function we can call on profile change to update GUI
|
|
function E:RefreshGUI()
|
|
E:RefreshCustomTextsConfigs()
|
|
E.Libs.AceConfigRegistry:NotifyChange("ElvUI")
|
|
end
|
|
|
|
E.Libs.AceConfig:RegisterOptionsTable("ElvUI", E.Options)
|
|
E.Libs.AceConfigDialog:SetDefaultSize("ElvUI", E:GetConfigDefaultSize())
|
|
|
|
E.Options.args = {
|
|
ElvUI_Header = {
|
|
order = 1,
|
|
type = "header",
|
|
name = format("%s: |cff99ff33%s|r", L["Version"], E.version),
|
|
width = "full"
|
|
},
|
|
RepositionWindow = {
|
|
order = 3,
|
|
type = "execute",
|
|
name = L["Reposition Window"],
|
|
desc = L["Reset the size and position of this frame."],
|
|
customWidth = 175,
|
|
func = function()
|
|
E:UpdateConfigSize(true)
|
|
end
|
|
},
|
|
ToggleTutorial = {
|
|
order = 4,
|
|
type = "execute",
|
|
name = L["Toggle Tutorials"],
|
|
customWidth = 150,
|
|
func = function()
|
|
E:Tutorials(true)
|
|
E:ToggleOptionsUI()
|
|
end
|
|
},
|
|
Install = {
|
|
order = 5,
|
|
type = "execute",
|
|
name = L["Install"],
|
|
customWidth = 100,
|
|
desc = L["Run the installation process."],
|
|
func = function()
|
|
E:Install()
|
|
E:ToggleOptionsUI()
|
|
end
|
|
},
|
|
ResetAllMovers = {
|
|
order = 6,
|
|
type = "execute",
|
|
name = L["Reset Anchors"],
|
|
customWidth = 150,
|
|
desc = L["Reset all frames to their original positions."],
|
|
func = function()
|
|
E:ResetUI()
|
|
end
|
|
},
|
|
ToggleAnchors = {
|
|
order = 7,
|
|
type = "execute",
|
|
name = L["Toggle Anchors"],
|
|
customWidth = 150,
|
|
desc = L["Unlock various elements of the UI to be repositioned."],
|
|
func = function()
|
|
E:ToggleMoveMode()
|
|
end
|
|
},
|
|
LoginMessage = {
|
|
order = 8,
|
|
type = "toggle",
|
|
name = L["Login Message"],
|
|
customWidth = 150,
|
|
get = function(info)
|
|
return E.db.general.loginmessage
|
|
end,
|
|
set = function(info, value)
|
|
E.db.general.loginmessage = value
|
|
end
|
|
}
|
|
}
|
|
|
|
local DEVELOPERS = {
|
|
"Tukz",
|
|
"Haste",
|
|
"Nightcracker",
|
|
"Omega1970",
|
|
"Hydrazine",
|
|
"Blazeflack",
|
|
"NihilisticPandemonium",
|
|
"|cffff7d0aMerathilis|r",
|
|
"|cFF8866ccSimpy|r",
|
|
"|cFF0070DEAzilroka|r"
|
|
}
|
|
local TESTERS = {
|
|
}
|
|
local DONATORS = {
|
|
}
|
|
|
|
do
|
|
local DEVELOPER_STRING
|
|
local TESTER_STRING
|
|
local DONATOR_STRING
|
|
|
|
if #DEVELOPERS > 0 then
|
|
table.sort(DEVELOPERS)
|
|
DEVELOPER_STRING = table.concat(DEVELOPERS, "\n")
|
|
end
|
|
if #TESTERS > 0 then
|
|
table.sort(TESTERS)
|
|
TESTER_STRING = table.concat(TESTERS, "\n")
|
|
end
|
|
if #DONATORS > 0 then
|
|
table.sort(DONATORS)
|
|
DONATOR_STRING = table.concat(DONATORS, "\n")
|
|
end
|
|
|
|
local CREDITS_STRING = format("%s%s%s%s",
|
|
L["ELVUI_CREDITS"],
|
|
(DEVELOPER_STRING and format("\n\n %s\n%s", L["Coding:"], DEVELOPER_STRING) or ""),
|
|
(TESTER_STRING and format("\n\n %s\n%s", L["Testing:"], TESTER_STRING) or ""),
|
|
(DONATOR_STRING and format("\n\n %s\n%s", L["Donations:"], DONATOR_STRING) or "")
|
|
)
|
|
|
|
E.Options.args.credits = {
|
|
order = -1,
|
|
type = "group",
|
|
name = L["Credits"],
|
|
args = {
|
|
text = {
|
|
order = 1,
|
|
type = "description",
|
|
name = CREDITS_STRING
|
|
}
|
|
}
|
|
}
|
|
end
|
|
|
|
local profileTypeItems = {
|
|
["profile"] = L["Profile"],
|
|
["private"] = L["Private (Character Settings)"],
|
|
["global"] = L["Global (Account Settings)"],
|
|
["filters"] = L["Aura Filters"],
|
|
["styleFilters"] = L["NamePlate Style Filters"]
|
|
}
|
|
local profileTypeListOrder = {
|
|
"profile",
|
|
"private",
|
|
"global",
|
|
"filters",
|
|
"styleFilters"
|
|
}
|
|
local exportTypeItems = {
|
|
["text"] = L["Text"],
|
|
["luaTable"] = L["Table"],
|
|
["luaPlugin"] = L["Plugin"]
|
|
}
|
|
local exportTypeListOrder = {
|
|
"text",
|
|
"luaTable",
|
|
"luaPlugin"
|
|
}
|
|
|
|
local exportString = ""
|
|
local function ExportImport_Open(mode)
|
|
local Frame = E.Libs.AceGUI:Create("Frame")
|
|
Frame:SetTitle(" ")
|
|
Frame:EnableResize(false)
|
|
Frame:SetWidth(800)
|
|
Frame:SetHeight(600)
|
|
Frame.frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
Frame:SetLayout("flow")
|
|
|
|
local Box = E.Libs.AceGUI:Create("MultiLineEditBox")
|
|
Box:SetNumLines(30)
|
|
Box:DisableButton(true)
|
|
Box:SetWidth(800)
|
|
Box:SetLabel(" ")
|
|
Frame:AddChild(Box)
|
|
--Save original script so we can restore it later
|
|
Box.editBox.OnTextChangedOrig = Box.editBox:GetScript("OnTextChanged")
|
|
Box.editBox.OnCursorChangedOrig = Box.editBox:GetScript("OnCursorChanged")
|
|
--Remove OnCursorChanged script as it causes weird behaviour with long text
|
|
Box.editBox:SetScript("OnCursorChanged", nil)
|
|
|
|
local Label1 = E.Libs.AceGUI:Create("Label")
|
|
local font = GameFontHighlightSmall:GetFont()
|
|
Label1:SetFont(font, 14)
|
|
Label1:SetText(" ") --Set temporary text so height is set correctly
|
|
Label1:SetWidth(800)
|
|
Frame:AddChild(Label1)
|
|
|
|
local Label2 = E.Libs.AceGUI:Create("Label")
|
|
font = GameFontHighlightSmall:GetFont()
|
|
Label2:SetFont(font, 14)
|
|
Label2:SetText(" \n ")
|
|
Label2:SetWidth(800)
|
|
Frame:AddChild(Label2)
|
|
|
|
if mode == "export" then
|
|
Frame:SetTitle(L["Export Profile"])
|
|
|
|
local ProfileTypeDropdown = E.Libs.AceGUI:Create("Dropdown")
|
|
ProfileTypeDropdown:SetMultiselect(false)
|
|
ProfileTypeDropdown:SetLabel(L["Choose What To Export"])
|
|
ProfileTypeDropdown:SetList(profileTypeItems, profileTypeListOrder)
|
|
ProfileTypeDropdown:SetValue("profile") --Default export
|
|
Frame:AddChild(ProfileTypeDropdown)
|
|
|
|
local ExportFormatDropdown = E.Libs.AceGUI:Create("Dropdown")
|
|
ExportFormatDropdown:SetMultiselect(false)
|
|
ExportFormatDropdown:SetLabel(L["Choose Export Format"])
|
|
ExportFormatDropdown:SetList(exportTypeItems, exportTypeListOrder)
|
|
ExportFormatDropdown:SetValue("text") --Default format
|
|
ExportFormatDropdown:SetWidth(150)
|
|
Frame:AddChild(ExportFormatDropdown)
|
|
|
|
local exportButton = E.Libs.AceGUI:Create("Button")
|
|
exportButton:SetText(L["Export Now"])
|
|
exportButton:SetAutoWidth(true)
|
|
local function OnClick(self)
|
|
--Clear labels
|
|
Label1:SetText(" ")
|
|
Label2:SetText(" ")
|
|
|
|
local profileType, exportFormat = ProfileTypeDropdown:GetValue(), ExportFormatDropdown:GetValue()
|
|
local profileKey, profileExport = D:ExportProfile(profileType, exportFormat)
|
|
if not profileKey or not profileExport then
|
|
Label1:SetText(L["Error exporting profile!"])
|
|
else
|
|
Label1:SetText(
|
|
format("%s: %s%s|r", L["Exported"], E.media.hexvaluecolor, profileTypeItems[profileType])
|
|
)
|
|
if profileType == "profile" then
|
|
Label2:SetText(format("%s: %s%s|r", L["Profile Name"], E.media.hexvaluecolor, profileKey))
|
|
end
|
|
end
|
|
Box:SetText(profileExport)
|
|
Box.editBox:HighlightText()
|
|
Box:SetFocus()
|
|
exportString = profileExport
|
|
end
|
|
exportButton:SetCallback("OnClick", OnClick)
|
|
Frame:AddChild(exportButton)
|
|
|
|
--Set scripts
|
|
Box.editBox:SetScript("OnChar", function()
|
|
Box:SetText(exportString)
|
|
Box.editBox:HighlightText()
|
|
end)
|
|
Box.editBox:SetScript("OnTextChanged", function(self, userInput)
|
|
if userInput then
|
|
--Prevent user from changing export string
|
|
Box:SetText(exportString)
|
|
Box.editBox:HighlightText()
|
|
end
|
|
end)
|
|
elseif mode == "import" then
|
|
Frame:SetTitle(L["Import Profile"])
|
|
local importButton = E.Libs.AceGUI:Create("Button-ElvUI") --This version changes text color on SetDisabled
|
|
importButton:SetDisabled(true)
|
|
importButton:SetText(L["Import Now"])
|
|
importButton:SetAutoWidth(true)
|
|
importButton:SetCallback("OnClick", function()
|
|
--Clear labels
|
|
Label1:SetText(" ")
|
|
Label2:SetText(" ")
|
|
|
|
local text
|
|
local success = D:ImportProfile(Box:GetText())
|
|
if success then
|
|
text = L["Profile imported successfully!"]
|
|
else
|
|
text = L["Error decoding data. Import string may be corrupted!"]
|
|
end
|
|
Label1:SetText(text)
|
|
end)
|
|
Frame:AddChild(importButton)
|
|
|
|
local decodeButton = E.Libs.AceGUI:Create("Button-ElvUI")
|
|
decodeButton:SetDisabled(true)
|
|
decodeButton:SetText(L["Decode Text"])
|
|
decodeButton:SetAutoWidth(true)
|
|
decodeButton:SetCallback("OnClick", function()
|
|
--Clear labels
|
|
Label1:SetText(" ")
|
|
Label2:SetText(" ")
|
|
local decodedText
|
|
local profileType, profileKey, profileData = D:Decode(Box:GetText())
|
|
if profileData then
|
|
decodedText = E:TableToLuaString(profileData)
|
|
end
|
|
local importText = D:CreateProfileExport(decodedText, profileType, profileKey)
|
|
Box:SetText(importText)
|
|
end)
|
|
Frame:AddChild(decodeButton)
|
|
|
|
local oldText = ""
|
|
local function OnTextChanged()
|
|
local text = Box:GetText()
|
|
if text == "" then
|
|
Label1:SetText(" ")
|
|
Label2:SetText(" ")
|
|
importButton:SetDisabled(true)
|
|
decodeButton:SetDisabled(true)
|
|
elseif oldText ~= text then
|
|
local stringType = D:GetImportStringType(text)
|
|
if stringType == "Base64" then
|
|
decodeButton:SetDisabled(false)
|
|
else
|
|
decodeButton:SetDisabled(true)
|
|
end
|
|
|
|
local profileType, profileKey = D:Decode(text)
|
|
if not profileType or (profileType and profileType == "profile" and not profileKey) then
|
|
Label1:SetText(L["Error decoding data. Import string may be corrupted!"])
|
|
Label2:SetText(" ")
|
|
importButton:SetDisabled(true)
|
|
decodeButton:SetDisabled(true)
|
|
else
|
|
Label1:SetText(
|
|
format("%s: %s%s|r", L["Importing"], E.media.hexvaluecolor, profileTypeItems[profileType] or "")
|
|
)
|
|
if profileType == "profile" then
|
|
Label2:SetText(format("%s: %s%s|r", L["Profile Name"], E.media.hexvaluecolor, profileKey))
|
|
end
|
|
importButton:SetDisabled(false)
|
|
end
|
|
|
|
--Scroll frame doesn't scroll to the bottom by itself, so let's do that now
|
|
Box.scrollFrame:UpdateScrollChildRect()
|
|
Box.scrollFrame:SetVerticalScroll(Box.scrollFrame:GetVerticalScrollRange())
|
|
|
|
oldText = text
|
|
end
|
|
end
|
|
|
|
Box.editBox:SetFocus()
|
|
--Set scripts
|
|
Box.editBox:SetScript("OnChar", nil)
|
|
Box.editBox:SetScript("OnTextChanged", OnTextChanged)
|
|
end
|
|
|
|
Frame:SetCallback("OnClose", function(widget)
|
|
--Restore changed scripts
|
|
Box.editBox:SetScript("OnChar", nil)
|
|
Box.editBox:SetScript("OnTextChanged", Box.editBox.OnTextChangedOrig)
|
|
Box.editBox:SetScript("OnCursorChanged", Box.editBox.OnCursorChangedOrig)
|
|
Box.editBox.OnTextChangedOrig = nil
|
|
Box.editBox.OnCursorChangedOrig = nil
|
|
|
|
--Clear stored export string
|
|
exportString = ""
|
|
|
|
E.Libs.AceGUI:Release(widget)
|
|
E.Libs.AceConfigDialog:Open("ElvUI")
|
|
end)
|
|
|
|
--Clear default text
|
|
Label1:SetText(" ")
|
|
Label2:SetText(" ")
|
|
|
|
--Close ElvUI OptionsUI
|
|
E.Libs.AceConfigDialog:Close("ElvUI")
|
|
|
|
GameTooltip_Hide() --The tooltip from the Export/Import button stays on screen, so hide it
|
|
end
|
|
|
|
--Create Profiles Table
|
|
E.Options.args.profiles = E.Libs.AceDBOptions:GetOptionsTable(E.data)
|
|
E.Libs.AceConfig:RegisterOptionsTable("ElvProfiles", E.Options.args.profiles)
|
|
E.Options.args.profiles.order = -10
|
|
|
|
E.Libs.DualSpec:EnhanceOptions(E.Options.args.profiles, E.data)
|
|
|
|
if not E.Options.args.profiles.plugins then
|
|
E.Options.args.profiles.plugins = {}
|
|
end
|
|
|
|
E.Options.args.profiles.plugins.ElvUI = {
|
|
spacer = {
|
|
order = 89,
|
|
type = "description",
|
|
name = "\n\n"
|
|
},
|
|
desc = {
|
|
order = 90,
|
|
type = "description",
|
|
name = L["This feature will allow you to transfer settings to other characters."]
|
|
},
|
|
distributeProfile = {
|
|
order = 91,
|
|
type = "execute",
|
|
name = L["Share Current Profile"],
|
|
desc = L["Sends your current profile to your target."],
|
|
func = function()
|
|
if not UnitExists("target") or not UnitIsPlayer("target")
|
|
or not UnitIsFriend("player", "target") or UnitIsUnit("player", "target") then
|
|
E:Print(L["You must be targeting a player."])
|
|
return
|
|
end
|
|
|
|
local name, server = UnitName("target")
|
|
if name and (not server or server == "") then
|
|
D:Distribute(name)
|
|
elseif server then
|
|
D:Distribute(name, true)
|
|
end
|
|
end
|
|
},
|
|
distributeGlobal = {
|
|
order = 92,
|
|
type = "execute",
|
|
name = L["Share Filters"],
|
|
desc = L["Sends your filter settings to your target."],
|
|
func = function()
|
|
if not UnitExists("target") or not UnitIsPlayer("target")
|
|
or not UnitIsFriend("player", "target") or UnitIsUnit("player", "target") then
|
|
E:Print(L["You must be targeting a player."])
|
|
return
|
|
end
|
|
|
|
local name, server = UnitName("target")
|
|
if name and (not server or server == "") then
|
|
D:Distribute(name, false, true)
|
|
elseif server then
|
|
D:Distribute(name, true, true)
|
|
end
|
|
end
|
|
},
|
|
spacer2 = {
|
|
order = 93,
|
|
type = "description",
|
|
name = ""
|
|
},
|
|
exportProfile = {
|
|
order = 94,
|
|
type = "execute",
|
|
name = L["Export Profile"],
|
|
func = function()
|
|
ExportImport_Open("export")
|
|
end
|
|
},
|
|
importProfile = {
|
|
order = 95,
|
|
type = "execute",
|
|
name = L["Import Profile"],
|
|
func = function()
|
|
ExportImport_Open("import")
|
|
end
|
|
}
|
|
}
|
|
|
|
do
|
|
local _, _, enabled = GetAddOnInfo("ElvUI_Config")
|
|
if enabled then
|
|
E:StaticPopup_Show("ELVUI_CONFIG_FOUND")
|
|
end
|
|
end |