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.

788 lines
31 KiB

local PA = _G.ProjectAzilroka
local stAM = PA:NewModule('stAddonManager', 'AceEvent-3.0')
PA.stAM, _G.stAddonManager = stAM, stAM
_G.stAddonManagerProfilesDB = {}
_G.stAddonManagerServerDB = {}
stAM.Title = PA.ACL['|cFF16C3F2st|r|cFFFFFFFFAddonManager|r']
stAM.Description = PA.ACL['A simple and minimalistic addon to disable/enabled addons without logging out.']
stAM.Authors = 'Azilroka Safturento'
stAM.isEnabled = false
local _G = _G
local unpack = unpack
local tinsert = tinsert
local wipe = wipe
local pairs = pairs
local sort = sort
local format = format
local strlen = strlen
local strlower = strlower
local strfind = strfind
local min = min
local max = max
local concat = table.concat
local select = select
local gsub = gsub
local GetNumAddOns = GetNumAddOns
local GetAddOnInfo = GetAddOnInfo
local GetAddOnDependencies = GetAddOnDependencies
local GetAddOnOptionalDependencies = GetAddOnOptionalDependencies
local DisableAddOn = DisableAddOn
local EnableAddOn = EnableAddOn
local GetAddOnMetadata = GetAddOnMetadata
local DisableAllAddOns = DisableAllAddOns
local EnableAllAddOns = EnableAllAddOns
local CreateFrame = CreateFrame
local UIParent = UIParent
local GameTooltip = GameTooltip
local IsShiftKeyDown = IsShiftKeyDown
local MAX_BUTTONS = 50
_G.StaticPopupDialogs.STADDONMANAGER_OVERWRITEPROFILE = {
button1 = PA.ACL['Overwrite'],
button2 = PA.ACL['Cancel'],
timeout = 0,
whileDead = 1,
enterClicksFirstButton = 1,
hideOnEscape = 1,
}
_G.StaticPopupDialogs.STADDONMANAGER_NEWPROFILE = {
text = PA.ACL['Enter a name for your new Addon Profile:'],
button1 = PA.ACL['Create'],
button2 = PA.ACL['Cancel'],
timeout = 0,
hasEditBox = 1,
whileDead = 1,
OnAccept = function(self) stAM:NewAddOnProfile(self.editBox:GetText()) end,
EditBoxOnEnterPressed = function(self) stAM:NewAddOnProfile(self:GetText()) self:GetParent():Hide() end,
EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
}
_G.StaticPopupDialogs.STADDONMANAGER_RENAMEPROFILE = {
text = PA.ACL['Enter a name for your AddOn Profile:'],
button1 = PA.ACL['Update'],
button2 = PA.ACL['Cancel'],
timeout = 0,
hasEditBox = 1,
whileDead = 1,
EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
}
_G.StaticPopupDialogs.STADDONMANAGER_DELETECONFIRMATION = {
button1 = PA.ACL['Delete'],
button2 = PA.ACL['Cancel'],
timeout = 0,
whileDead = 1,
enterClicksFirstButton = 1,
hideOnEscape = 1,
}
local function strtrim(str)
return gsub(str, '^%s*(.-)%s*$', '%1')
end
function stAM:BuildFrame()
local Frame = CreateFrame('Frame', 'stAMFrame', UIParent)
local Close = CreateFrame('Button', 'stAMCloseButton', Frame)
local Search = CreateFrame('EditBox', 'stAMSearchBox', Frame, 'SearchBoxTemplate')
local Profiles = CreateFrame('Button', 'stAMProfiles', Frame)
local AddOns = CreateFrame('Frame', 'stAMAddOns', Frame)
local Slider = CreateFrame('Slider', nil, AddOns)
local Reload = CreateFrame('Button', 'stAMReload', Frame)
local RequiredAddons = CreateFrame('CheckButton', nil, Frame)
local OptionalAddons = CreateFrame('CheckButton', nil, Frame)
local CharacterSelect = CreateFrame('Button', nil, Frame)
local Title = Frame:CreateFontString(nil, 'OVERLAY')
-- Defines
local font, fontSize, fontFlag = PA.LSM:Fetch('font', stAM.db.Font), stAM.db.FontSize, stAM.db.FontFlag
local Texture = PA.LSM:Fetch('statusbar', stAM.db.CheckTexture)
local FrameWidth = stAM.db.FrameWidth
local NumAddOns = stAM.db.NumAddOns
local Color = stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor
local Width, Height = stAM.db.ButtonWidth, stAM.db.ButtonHeight
Frame:SetSize(FrameWidth, 10 + NumAddOns * 25 + 40)
Frame:SetPoint('CENTER', UIParent, 'CENTER', 0, 0)
PA:SetTemplate(Frame)
Frame:Hide()
Frame:SetFrameStrata('HIGH')
Frame:SetClampedToScreen(true)
Frame:SetMovable(true)
Frame:EnableMouse(true)
Frame:SetScript('OnMouseDown', Frame.StartMoving)
Frame:SetScript('OnMouseUp', Frame.StopMovingOrSizing)
Title:SetPoint('TOPLEFT', 0, -5)
Title:SetPoint('TOPRIGHT', 0, -5)
Title:SetFont(font, 14, fontFlag)
Title:SetText(stAM.Title)
Title:SetJustifyH('CENTER')
Title:SetJustifyV('MIDDLE')
PA:SetTemplate(Close)
Close:SetPoint('TOPRIGHT', -3, -3)
Close:SetSize(16, 16)
Close:SetScript('OnEnter', function() Close:SetBackdropBorderColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor)) end)
Close:SetScript('OnLeave', function() PA:SetTemplate(Close) end)
Close:SetScript('OnClick', function() Frame:Hide() end)
local Mask = Close:CreateMaskTexture()
Mask:SetTexture('Interface/AddOns/ProjectAzilroka/Media/Textures/Close', 'CLAMPTOBLACKADDITIVE', 'CLAMPTOBLACKADDITIVE')
Mask:SetSize(10, 10)
Mask:SetPoint('CENTER')
Close.Mask = Mask
Close:SetNormalTexture(Texture)
Close:SetPushedTexture(Texture)
local Normal, Pushed = Close:GetNormalTexture(), Close:GetPushedTexture()
PA:SetInside(Normal, Close)
Normal:SetVertexColor(1, 1, 1)
Normal:AddMaskTexture(Mask)
PA:SetInside(Pushed, Close)
Pushed:SetVertexColor(1, .2, .2)
Pushed:AddMaskTexture(Mask)
Search:SetPoint('TOPLEFT', Title, 'BOTTOMLEFT', 10, -10)
Search:SetPoint('BOTTOMRIGHT', Profiles, 'BOTTOMLEFT', -5, 0)
Search:SetSize(1, 20)
Search.Left:SetTexture()
Search.Middle:SetTexture()
Search.Right:SetTexture()
PA:SetTemplate(Search)
Search.AddOns = {}
Search:HookScript('OnEscapePressed', function() stAM:UpdateAddonList() end)
Search:HookScript('OnTextChanged', function(_, userInput) stAM.scrollOffset = 0 stAM.searchQuery = userInput stAM:UpdateAddonList() end)
Search:HookScript('OnEditFocusGained', function() Search:SetBackdropBorderColor(unpack(stAM.db.CheckColor)) Search:HighlightText() end)
Search:HookScript('OnEditFocusLost', function() PA:SetTemplate(Search) Search:HighlightText(0, 0) PA:SetTemplate(Search) end)
Search.clearButton:HookScript('OnClick', stAM.UpdateAddonList)
PA:SetTemplate(Reload)
Reload:SetSize(70, 20)
Reload:SetScript('OnEnter', function() Reload:SetBackdropBorderColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor)) end)
Reload:SetScript('OnLeave', function() PA:SetTemplate(Reload) end)
Reload:SetScript('OnClick', _G.ReloadUI)
Reload.Text = Reload:CreateFontString(nil, 'OVERLAY')
Reload.Text:SetFont(font, 12, fontFlag)
Reload.Text:SetText(PA.ACL['Reload'])
Reload.Text:SetPoint('CENTER', 0, 0)
Reload.Text:SetJustifyH('CENTER')
Reload:SetPoint('TOPLEFT', AddOns, 'BOTTOMLEFT', 0, -10)
RequiredAddons:SetPoint('LEFT', Reload, 'RIGHT', 50, 0)
PA:SetTemplate(RequiredAddons)
RequiredAddons:SetSize(20, 20)
RequiredAddons:SetScript('OnClick', function()
stAM.db.EnableRequiredAddons = not stAM.db.EnableRequiredAddons
end)
RequiredAddons:SetScript('OnEnter', function()
GameTooltip:SetOwner(RequiredAddons, 'ANCHOR_TOPRIGHT', 0, 4)
GameTooltip:ClearLines()
GameTooltip:AddLine(PA.ACL['Enable Required AddOns'], 1, 1, 1)
GameTooltip:AddLine(PA.ACL['This will attempt to enable all the "Required" AddOns for the selected AddOn.'], 1, 1, 1)
GameTooltip:Show()
end)
RequiredAddons:SetScript('OnLeave', function() PA:SetTemplate(RequiredAddons) GameTooltip:Hide() end)
RequiredAddons.CheckTexture = RequiredAddons:CreateTexture(nil, 'OVERLAY', nil, 1)
RequiredAddons.CheckTexture:SetTexture(Texture)
RequiredAddons.CheckTexture:SetVertexColor(unpack(Color))
PA:SetInside(RequiredAddons.CheckTexture, RequiredAddons)
RequiredAddons:SetCheckedTexture(RequiredAddons.CheckTexture)
RequiredAddons:SetHighlightTexture('')
RequiredAddons.Text = RequiredAddons:CreateFontString(nil, 'OVERLAY')
RequiredAddons.Text:SetPoint('LEFT', RequiredAddons, 'RIGHT', 5, 0)
RequiredAddons.Text:SetFont(font, 12, fontFlag)
RequiredAddons.Text:SetText(PA.ACL['Required'])
RequiredAddons:SetChecked(stAM.db.EnableRequiredAddons)
CharacterSelect:SetPoint('TOPRIGHT', AddOns, 'BOTTOMRIGHT', 0, -10)
CharacterSelect.DropDown = CreateFrame('Frame', 'stAMCharacterSelectDropDown', CharacterSelect, 'UIDropDownMenuTemplate')
CharacterSelect:SetSize(150, 20)
PA:SetTemplate(CharacterSelect)
CharacterSelect:SetScript('OnEnter', function() CharacterSelect:SetBackdropBorderColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor)) end)
CharacterSelect:SetScript('OnLeave', function() PA:SetTemplate(CharacterSelect) end)
CharacterSelect:SetScript('OnClick', function() _G.EasyMenu(stAM.Menu, CharacterSelect.DropDown, CharacterSelect, 0, 38 + (stAM.MenuOffset * 16), 'MENU', 5) end)
CharacterSelect.Text = CharacterSelect:CreateFontString(nil, 'OVERLAY')
CharacterSelect.Text:SetFont(font, 12, fontFlag)
CharacterSelect.Text:SetText(PA.ACL['Character Select'])
CharacterSelect.Text:SetPoint('CENTER', 0, 0)
CharacterSelect.Text:SetJustifyH('CENTER')
Profiles:SetPoint('TOPRIGHT', Title, 'BOTTOMRIGHT', -10, -10)
PA:SetTemplate(Profiles)
Profiles:SetSize(70, 20)
Profiles:SetScript('OnEnter', function() Profiles:SetBackdropBorderColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor)) end)
Profiles:SetScript('OnLeave', function() PA:SetTemplate(Profiles) end)
Profiles:SetScript('OnClick', function() stAM:ToggleProfiles() end)
Profiles.Text = Profiles:CreateFontString(nil, 'OVERLAY')
Profiles.Text:SetFont(font, 12, fontFlag)
Profiles.Text:SetText(PA.ACL['Profiles'])
Profiles.Text:SetPoint('CENTER', 0, 0)
Profiles.Text:SetJustifyH('CENTER')
AddOns:SetPoint('TOPLEFT', Search, 'BOTTOMLEFT', 0, -5)
AddOns:SetPoint('TOPRIGHT', Profiles, 'BOTTOMRIGHT', 0, -5)
AddOns:SetHeight(NumAddOns * (Height + 5) + 15)
PA:SetTemplate(AddOns)
AddOns.Buttons = {}
AddOns:EnableMouse(true)
AddOns:EnableMouseWheel(true)
Slider:SetPoint('RIGHT', -2, 0)
Slider:SetWidth(12)
Slider:SetHeight(NumAddOns * (Height + 5) + 11)
Slider:SetThumbTexture(PA.LSM:Fetch('background', 'Solid'))
Slider:SetOrientation('VERTICAL')
Slider:SetValueStep(1)
PA:SetTemplate(Slider)
Slider:SetMinMaxValues(0, 1)
Slider:SetValue(0)
Slider:EnableMouse(true)
Slider:EnableMouseWheel(true)
local Thumb = Slider:GetThumbTexture()
Thumb:SetSize(8, 16)
Thumb:SetVertexColor(unpack(Color))
AddOns.ScrollBar = Slider
local OnScroll = function(_, delta)
local numAddons = stAM.searchQuery and #Search.AddOns or #stAM.AddOnInfo
if numAddons < stAM.db.NumAddOns then return end
if IsShiftKeyDown() then
if delta == 1 then
stAM.scrollOffset = max(0, stAM.scrollOffset - stAM.db.NumAddOns)
elseif delta == -1 then
stAM.scrollOffset = min(numAddons - stAM.db.NumAddOns, stAM.scrollOffset + stAM.db.NumAddOns)
end
else
if delta == 1 and stAM.scrollOffset > 0 then
stAM.scrollOffset = stAM.scrollOffset - 1
elseif delta == -1 then
if stAM.scrollOffset < numAddons - stAM.db.NumAddOns then
stAM.scrollOffset = stAM.scrollOffset + 1
end
end
end
Slider:SetMinMaxValues(0, (numAddons - stAM.db.NumAddOns))
Slider:SetValue(stAM.scrollOffset)
stAM:UpdateAddonList()
end
AddOns:SetScript('OnMouseWheel', OnScroll)
Slider:SetScript('OnMouseWheel', OnScroll)
Slider:SetScript('OnValueChanged', function(_, value)
stAM.scrollOffset = value
OnScroll()
end)
for i = 1, MAX_BUTTONS do
local CheckButton = CreateFrame('CheckButton', 'stAMCheckButton_'..i, AddOns)
CheckButton:Hide()
PA:SetTemplate(CheckButton)
CheckButton:SetSize(Width, Height)
CheckButton:SetPoint(unpack(i == 1 and {'TOPLEFT', AddOns, 'TOPLEFT', 10, -10} or {'TOP', AddOns.Buttons[i-1], 'BOTTOM', 0, -5}))
CheckButton:SetScript('OnClick', function()
if CheckButton.name then
if PA:IsAddOnEnabled(CheckButton.name, stAM.SelectedCharacter) then
DisableAddOn(CheckButton.name, stAM.SelectedCharacter)
else
EnableAddOn(CheckButton.name, stAM.SelectedCharacter)
if stAM.db.EnableRequiredAddons and CheckButton.required then
for _, AddOn in pairs(CheckButton.required) do
EnableAddOn(AddOn)
end
end
end
stAM:UpdateAddonList()
end
end)
CheckButton:SetScript('OnEnter', function()
GameTooltip:SetOwner(CheckButton, 'ANCHOR_TOPRIGHT', 0, 4)
GameTooltip:ClearLines()
GameTooltip:AddDoubleLine('AddOn:', CheckButton.title, 1, 1, 1, 1, 1, 1)
GameTooltip:AddDoubleLine(PA.ACL['Authors:'], CheckButton.authors, 1, 1, 1, 1, 1, 1)
GameTooltip:AddDoubleLine(PA.ACL['Version:'], CheckButton.version, 1, 1, 1, 1, 1, 1)
if CheckButton.notes ~= nil then
GameTooltip:AddDoubleLine('Notes:', CheckButton.notes, 1, 1, 1, 1, 1, 1)
end
if CheckButton.required or CheckButton.optional then
GameTooltip:AddLine(' ')
end
if CheckButton.required then
GameTooltip:AddDoubleLine('Required Dependencies:', concat(CheckButton.required, ', '), 1, 1, 1, 1, 1, 1)
end
if CheckButton.optional then
GameTooltip:AddDoubleLine('Optional Dependencies:', concat(CheckButton.optional, ', '), 1, 1, 1, 1, 1, 1)
end
GameTooltip:Show()
CheckButton:SetBackdropBorderColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor))
end)
CheckButton:SetScript('OnLeave', function() PA:SetTemplate(CheckButton) GameTooltip:Hide() end)
local Checked = CheckButton:CreateTexture(nil, 'OVERLAY', nil, 1)
Checked:SetTexture(Texture)
Checked:SetVertexColor(unpack(Color))
PA:SetInside(Checked, CheckButton)
CheckButton.CheckTexture = Checked
CheckButton:SetCheckedTexture(Checked)
CheckButton:SetHighlightTexture('')
local Text = CheckButton:CreateFontString(nil, 'OVERLAY')
Text:SetFont(font, fontSize, fontFlag)
Text:SetText('')
Text:SetJustifyH('CENTER')
Text:ClearAllPoints()
Text:SetPoint('LEFT', CheckButton, 'RIGHT', 10, 0)
Text:SetPoint('TOP', CheckButton, 'TOP')
Text:SetPoint('BOTTOM', CheckButton, 'BOTTOM')
Text:SetPoint('RIGHT', AddOns, 'CENTER', 0, 0)
Text:SetJustifyH('LEFT')
CheckButton.Text = Text
local StatusText = CheckButton:CreateFontString(nil, 'OVERLAY')
StatusText:SetFont(font, fontSize, fontFlag)
StatusText:SetText('')
StatusText:SetJustifyH('CENTER')
StatusText:ClearAllPoints()
StatusText:SetPoint('LEFT', Text, 'RIGHT', 0, 0)
StatusText:SetPoint('TOP', CheckButton, 'TOP')
StatusText:SetPoint('BOTTOM', CheckButton, 'BOTTOM')
StatusText:SetPoint('RIGHT', AddOns, 'RIGHT', -10, 0)
StatusText:SetJustifyH('LEFT')
CheckButton.StatusText = StatusText
local Icon = CheckButton:CreateTexture(nil, 'OVERLAY')
Icon:SetTexture('Interface/AddOns/ProjectAzilroka/Media/Textures/QuestBang')
Icon:SetPoint('CENTER', CheckButton, 'RIGHT', 10, 0)
Icon:SetSize(32, 32)
CheckButton.Icon = Icon
AddOns.Buttons[i] = CheckButton
end
Frame.Title = Title
Frame.Close = Close
Frame.Reload = Reload
Frame.RequiredAddons = RequiredAddons
Frame.OptionalAddons = OptionalAddons
Frame.Search = Search
Frame.CharacterSelect = CharacterSelect
Frame.Profiles = Profiles
Frame.AddOns = AddOns
Frame.AddOns:SetHeight(stAM.db.NumAddOns * (stAM.db.ButtonHeight + 5) + 15)
Frame:SetSize(stAM.db.FrameWidth, Frame.Title:GetHeight() + Frame.Search:GetHeight() + Frame.AddOns:GetHeight() + Frame.Profiles:GetHeight() + 40)
stAM.Frame = Frame
tinsert(_G.UISpecialFrames, stAM.Frame:GetName())
_G.GameMenuButtonAddons:SetScript('OnClick', function() stAM.Frame:Show() _G.HideUIPanel(_G.GameMenuFrame) end)
end
function stAM:NewAddOnProfile(name, overwrite)
if _G.stAddonManagerProfilesDB[name] and (not overwrite) then
_G.StaticPopupDialogs['STADDONMANAGER_OVERWRITEPROFILE'].text = format(PA.ACL['There is already a profile named %s. Do you want to overwrite it?'], name)
_G.StaticPopupDialogs['STADDONMANAGER_OVERWRITEPROFILE'].OnAccept = function() stAM:NewAddOnProfile(name, true) end
_G.StaticPopup_Show('STADDONMANAGER_OVERWRITEPROFILE')
return
end
_G.stAddonManagerProfilesDB[name] = {}
for i = 1, #stAM.AddOnInfo do
local AddOn, isEnabled = stAM.AddOnInfo[i].Name, PA:IsAddOnEnabled(i, stAM.SelectedCharacter)
if isEnabled then
tinsert(_G.stAddonManagerProfilesDB[name], AddOn)
end
end
stAM:UpdateProfiles()
end
function stAM:InitProfiles()
local ProfileMenu = CreateFrame('Frame', 'stAMProfileMenu', stAM.Frame)
ProfileMenu:SetPoint('TOPLEFT', stAM.Frame, 'TOPRIGHT', 3, 0)
ProfileMenu:SetSize(250, 50)
PA:SetTemplate(ProfileMenu)
ProfileMenu:Hide()
for _, name in pairs({'EnableAll', 'DisableAll', 'NewButton'}) do
local Button = CreateFrame('Button', nil, ProfileMenu)
PA:SetTemplate(Button)
Button:SetSize(stAM.db.ButtonWidth, stAM.db.ButtonHeight)
Button:SetScript('OnEnter', function() Button:SetBackdropBorderColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor)) end)
Button:SetScript('OnLeave', function() PA:SetTemplate(Button) end)
Button.Text = Button:CreateFontString(nil, 'OVERLAY')
Button.Text:SetFont(PA.LSM:Fetch('font', stAM.db.Font), 12, 'OUTLINE')
Button.Text:SetPoint('CENTER', 0, 0)
Button.Text:SetJustifyH('CENTER')
ProfileMenu[name] = Button
end
ProfileMenu.EnableAll.Text:SetText(PA.ACL['Enable All'])
ProfileMenu.EnableAll:SetPoint('TOPLEFT', ProfileMenu, 'TOPLEFT', 10, -10)
ProfileMenu.EnableAll:SetPoint('TOPRIGHT', ProfileMenu, 'TOP', -3, -10)
ProfileMenu.EnableAll:SetScript('OnClick', function() EnableAllAddOns(stAM.SelectedCharacter) stAM:UpdateAddonList() end)
ProfileMenu.DisableAll.Text:SetText(PA.ACL['Disable All'])
ProfileMenu.DisableAll:SetPoint('TOPRIGHT', ProfileMenu, 'TOPRIGHT', -10, -10)
ProfileMenu.DisableAll:SetPoint('TOPLEFT', ProfileMenu, 'TOP', 2, -10)
ProfileMenu.DisableAll:SetScript('OnClick', function() DisableAllAddOns(stAM.SelectedCharacter) stAM:UpdateAddonList() end)
ProfileMenu.NewButton.Text:SetText(PA.ACL['New Profile'])
ProfileMenu.NewButton:SetPoint('TOPLEFT', ProfileMenu.EnableAll, 'BOTTOMLEFT', 0, -5)
ProfileMenu.NewButton:SetPoint('TOPRIGHT', ProfileMenu.DisableAll, 'BOTTOMRIGHT', 0, -5)
ProfileMenu.NewButton:SetScript('OnClick', function() _G.StaticPopup_Show('STADDONMANAGER_NEWPROFILE') end)
ProfileMenu.Buttons = {}
for i = 1, MAX_BUTTONS do
local Pullout = CreateFrame('Frame', nil, ProfileMenu)
Pullout:SetWidth(210)
Pullout:SetHeight(stAM.db.ButtonHeight)
Pullout:Hide()
for _, Frame in pairs({'Load', 'Delete', 'Update'}) do
local Button = CreateFrame('Button', nil, Pullout)
PA:SetTemplate(Button)
Button:SetSize(73, stAM.db.ButtonHeight)
Button:RegisterForClicks('AnyDown')
Button:SetScript('OnEnter', function() Button:SetBackdropBorderColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor)) end)
Button:SetScript('OnLeave', function() PA:SetTemplate(Button) end)
Button.Text = Button:CreateFontString(nil, 'OVERLAY')
Button.Text:SetFont(PA.LSM:Fetch('font', stAM.db.Font), 12, 'OUTLINE')
Button.Text:SetPoint('CENTER', 0, 0)
Button.Text:SetJustifyH('CENTER')
Pullout[Frame] = Button
end
Pullout.Load:SetPoint('LEFT', Pullout, 0, 0)
Pullout.Load.Text:SetText('Load')
Pullout.Load:SetScript('OnClick', function(_, btn)
if btn == 'RightButton' then
local Dialog = _G.StaticPopupDialogs.STADDONMANAGER_RENAMEPROFILE
Dialog.OnAccept = function(dialog)
_G.stAddonManagerProfilesDB[Pullout.Name] = nil
stAM:NewAddOnProfile(dialog.editBox:GetText())
stAM:UpdateProfiles()
end
Dialog.EditBoxOnEnterPressed = function(editBox)
_G.stAddonManagerProfilesDB[Pullout.Name] = nil
stAM:NewAddOnProfile(editBox:GetText())
stAM:UpdateProfiles()
editBox:GetParent():Hide()
end
_G.StaticPopup_Show('STADDONMANAGER_RENAMEPROFILE')
else
if not IsShiftKeyDown() then
DisableAllAddOns(stAM.SelectedCharacter)
end
for _, AddOn in pairs(_G.stAddonManagerProfilesDB[Pullout.Name]) do
EnableAddOn(AddOn, stAM.SelectedCharacter)
end
stAM:UpdateAddonList()
end
end)
Pullout.Update:SetPoint('LEFT', Pullout.Load, 'RIGHT', 5, 0)
Pullout.Update.Text:SetText(PA.ACL['Update'])
Pullout.Update:SetScript('OnClick', function() stAM:NewAddOnProfile(Pullout.Name, true) end)
Pullout.Delete:SetPoint('LEFT', Pullout.Update, 'RIGHT', 5, 0)
Pullout.Delete.Text:SetText(PA.ACL['Delete'])
Pullout.Delete:SetScript('OnClick', function()
local dialog = _G.StaticPopupDialogs['STADDONMANAGER_DELETECONFIRMATION']
dialog.text = format(PA.ACL['Are you sure you want to delete %s?'], Pullout.Name)
dialog.OnAccept = function() _G.stAddonManagerProfilesDB[Pullout.Name] = nil stAM:UpdateProfiles() end
_G.StaticPopup_Show('STADDONMANAGER_DELETECONFIRMATION')
end)
ProfileMenu.Buttons[i] = Pullout
end
stAM.ProfileMenu = ProfileMenu
end
function stAM:UpdateProfiles()
local ProfileMenu = stAM.ProfileMenu
wipe(stAM.Profiles)
for name, _ in pairs(_G.stAddonManagerProfilesDB) do tinsert(stAM.Profiles, name) end
sort(stAM.Profiles)
local PreviousButton
for i, Button in ipairs(ProfileMenu.Buttons) do
local isShown = i <= min(#stAM.Profiles, MAX_BUTTONS)
if isShown then
Button.Load.Text:SetText(stAM.Profiles[i])
end
Button.Name = isShown and stAM.Profiles[i] or nil
Button:SetShown(isShown)
if i == 1 then
Button:SetPoint('TOPLEFT', ProfileMenu.NewButton, 'BOTTOMLEFT', 0, -5)
else
Button:SetPoint('TOP', PreviousButton, 'BOTTOM', 0, -5)
end
PreviousButton = Button
end
ProfileMenu:SetHeight((min(#stAM.Profiles, MAX_BUTTONS) + 2) * (stAM.db.ButtonHeight + 5) + 15)
end
function stAM:ToggleProfiles()
_G.ToggleFrame(stAM.ProfileMenu)
stAM:UpdateProfiles()
end
function stAM:UpdateAddonList()
wipe(stAM.Frame.Search.AddOns)
if stAM.searchQuery then
local query = strlower(strtrim(stAM.Frame.Search:GetText()))
if (strlen(query) == 0) then
stAM.searchQuery = false
end
for i, AddOn in ipairs(stAM.AddOnInfo) do
local name, title, authors = AddOn.Name, AddOn.Title, AddOn.Authors
if strfind(strlower(name), query, nil, true) or strfind(strlower(title), query, nil, true) or (authors and strfind(strlower(authors), query, nil, true)) then
tinsert(stAM.Frame.Search.AddOns, i)
end
end
end
for i, button in ipairs(stAM.Frame.AddOns.Buttons) do
local addonIndex = (not stAM.searchQuery and (stAM.scrollOffset + i)) or stAM.Frame.Search.AddOns[stAM.scrollOffset + i]
local info = stAM.AddOnInfo[addonIndex]
if addonIndex and addonIndex <= #stAM.AddOnInfo then
button.name, button.title, button.authors, button.version, button.notes, button.required, button.optional = info.Name, info.Title, info.Authors, info.Version, info.Notes, info.Required, info.Optional
button.Text:SetText(button.title)
button.Icon:SetShown(info.Missing or info.Disabled)
button.StatusText:SetShown(info.Missing or info.Disabled)
if info.Missing or info.Disabled then
if info.Missing then
button.Icon:SetVertexColor(.77, .12, .24)
button.StatusText:SetVertexColor(.77, .12, .24)
button.StatusText:SetText(PA.ACL['Missing: ']..concat(info.Missing, ', '))
else
button.Icon:SetVertexColor(1, .8, .1)
button.StatusText:SetVertexColor(1, .8, .1)
button.StatusText:SetText(PA.ACL['Disabled: ']..concat(info.Disabled, ', '))
end
button.Text:SetPoint('LEFT', button.Icon, 'CENTER', 5, 0)
button.Text:SetPoint('RIGHT', stAM.Frame.AddOns, 'CENTER', 0, 0)
else
button.Text:SetPoint('LEFT', button, 'RIGHT', 5, 0)
button.Text:SetPoint('RIGHT', stAM.Frame.AddOns, 'RIGHT', -10, 0)
end
button:SetChecked(PA:IsAddOnPartiallyEnabled(addonIndex, stAM.SelectedCharacter) or PA:IsAddOnEnabled(addonIndex, stAM.SelectedCharacter))
button.CheckTexture:SetVertexColor(unpack(PA:IsAddOnPartiallyEnabled(addonIndex, stAM.SelectedCharacter) and {.6, .6, .6} or stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor))
button:SetShown(i <= min(#stAM.Frame.Search.AddOns > 0 and #stAM.Frame.Search.AddOns or stAM.db.NumAddOns, stAM.db.NumAddOns))
else
button:SetShown(false)
end
end
end
function stAM:Update()
if not stAM.Frame then return end
stAM.Frame:SetSize(stAM.db.FrameWidth, stAM.Frame.Title:GetHeight() + 5 + stAM.Frame.Search:GetHeight() + 5 + stAM.Frame.AddOns:GetHeight() + 10 + stAM.Frame.Profiles:GetHeight() + 20)
stAM.Frame.AddOns:SetHeight(stAM.db.NumAddOns * (stAM.db.ButtonHeight + 5) + 15)
stAM.Frame.AddOns.ScrollBar:SetHeight(stAM.db.NumAddOns * (stAM.db.ButtonHeight + 5) + 11)
local font, fontSize, fontFlag = PA.LSM:Fetch('font', stAM.db.Font), stAM.db.FontSize, stAM.db.FontFlag
for _, CheckButton in ipairs(stAM.Frame.AddOns.Buttons) do
CheckButton:SetSize(stAM.db.ButtonWidth, stAM.db.ButtonHeight)
CheckButton.Text:SetFont(font, fontSize, fontFlag)
CheckButton.StatusText:SetFont(font, fontSize, fontFlag)
CheckButton.CheckTexture:SetTexture(PA.LSM:Fetch('statusbar', stAM.db.CheckTexture))
CheckButton.CheckTexture:SetVertexColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor))
CheckButton:SetCheckedTexture(CheckButton.CheckTexture)
end
stAM.Frame.AddOns.ScrollBar:GetThumbTexture():SetVertexColor(unpack(stAM.db.ClassColor and PA.ClassColor or stAM.db.CheckColor))
stAM.Frame.Title:SetFont(font, 14, fontFlag)
stAM.Frame.Search:SetFont(font, 12, fontFlag)
stAM.Frame.Reload.Text:SetFont(font, 12, fontFlag)
stAM.Frame.Profiles.Text:SetFont(font, 12, fontFlag)
stAM.Frame.CharacterSelect.Text:SetFont(font, 12, fontFlag)
stAM.Frame.RequiredAddons.Text:SetFont(font, 12, fontFlag)
stAM.Frame.RequiredAddons:SetChecked(stAM.db.EnableRequiredAddons)
stAM.Frame.OptionalAddons:SetChecked(stAM.db.EnableOptionalAddons)
stAM.ProfileMenu.EnableAll.Text:SetFont(font, 12, fontFlag)
stAM.ProfileMenu.DisableAll.Text:SetFont(font, 12, fontFlag)
stAM.ProfileMenu.NewButton.Text:SetFont(font, 12, fontFlag)
for _, Button in ipairs(stAM.ProfileMenu.Buttons) do
Button.Load.Text:SetFont(font, 12, fontFlag)
Button.Update.Text:SetFont(font, 12, fontFlag)
Button.Delete.Text:SetFont(font, 12, fontFlag)
end
stAM:UpdateAddonList()
end
function stAM:GetOptions()
local stAddonManager = PA.ACH:Group(stAM.Title, stAM.Description, nil, nil, function(info) return stAM.db[info[#info]] end, function(info, value) stAM.db[info[#info]] = value stAM:Update() end)
PA.Options.args.stAddonManager = stAddonManager
stAddonManager.args.Description = PA.ACH:Description(stAM.Description, 0)
stAddonManager.args.Enable = PA.ACH:Toggle(PA.ACL['Enable'], nil, 1, nil, nil, nil, nil, function(info, value) stAM.db[info[#info]] = value if not stAM.isEnabled then stAM:Initialize() else _G.StaticPopup_Show('PROJECTAZILROKA_RL') end end)
stAddonManager.args.General = PA.ACH:Group(PA.ACL['General'], nil, 2)
stAddonManager.args.General.inline = true
stAddonManager.args.General.args.NumAddOns = PA.ACH:Range(PA.ACL['# Shown AddOns'], nil, 1, { min = 3, max = MAX_BUTTONS, step = 1 })
stAddonManager.args.General.args.FrameWidth = PA.ACH:Range(PA.ACL['Frame Width'], nil, 2, { min = 250, max = 2048, step = 2 })
stAddonManager.args.General.args.ButtonHeight = PA.ACH:Range(PA.ACL['Button Height'], nil, 3, { min = 3, max = 30, step = 1 })
stAddonManager.args.General.args.ButtonWidth = PA.ACH:Range(PA.ACL['Button Width'], nil, 4, { min = 3, max = 30, step = 1 })
stAddonManager.args.General.args.EnableRequiredAddons = PA.ACH:Toggle(PA.ACL['Enable Required AddOns'], PA.ACL['This will attempt to enable all the "Required" AddOns for the selected AddOn.'], 5)
stAddonManager.args.General.args.CheckTexture = PA.ACH:SharedMediaStatusbar(PA.ACL['Texture'], nil, 6)
stAddonManager.args.General.args.CheckColor = PA.ACH:Color(COLOR_PICKER, nil, 2, true, nil, function(info) return unpack(stAM.db[info[#info]]) end, function(info, r, g, b, a) stAM.db[info[#info]] = { r, g, b, a} stAM:Update() end, function() return stAM.db.ClassColor end)
stAddonManager.args.General.args.ClassColor = PA.ACH:Toggle(PA.ACL['Class Color Check Texture'], nil, 8)
stAddonManager.args.General.args.FontSettings = PA.ACH:Group(PA.ACL['Font Settings'], nil, -1)
stAddonManager.args.General.args.FontSettings.inline = true
stAddonManager.args.General.args.FontSettings.args.Font = PA.ACH:SharedMediaFont(PA.ACL['Font'], nil, 1)
stAddonManager.args.General.args.FontSettings.args.FontSize = PA.ACH:Range(FONT_SIZE, nil, 2, { min = 6, max = 22, step = 1 })
stAddonManager.args.General.args.FontSettings.args.FontFlag = PA.ACH:FontFlags(PA.ACL['Font Outline'], nil, 3)
stAddonManager.args.AuthorHeader = PA.ACH:Header(PA.ACL['Authors:'], -2)
stAddonManager.args.Authors = PA.ACH:Description(stAM.Authors, -1, 'large')
end
function stAM:BuildProfile()
PA.Defaults.profile.stAddonManager = {
Enable = true,
NumAddOns = 30,
FrameWidth = 550,
Font = 'PT Sans Narrow Bold',
FontSize = 16,
FontFlag = 'OUTLINE',
ButtonHeight = 18,
ButtonWidth = 22,
CheckColor = { 0, .66, 1},
ClassColor = false,
CheckTexture = 'Solid',
EnableRequiredAddons = true,
EnableOptionalAddons = false,
}
end
function stAM:UpdateSettings()
stAM.db = PA.db.stAddonManager
end
function stAM:Initialize()
stAM:UpdateSettings()
if stAM.db.Enable ~= true then
return
end
stAM.isEnabled = true
stAM.AddOnInfo = {}
stAM.Profiles = {}
for i = 1, GetNumAddOns() do
local Name, Title, Notes = GetAddOnInfo(i)
local Required, Optional = nil, nil
local MissingAddons, DisabledAddons
local HasRequired, HasOptional = GetAddOnDependencies(i), GetAddOnOptionalDependencies(i)
if HasRequired then
Required = { HasRequired }
for _, addon in pairs(Required) do
local Reason = select(5, GetAddOnInfo(addon))
if Reason == 'MISSING' then
MissingAddons = MissingAddons or {}
tinsert(MissingAddons, addon)
elseif Reason == 'DISABLED' then
DisabledAddons = DisabledAddons or {}
tinsert(DisabledAddons, addon)
end
end
end
if HasOptional then
Optional = { HasOptional }
end
local Authors = GetAddOnMetadata(i, 'Author')
local Version = GetAddOnMetadata(i, 'Version')
stAM.AddOnInfo[i] = { Name = Name, Title = Title, Authors = Authors, Version = Version, Notes = Notes, Required = Required, Optional = Optional, Missing = MissingAddons, Disabled = DisabledAddons }
end
stAM.SelectedCharacter = PA.MyName
stAM.Menu = {
{ text = 'All', checked = function() return stAM.SelectedCharacter == true end, func = function() stAM.SelectedCharacter = true stAM:UpdateAddonList() end}
}
_G.stAddonManagerServerDB[PA.MyRealm] = _G.stAddonManagerServerDB[PA.MyRealm] or {}
_G.stAddonManagerServerDB[PA.MyRealm][PA.MyName] = true
local index = 2
for Character in PA:PairsByKeys(_G.stAddonManagerServerDB[PA.MyRealm]) do
stAM.Menu[index] = { text = Character, checked = function() return stAM.SelectedCharacter == Character end, func = function() stAM.SelectedCharacter = Character stAM:UpdateAddonList() end }
index = index + 1
end
stAM.MenuOffset = index
stAM.scrollOffset = 0
stAM:BuildFrame()
stAM:InitProfiles()
stAM:Update()
end