Mercurial > wow > reaction
diff Editor.lua @ 185:2e7a322e0195
move ConfigUI module to Editor non-module, make it more self-contained
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Fri, 22 Oct 2010 23:48:02 +0000 |
parents | modules/ConfigUI.lua@1ee86bbb05a0 |
children | d58055179c16 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Editor.lua Fri Oct 22 23:48:02 2010 +0000 @@ -0,0 +1,476 @@ +local addonName, addonTable = ... +local ReAction = addonTable.ReAction +local L = ReAction.L +local _G = _G +local wipe = wipe + +local AceConfigReg = LibStub("AceConfigRegistry-3.0") +local AceConfigDialog = LibStub("AceConfigDialog-3.0") + + +local pointTable = { + CENTER = L["Center"], + LEFT = L["Left"], + RIGHT = L["Right"], + TOP = L["Top"], + BOTTOM = L["Bottom"], + TOPLEFT = L["Top Left"], + TOPRIGHT = L["Top Right"], + BOTTOMLEFT = L["Bottom Left"], + BOTTOMRIGHT = L["Bottom Right"], +} + +local Editor = { } + +function Editor:New() + -- create new self + self = setmetatable( { }, { __index = self } ) + + self.barOptMap = setmetatable({},{__mode="v"}) + self.tmp = { } + self.configID = "ReAction-Editor" + + self.gui = LibStub("AceGUI-3.0"):Create("Frame") + + local frame = self.gui.frame + frame:SetClampedToScreen(true) + frame:Hide() + + frame:SetScript("OnHide", + function(...) + ReAction:SetConfigMode(false) + end) + + self.options = { + type = "group", + name = L["Select Bar:"], + desc = "foo foo foo", + handler = self, + childGroups = "select", + args = { + launchConfig = { + type = "execute", + name = L["Global Config"], + desc = L["Opens ReAction global configuration settings panel"], + func = function() + if ReAction.db.profile.editorCloseOnLaunch then + self:Close() + end + ReAction:ShowOptions() + end, + order = 1 + }, + closeThis = { + type = "toggle", + name = L["Close Editor"], + desc = L["Close the Bar Editor when opening the ReAction global Interface Options"], + get = function() return ReAction.db.profile.editorCloseOnLaunch end, + set = function(info, val) ReAction.db.profile.editorCloseOnLaunch = val end, + order = 2, + }, + hdr = { + type = "header", + name = "", + order = 3, + }, + desc = { + type = "description", + name = L["Use the mouse to arrange and resize the bars on screen. Tooltips on bars indicate additional functionality."], + width = "double", + order = 4, + }, + _new = { + type = "group", + name = L["New Bar..."], + order = 5, + args = { + desc = { + type = "description", + name = L["Choose a name, type, and initial grid for your new action bar:"], + order = 1, + }, + name = { + type = "input", + name = L["Bar Name"], + desc = L["Enter a name for your new action bar"], + get = function() return self.tmp.barName or "" end, + set = function(info, val) self.tmp.barName = val end, + order = 2, + }, + type = { + type = "select", + name = L["Button Type"], + get = function() return self.tmp.barType or ReAction:GetDefaultBarType() or "" end, + set = function(info, val) + local c = ReAction:GetBarTypeConfig(val) + self.tmp.barType = val + self.tmp.barSize = c.defaultButtonSize or self.tmp.barSize + self.tmp.barRows = c.defaultBarRows or self.tmp.barRows + self.tmp.barCols = c.defaultBarCols or self.tmp.barCols + self.tmp.barSpacing = c.defaultBarSpacing or self.tmp.barSpacing + end, + values = "GetBarTypes", + order = 3, + }, + go = { + type = "execute", + name = L["Create Bar"], + func = "CreateBar", + order = 4, + }, + grid = { + type = "group", + name = L["Button Grid"], + inline = true, + order = 5, + args = { + rows = { + type = "range", + name = L["Rows"], + get = function() return self.tmp.barRows or 1 end, + set = function(info, val) self.tmp.barRows = val end, + width = "full", + min = 1, + max = 32, + step = 1, + order = 2, + }, + cols = { + type = "range", + name = L["Columns"], + get = function() return self.tmp.barCols or 12 end, + set = function(info, val) self.tmp.barCols = val end, + width = "full", + min = 1, + max = 32, + step = 1, + order = 3, + }, + sz = { + type = "range", + name = L["Size"], + get = function() return self.tmp.barSize or 36 end, + set = function(info, val) self.tmp.barSize = val end, + width = "full", + min = 10, + max = 72, + step = 1, + order = 4, + }, + spacing = { + type = "range", + name = L["Spacing"], + get = function() return self.tmp.barSpacing or 3 end, + set = function(info, val) self.tmp.barSpacing = val end, + width = "full", + min = 0, + max = 24, + step = 1, + order = 5, + } + }, + }, + } + } + }, + } + + self.title = ("%s - %s"):format(L["ReAction"],L["Bar Editor"]) + self.gui:SetTitle(self.title) + + self.gui:SetCallback("OnClose", + function() + ReAction:SetConfigMode(false) + end ) + + AceConfigReg:RegisterOptionsTable(self.configID, self.options) + AceConfigDialog:SetDefaultSize(self.configID, 700, 540) + + ReAction.RegisterCallback(self,"OnCreateBar") + ReAction.RegisterCallback(self,"OnDestroyBar") + ReAction.RegisterCallback(self,"OnEraseBar") + ReAction.RegisterCallback(self,"OnRenameBar") + + for name, bar in ReAction:IterateBars() do + self:CreateBarTree(bar) + end + + return self +end + + +function Editor:Open(bar, ...) + if bar then + AceConfigDialog:SelectGroup(self.configID, self.barOptMap[bar:GetName()], ...) + end + AceConfigDialog:Open(self.configID,self.gui) + self.gui:SetTitle(self.title) +end + +function Editor:Close() + if self.gui then + print("closing...") + self.gui:ReleaseChildren() + self.gui:Hide() + end +end + +function Editor:Refresh() + AceConfigReg:NotifyChange(self.configID) +end + +function Editor:CreateBarTree(bar) + local name = bar:GetName() + -- AceConfig doesn't allow spaces, etc, in arg key names, and they must be + -- unique strings. So generate a unique key (it can be whatever) for the bar + local args = self.options.args + local key + local i = 1 + repeat + key = ("bar%s"):format(i) + i = i+1 + until args[key] == nil + self.barOptMap[name] = key + args[key] = { + type = "group", + name = name, + childGroups = "tab", + order = i+100, + args = { + general = { + type = "group", + name = L["General"], + order = 1, + args = { + name = { + type = "input", + name = L["Rename Bar"], + get = function() return bar:GetName() end, + set = function(info, value) return ReAction:RenameBar(bar, value) end, + order = 1, + }, + delete = { + type = "execute", + name = L["Delete Bar"], + desc = function() return bar:GetName() end, + confirm = true, + func = function() ReAction:EraseBar(bar) end, + order = 2 + }, + anchor = { + type = "group", + name = L["Anchor"], + inline = true, + args = { + frame = { + type = "input", + name = L["Frame"], + desc = L["The frame that the bar is anchored to"], + get = function() local _, f = bar:GetAnchor(); return f end, + set = function(info, val) bar:SetAnchor(nil,val) end, + validate = function(info, name) + if name then + local f = ReAction:GetBar(name) + if f then + return true + else + f = _G[name] + if f and type(f) == "table" and f.IsObjectType and f:IsObjectType("Frame") then + local _, explicit = f:IsProtected() + return explicit + end + end + end + return false + end, + width = "double", + order = 1 + }, + point = { + type = "select", + name = L["Point"], + desc = L["Anchor point on the bar frame"], + style = "dropdown", + get = function() return bar:GetAnchor() end, + set = function(info, val) bar:SetAnchor(val) end, + values = pointTable, + order = 2, + }, + relativePoint = { + type = "select", + name = L["Relative Point"], + desc = L["Anchor point on the target frame"], + style = "dropdown", + get = function() local p,f,r = bar:GetAnchor(); return r end, + set = function(info, val) bar:SetAnchor(nil,nil,val) end, + values = pointTable, + order = 3, + }, + x = { + type = "input", + pattern = "\-?%d+", + name = L["X offset"], + get = function() local p,f,r,x = bar:GetAnchor(); return ("%d"):format(x) end, + set = function(info,val) bar:SetAnchor(nil,nil,nil,val) end, + order = 4 + }, + y = { + type = "input", + pattern = "\-?%d+", + name = L["Y offset"], + get = function() local p,f,r,x,y = bar:GetAnchor(); return ("%d"):format(y) end, + set = function(info,val) bar:SetAnchor(nil,nil,nil,nil,val) end, + order = 5 + }, + }, + order = 3 + }, + alpha = { + type = "range", + name = L["Transparency"], + get = function() return bar:GetAlpha() end, + set = function(info, val) bar:SetAlpha(val) end, + min = 0, + max = 1, + isPercent = true, + step = 0.01, + bigStep = 0.05, + order = 4, + }, + }, + }, + } + } + self:RefreshBarOptions() +end + +function Editor:RefreshBarOptions() + for name, key in pairs(self.barOptMap) do + local bar = ReAction:GetBar(name) + if bar and key and self.options.args[key] then + self.options.args[key].plugins = self:GenerateBarOptionsTable(bar) + end + end + AceConfigReg:NotifyChange(self.configID) +end + +function Editor:OnCreateBar(evt, bar) + if not self.tmp.creating then + -- a bit of hack to work around OnCreateBar event handler ordering + self:CreateBarTree(bar) + end +end + +function Editor:OnDestroyBar(evt, bar, name) + local key = self.barOptMap[name] + if key then + self.options.args[key] = nil + end + self:Refresh() +end + +function Editor:OnEraseBar(evt, name) + local key = self.barOptMap[name] + self.barOptMap[name] = nil + if key then + self.options.args[key] = nil + self:Refresh() + end +end + +function Editor:OnRenameBar(evt, bar, oldname, newname) + local key = self.barOptMap[oldname] + self.barOptMap[oldname], self.barOptMap[newname] = nil, key + if key then + self.options.args[key].name = newname + self:Refresh() + end +end + +local _scratch = { } +function Editor:GetBarTypes() + wipe(_scratch) + return ReAction:GetBarTypeOptions(_scratch) +end + +function Editor:CreateBar() + if self.tmp.barName and self.tmp.barName ~= "" then + self.tmp.creating = true + local bar = ReAction:CreateBar(self.tmp.barName, self.tmp.barType or ReAction:GetDefaultBarType(), self.tmp.barRows, self.tmp.barCols, self.tmp.barSize, self.tmp.barSpacing) + if bar then + self:CreateBarTree(bar) + AceConfigDialog:SelectGroup(self.configID, self.barOptMap[self.tmp.barName]) + self.tmp.barName = nil + end + self.tmp.creating = false + end +end + +function Editor:GenerateBarOptionsTable( bar ) + local opts = { } + if not ReAction.barOptionGenerators then + return + end + + for module, func in pairs(ReAction.barOptionGenerators) do + local success, r + if type(func) == "string" then + success, r = pcall(module[func], module, bar) + else + success, r = pcall(func, bar) + end + if success then + if r then + opts[module:GetName()] = { [module:GetName()] = r } + end + else + geterrorhandler()(r) + end + end + return opts +end + + + +---- Export to ReAction ---- +function ReAction:ShowEditor(bar, ...) + if InCombatLockdown() then + self:UserError(L["ReAction config mode disabled during combat."]) + else + self.editor = self.editor or Editor:New() + self.editor:Open(bar, ...) + self:SetConfigMode(true) + end +end + +function ReAction:CloseEditor() + if self.editor then + self.editor:Close() + end +end + +function ReAction:RefreshEditor() + if self.editor then + self.editor:RefreshBarOptions() + end +end + +function ReAction:RegisterBarOptionGenerator( module, func ) + if not module or type(module) ~= "table" then -- doesn't need to be a proper module, strictly + error("ReAction:RegisterBarOptionGenerator() : Invalid module") + end + if type(func) == "string" then + if not module[func] then + error(("ReAction:RegisterBarOptionGenerator() : Invalid method '%s'"):format(func)) + end + elseif func and type(func) ~= "function" then + error("ReAction:RegisterBarOptionGenerator() : Invalid function") + end + self.barOptionGenerators = self.barOptionGenerators or { } + self.barOptionGenerators[module] = func + + if self.editor then + self.editor:RefreshBarOptions() + end +end +