Mercurial > wow > whichrankdoeswhat
view main.lua @ 29:8af99e154a01 1.4.4
TOC bump for 7.0, seems to work for Legion.
| author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
|---|---|
| date | Sat, 23 Jul 2016 15:53:18 -0400 |
| parents | 3a2beea01a28 |
| children |
line wrap: on
line source
local nametag, addon = ... local L = LibStub("AceLocale-3.0"):GetLocale(nametag) addon.defaults = { profile = { enable = true, guildcontrol = true, }, } addon.options = { name = "", type = 'group', childGroups = 'tab', handler = addon, -- functions listed as strings called as addon:func get = "GetOption", set = "SetOption", args = { general = { name = GENERAL, desc = L["General options"], type = 'group', order = 10, args = { version = { --name = filled in during OnInit type = 'description', fontSize = "large", cmdHidden = true, width = 'full', order = 1, }, enable = { name = ENABLE, desc = L["Use this addon"], type = 'toggle', arg = "ToggleEnable", order = 5, }, guildcontrol = { name = L["Guild Control for non-GMs"], desc = L["Make the grayed-out Guild Control button activate this addon instead."], type = 'toggle', width = 'double', -- else it gets cut off order = 10, }, break1 = { name = '', type = 'description', cmdHidden = true, width = 'full', order = 14, }, popup = { name = "/wrdw", desc = L["Toggle WRDW window"], type = 'execute', func = function() InterfaceOptionsFrameCancel:Click() HideUIPanel(GameMenuFrame) addon:BuildWindow() end, order = 15, }, }, }, --profiles = filled in OnInit }, } ----------------------------------------------------------------------------- -- other locals local AceGUI = LibStub("AceGUI-3.0") local st_rowheight = 25 local st_displayed_rows = 15 --math.floor(366/st_rowheight) local st_colwidth = 80 --65 local cols_per_group = 6 local num_flagsets local sidetabs local incomplete local flagmap -- Remove children ST widgets without explicitly Release()'ing them. As there -- are no children other than STs, no "normal" widget resources are leaked. local function DisownChildren (container) for i,v in ipairs(container.children) do container.children[i] = nil v.frame:Hide() v.frame:ClearAllPoints() end end local function setstatus(txt) addon.display:SetStatusText(txt) addon.tooltip = #txt > 40 and txt or nil end ----------------------------------------------------------------------------- addon = LibStub("AceAddon-3.0"):NewAddon(addon, nametag, "AceConsole-3.0", "AceEvent-3.0") -- Thanks to jerry for the nifty arg idea. function addon:SetOption (info, value) local name = info[#info] self.db.profile[name] = value local arg = info.arg if arg then self[arg](self) end end function addon:GetOption (info) local name = info[#info] return self.db.profile[name] end function addon:OnInitialize() self.db = LibStub("AceDB-3.0"):New("wrdwDB", self.defaults, --[[Default=]]true) local AceDBOptions = LibStub("AceDBOptions-3.0", true) if AceDBOptions then self.options.args.profiles = AceDBOptions:GetOptionsTable(self.db) self.options.args.profiles.order = 200 end self.options.args.general.args.version.name = "|cff30adffVersion " .. (GetAddOnMetadata(nametag, "Version") or "?") .. "|r" LibStub("AceConfig-3.0"):RegisterOptionsTable(nametag, self.options) self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions(nametag, "WhichRankDoesWhat") --self.optionsFrame.okay = function() pattern_editing_safe = false end --self.optionsFrame.refresh = self.optionsFrame.okay --self.optionsFrame.cancel = self.optionsFrame.okay self:SetEnabledState(self.db.profile.enable) self.OnInitialize = nil end function addon:OnEnable() self:RegisterEvent("GUILD_RANKS_UPDATE") self:RegisterChatCommand("wrdw", "OnSlashCommand") -- Ideally, most of this stuff wouldn't be done at load time at all; this -- whole addon should be LoD. if (not IsGuildLeader()) and self.db.profile.guildcontrol then local function onclick() addon:BuildWindow() end local function onenter(this) GameTooltip_AddNewbieTip(this, GUILDCONTROL, 1.0, 1.0, 1.0, "/wrdw", 1) end GuildFrame_LoadUI() if not NUM_RANK_FLAGS then UIParentLoadAddOn("Blizzard_GuildControlUI") end local function noreallyitsokay() GuildControlButton:Enable() GuildControlButton:SetScript("OnClick", onclick) GuildControlButton:SetScript("OnEnter", onenter) end hooksecurefunc("GuildInfoFrame_UpdatePermissions", noreallyitsokay) -- This doesn't seem to be used anymore...? hooksecurefunc("GuildFrame_CheckPermissions", noreallyitsokay) end end function addon:OnDisable() self:Print(L["You will need to relog or /reload to fully disable this addon."]) end function addon:ToggleEnable() if self.db.profile.enable then self:Enable() else self:Disable() end end function addon:OnSlashCommand (input) if not NUM_RANK_FLAGS then -- in case a GM didn't get it loaded earlier GuildFrame_LoadUI() UIParentLoadAddOn("Blizzard_GuildControlUI") end if not input or input:trim() == "" then if self.display and self.display:IsShown() then self.display:Hide() else self:BuildWindow() end else --LibStub("AceConfigCmd-3.0").HandleCommand(self, "wrdw", nametag, input) LibStub("AceConfigDialog-3.0"):Open(nametag) end end -- Something somewhere has changed, redo the cache do local text = '|cffff1010' .. L["Guild flags have changed!"] .. '|r ' .. L["You must close and reopen this window to display the changes."] function addon:GUILD_RANKS_UPDATE() self.perms = nil if (not incomplete) and self.display and self.display:IsVisible() then setstatus(text) end end end function addon:BuildPerms() assert(UIParentLoadAddOn("Blizzard_GuildControlUI")) local check = "|TInterface\\Buttons\\UI-CheckBox-Check:"..(st_rowheight+5).."|t" -- http://www.wowace.com/addons/lib-st/pages/set-data/minimal-dataset-format/ local p,v = {}, {} flagmap = {} num_flagsets = math.floor(NUM_RANK_FLAGS/cols_per_group + 1) for flagset = 1, num_flagsets do p[flagset] = {} end for r = 1, GuildControlGetNumRanks() do GuildControlSetRank(r) -- permissions (most special handling goes here) -- flag 14 is no longer used -- flags 15 and 16 may have numeric values not just a boolean -- flag 21 is... not included yet, apparently local flags = { GuildControlGetRankFlags() } for flagset = 1, num_flagsets do local row = { GuildControlGetRankName(r) } for c_offset = 1, cols_per_group do while true do local c = (flagset-1) * cols_per_group + c_offset --if c == 14 or c > NUM_RANK_FLAGS then break end if c > NUM_RANK_FLAGS then break end local newcol = #row + 1 flagmap[flagset..'x'..newcol] = c if c == 15 or c == 16 then local val = GetGuildBankWithdrawGoldLimit() row[newcol] = flags[c] and ((val == -1) and check or val) or "" elseif c == 14 then row[newcol] = "" else row[newcol] = flags[c] and check or "" end break end end p[flagset][r] = row end -- guild vault local banktabs = {} for t = 1, GetNumGuildBankTabs() do -- isViewable, canDeposit, editText, numWithdrawals banktabs[t] = { GuildControlGetRankName(r), GetGuildBankTabPermissions(t) } banktabs[t][2] = banktabs[t][2] and check or "" banktabs[t][3] = banktabs[t][3] and check or "" banktabs[t][4] = banktabs[t][4] and check or "" local withdraw = banktabs[t][5] banktabs[t][5] = (withdraw == -1) and check or (withdraw == 0) and "" or withdraw end v[r] = banktabs end self.perms = p -- This one needs to be turned inside-out to match the data requirements self.vault = {} for t = 1, GetNumGuildBankTabs() do self.vault[t] = {} for r = 1, #v do self.vault[t][r] = v[r][t] end end end local make_sidetab do local lastclicked local function OnClick (thistab) if thistab == lastclicked then return end for i = 1, #sidetabs do sidetabs[i]:SetChecked(false) end thistab:SetChecked(true) -- should be redundant, but just in case lastclicked = thistab if thistab.callback then thistab:callback(thistab:GetID()) end end -- Some magic numbers here wrt the index function make_sidetab (index, callback) if not sidetabs then sidetabs = {} end local tab = CreateFrame("CheckButton", "WRDWTab"..index, addon.display.frame, "SpellBookSkillLineTabTemplate", index) if index > 1 then tab:SetPoint("TOPLEFT", sidetabs[index-1], "BOTTOMLEFT", 0, -17) else tab:SetNormalTexture("Interface\\SpellBook\\GuildSpellbooktabBG") tab.TabardEmblem:Show() tab.TabardIconFrame:Show() SetLargeGuildTabardTextures("player", tab.TabardEmblem, tab:GetNormalTexture(), tab.TabardIconFrame) tab:SetPoint("TOPLEFT", addon.display.frame, "TOPRIGHT", 0, -17) end tab:SetScript("OnClick", OnClick) --tab:SetChecked(false) -- is default tab:Show() tab.callback = callback sidetabs[index] = tab return tab end function addon:BuildVaultTabs() incomplete = nil local offset = 1 -- number of tabs already made local function pick_a_tab (tab, id) DisownChildren(self.display) self.display:AddChild(self.vault_sts[id-offset]) local buttons = self.display:GetUserData("extra buttons") buttons['prev']:Disable() buttons['next']:Disable() end for t = 1, GetNumGuildBankTabs() do local name, icon = GetGuildBankTabInfo(t) incomplete = incomplete or icon == [[Interface\Icons\INV_Misc_QuestionMark]] local tab = make_sidetab(t+offset, pick_a_tab) tab:SetNormalTexture(icon) tab.tooltip = name end if incomplete then setstatus(L["Guild vault information is incomplete. Be closer to a vault, and give it some time. You may need to relog and/or open the guild roster/vault to force a client update."]) end end end -- The "closebutton" variable isn't accessible through the widget. I should -- probably just constuct an entire Frame-equse thing by hand instead... gah. local function FIXFRAME (container, ...) for i = 1, select('#',...) do local child = select(i,...) if child:GetObjectType() == "Button" and child:GetText() == CLOSE then container:SetUserData("close button", child) return end end end local function adjust_flagset (button) local key = button.button_key assert (key == 'prev' or key == 'next') local flagset = addon.current_main_st if key == 'prev' then flagset = flagset - 1 else flagset = flagset + 1 end return flagset end local function AddedButton_OnEnter (button) -- not very generic, that's okay until we need to be local high = adjust_flagset(button) * cols_per_group local low = high - cols_per_group + 1 if high > NUM_RANK_FLAGS then high = NUM_RANK_FLAGS end setstatus(L["Show flag columns %d - %d"]:format(low,high)) end local function AddedButton_OnLeave (button) setstatus("") end local function AddedButton_OnClick (button) addon:DoMainST(adjust_flagset(button)) -- the buttons may have changed state, adjust their status text if button:IsEnabled() then AddedButton_OnEnter (button) else AddedButton_OnLeave (button) end end local function AddButton (container, key, label) assert(not tonumber(key)) local all = container:GetUserData("extra buttons") or {} container:SetUserData("extra buttons", all) local n = #all local closebutton = assert(container:GetUserData("close button"), "something horrible") local b = CreateFrame("Button", nil, container.frame, "UIPanelButtonTemplate") b.button_key = key b.obj = self b:SetScript("OnClick", AddedButton_OnClick) b:SetScript("OnEnter", AddedButton_OnEnter) b:SetScript("OnLeave", AddedButton_OnLeave) b:SetText(label) b:SetHeight(20) b:SetWidth(50) -- "Close" is 100 b:SetPoint("BOTTOMRIGHT", closebutton, "BOTTOMLEFT", -5, 0) b:Show() all[n+1] = b all[key] = b for i = n, 1, -1 do local ob = all[i] ob:ClearAllPoints() ob:SetPoint("BOTTOMRIGHT", all[i+1], "BOTTOMLEFT", -5, 0) end -- The Frame's statusbar is not accessible via the Frame widget itself. -- Which is nice and properly encapsulated and all, but also inconvenient. -- We'll take the long route there. local sb = container.statustext:GetParent() assert (sb.obj == container) sb:ClearAllPoints() sb:SetPoint("BOTTOMLEFT", 15, 15) -- default sb:SetPoint("BOTTOMRIGHT", all[1], "BOTTOMLEFT", -5, 0) end local function st_OnEnter (rowFrame, cellFrame, data, cols, row, realrow, column, sttable, button, ...) if (row == nil) or (realrow == nil) then -- mouseover column header setstatus(cellFrame:GetText():gsub('\n',' ')) return true end return false -- continue with default highlighting behavior end local function st_OnLeave (rowFrame, cellFrame, data, cols, row, realrow, column, sttable, button, ...) setstatus("") return false -- continue with default un-highlighting behavior end local function st_OnClick (rowFrame, cellFrame, data, cols, row, realrow, column, sttable, button, ...) if (row == nil) or (realrow == nil) then return true end -- click column header, suppress reordering -- more here? return true -- do not do anything further end local function OnEnterStatusBar (container) if not addon.tooltip then return end GameTooltip:SetOwner (container.frame, "ANCHOR_RIGHT") GameTooltip:ClearLines() GameTooltip:AddLine (nametag) GameTooltip:AddLine (addon.tooltip, 0.8, 0.8, 0.8, 1) GameTooltip:Show() end function addon:BuildMainSTs (permissions, parent_frame) local errtxt = "flagset %d, column %d, failed to map to a flag number" -- if this language uses a trailing colon, strip it local ranklabel = GUILDCONTROL_RANKLABEL:gsub(":$","") self.main_sts = {} for flagset = 1, #permissions do local cols = {{ name = ranklabel, width = 10 * #ranklabel, }} for c = #cols+1, #permissions[flagset][1] do -- all ranks work here local f = flagmap[flagset..'x'..c] if not f then error(errtxt:format(flagset, c)) end table.insert(cols,{ -- the only special handling outside BuildPerms name = _G[f == 14 and 'UNUSED' or 'GUILDCONTROL_OPTION'..f], width = st_colwidth, }) end local ST = LibStub("ScrollingTable"):CreateST (cols, st_displayed_rows, st_rowheight, --[[highlight=]]nil, parent_frame) ST:Hide() ST:SetData(permissions[flagset], --[[minimal format=]]true) ST:RegisterEvents{ OnEnter = st_OnEnter, OnLeave = st_OnLeave, OnClick = st_OnClick, OnDoubleClick = st_OnClick, } self.main_sts[flagset] = ST end end function addon:BuildVaultSTs (permissions, parent_frame) self.vault_sts = {} local cols = { self.main_sts[1].st.cols[1], { name = GUILDCONTROL_VIEW_TAB, width = 80 }, { name = GUILDCONTROL_DEPOSIT_ITEMS, width = 80 }, { name = GUILDCONTROL_UPDATE_TEXT, width = 80 }, { name = GUILDCONTROL_WITHDRAW_ITEMS, width = 150 }, } for tab = 1, #permissions do local ST = LibStub("ScrollingTable"):CreateST (cols, st_displayed_rows, st_rowheight, --[[highlight=]]nil, parent_frame) ST:Hide() ST:SetData(permissions[tab], --[[minimal format=]]true) ST:RegisterEvents{ OnEnter = st_OnEnter, OnLeave = st_OnLeave, OnClick = st_OnClick, OnDoubleClick = st_OnClick, } self.vault_sts[tab] = ST end end function addon:DoMainST (index) self.current_main_st = index DisownChildren(self.display) self.display:AddChild(self.main_sts[index]) local buttons = self.display:GetUserData("extra buttons") buttons['prev'][index <= 1 and 'Disable' or 'Enable'](buttons['prev']) buttons['next'][index >= num_flagsets and 'Disable' or 'Enable'](buttons['next']) end -- Under normal conditions, this massive wodge is built once, and then merely -- :Show'n and :Hide'n. Only if info gets out of date do we release/destroy -- the UI elements and rebuild. function addon:BuildWindow() local need_tabs if self.display then self.display:Hide() else self.display = AceGUI:Create("Frame") self.display:SetTitle("Which Rank Does What") self.display:SetLayout("Fill") self.display:EnableResize(false) self.display:SetStatusTable{ width = (st_colwidth+4) * cols_per_group -- flag columns + 105, -- rank label column height = 500, } self.display:ApplyStatus() FIXFRAME (self.display, self.display.frame:GetChildren()) AddButton (self.display, 'prev', "<<") AddButton (self.display, 'next', ">>") self.display:SetCallback("OnEnterStatusBar", OnEnterStatusBar) self.display:SetCallback("OnLeaveStatusBar", GameTooltip_Hide) self.display:SetCallback("OnClose", function(_d) if incomplete or (not self.perms) then -- stuff changed while open self.perms = nil self.display = nil if sidetabs then for i,s in ipairs(sidetabs) do s:Hide() s:ClearAllPoints() s:SetParent(nil) -- Blizzard does this too. Huh. end end sidetabs = nil for i,b in ipairs(_d:GetUserData("extra buttons")) do b.obj = nil b:Hide() b:ClearAllPoints() b:SetParent(nil) end AceGUI:Release(_d) end end) need_tabs = true end if not self.perms then need_tabs = true self:BuildPerms() -- creates self.perms and self.vault DisownChildren(self.display) -- Could be new rows, fewer rows, changed tickboxes... ugh, trying to -- update the scrolltable is a pain. Throw it out and start over. if sidetabs then for i,s in ipairs(sidetabs) do s:Hide() s:ClearAllPoints() s:SetParent(nil) -- Blizzard does this too. Huh. end end if self.main_sts then for i = 1, #self.main_sts do if self.main_sts[i] and self.main_sts[i].st then self.main_sts[i]:Release() end end end if self.vault_sts then for i = 1, #self.vault_sts do if self.vault_sts[i] and self.vault_sts[i].st then self.vault_sts[i]:Release() end end end self.main_sts = nil self.vault_sts = nil end if not self.main_sts then self:BuildMainSTs (self.perms, self.display.content) for i,st in ipairs(self.main_sts) do self.main_sts[i] = AceGUI:Create("lib-st"):WrapST(st) self.main_sts[i].head_offset = 20 end self:DoMainST(1) self:BuildVaultSTs (self.vault, self.display.content) for i,st in ipairs(self.vault_sts) do self.vault_sts[i] = AceGUI:Create("lib-st"):WrapST(st) self.vault_sts[i].head_offset = 20 end end if need_tabs or incomplete then local maintab = make_sidetab(1, function (this, id) self:DoMainST(self.current_main_st) end) maintab.tooltip = [[Rank permissions]] maintab:SetChecked(true) self:BuildVaultTabs() end self.display:Show() return self.display end -- vim:noet
