Mercurial > wow > reaction
view modules/ReAction_Action/ReAction_Action.lua @ 75:06cd74bdc7da
- Cleaned up Bar interface
- Move all attribute setting from Bar into State
- Separated Moonkin and Tree of Life
- Removed PossessBar module
- Added some infrastructure for paged/mind control support to Action
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Mon, 16 Jun 2008 18:46:08 +0000 |
parents | 768be7eb22a0 |
children | da8ba8783924 |
line wrap: on
line source
--[[ ReAction Action button module. The button module implements standard action button functionality by wrapping Blizzard's ActionButton frame and associated functions. It also provides some button layout modification tools. --]] -- local imports local ReAction = ReAction local L = ReAction.L local _G = _G local CreateFrame = CreateFrame -- module declaration local moduleID = "Action" local module = ReAction:NewModule( moduleID ) -- private -- local function GetBarConfig(bar) return module.db.profile.bars[bar:GetName()] end local function RefreshLite(bar) local btns = module.buttons[bar] if btns then for _, b in ipairs(btns) do b:Refresh() end end end -- module methods function module:OnInitialize() self.db = ReAction.db:RegisterNamespace( moduleID, { profile = { buttons = { }, bars = { }, } } ) self.buttons = { } ReAction:RegisterOptions(self, { [moduleID] = { type = "group", name = L["Action Bars"], args = { hideEmpty = { type = "toggle", name = L["Hide Empty Buttons"], get = function() return self.db.profile.hideEmptyButtons end, set = function(info, val) module:SetHideEmptyButtons(val) end, } } } }) ReAction:RegisterBarOptionGenerator(self, "GetBarOptions") ReAction.RegisterCallback(self, "OnCreateBar", "OnRefreshBar") ReAction.RegisterCallback(self, "OnDestroyBar") ReAction.RegisterCallback(self, "OnRefreshBar") ReAction.RegisterCallback(self, "OnEraseBar") ReAction.RegisterCallback(self, "OnRenameBar") ReAction.RegisterCallback(self, "OnConfigModeChanged") end function module:OnEnable() ReAction:RegisterBarType(L["Action Bar"], { type = moduleID, defaultButtonSize = 36, defaultBarRows = 1, defaultBarCols = 12, defaultBarSpacing = 3 }, true) end function module:OnDisable() ReAction:UnregisterBarType(L["Action Bar"]) end function module:OnRefreshBar(event, bar, name) if bar.config.type == moduleID then if self.buttons[bar] == nil then self.buttons[bar] = { } end local btns = self.buttons[bar] local profile = self.db.profile if profile.buttons[name] == nil then profile.buttons[name] = {} end if profile.bars[name] == nil then profile.bars[name] = {} end local btnCfg = profile.buttons[name] local barCfg = profile.bars[name] local r, c = bar:GetButtonGrid() local n = r*c for i = 1, n do if btnCfg[i] == nil then btnCfg[i] = {} end if btns[i] == nil then local ok, b = pcall(self.BtnClass.New, self.BtnClass, bar, i, btnCfg[i], barCfg) if ok and b then btns[i] = b bar:AddButton(i,b) end end end for i = n+1, #btns do if btns[i] then bar:RemoveButton(btns[i]) btns[i] = btns[i]:Destroy() if btnCfg[i] then btnCfg[i] = nil end end end RefreshLite(bar) end end function module:OnDestroyBar(event, bar, name) if self.buttons[bar] then local btns = self.buttons[bar] for _,b in pairs(btns) do if b then b:Destroy() end end self.buttons[bar] = nil end end function module:OnEraseBar(event, bar, name) self.db.profile.buttons[name] = nil self.db.profile.bars[name] = nil end function module:OnRenameBar(event, bar, oldname, newname) local b = self.db.profile.buttons b[newname], b[oldname] = b[oldname], nil b = self.db.profile.bars b[newname], b[oldname] = b[oldname], nil end function module:SetHideEmptyButtons(hide) if hide ~= self.db.profile.hideEmptyButtons then for _, bar in pairs(self.buttons) do for _, b in pairs(bar) do if hide then ActionButton_HideGrid(b.frame) else ActionButton_ShowGrid(b.frame) end end end self.db.profile.hideEmptyButtons = hide end end function module:OnConfigModeChanged(event, mode) for _, bar in ReAction:IterateBars() do if bar and self.buttons[bar] then for _, b in pairs(self.buttons[bar]) do if b then if mode then ActionButton_ShowGrid(b.frame) self:showActionIDLabel(b) else ActionButton_HideGrid(b.frame) self:hideActionIDLabel(b) end end end end end end function module:showActionIDLabel(button) if not button.actionIDLabel and button:GetActionID() then local f = button:GetFrame() local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") label:SetAllPoints() label:SetJustifyH("CENTER") label:SetShadowColor(0,0,0,1) label:SetShadowOffset(2,-2) label:SetText(tostring(button:GetActionID())) button.actionIDLabel = label f:HookScript("OnAttributeChanged", function(frame, attr, value) if attr == "state-parent" then label:SetText(tostring(button:GetActionID())) end end) end button.actionIDLabel:Show() end function module:hideActionIDLabel(button) if button.actionIDLabel then button.actionIDLabel:Hide() end end ---- Options ---- function module:GetBarOptions(bar) return { type = "group", name = L["Action Buttons"], hidden = function() return bar.config.type ~= moduleID end, args = { } } end -- use-count of action IDs local nActionIDs = 120 local ActionIDList = setmetatable( {}, { __index = function(self, idx) if idx == nil then for i = 1, nActionIDs do if rawget(self,i) == nil then rawset(self,i,1) return i end end error("ran out of action IDs") else local c = rawget(self,idx) or 0 rawset(self,idx,c+1) return idx end end, __newindex = function(self,idx,value) if value == nil then value = rawget(self,idx) if value == 1 then value = nil elseif value then value = value - 1 end end rawset(self,idx,value) end }) ------ Button class ------ local Button = { } local function Constructor( self, bar, idx, config, barConfig ) self.bar, self.idx, self.config, self.barConfig = bar, idx, config, barConfig local barFrame = bar:GetFrame() config.name = config.name or ("ReAction_%s_%d"):format(bar:GetName(),idx) self.name = config.name config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured self.nPages = 1 local f = CreateFrame("CheckButton", self.name, barFrame, "ActionBarButtonTemplate") -- TODO: re-implement ActionButton event handlers that don't do secure stuff -- this will probably cause taint and/or performance problems, using right now for display/debugging purposes f:SetScript("OnAttributeChanged", ActionButton_UpdateAction) f:SetAttribute("action", config.actionID) -- install mind control action support for all buttons here just for simplicity if self.idx <= 12 then f:SetAttribute("action-mc", 120 + self.idx) end barFrame:SetAttribute("addchild",f) self.frame = f self:Refresh() if not module.db.profile.hideEmptyButtons then ActionButton_ShowGrid(self.frame) end if ReAction.configMode then ActionButton_ShowGrid(self.frame) module:showActionIDLabel(self) end end function Button:Destroy() local f = self.frame f:UnregisterAllEvents() f:Hide() f:SetParent(UIParent) f:ClearAllPoints() if self.name then _G[self.name] = nil end if self.config.actionID then ActionIDList[self.config.actionID] = nil end if self.config.pages then for _, id in ipairs(self.config.pages) do ActionIDList[id] = nil end end self.frame = nil self.config = nil self.bar = nil end function Button:Refresh() local f = self.frame self.bar:PlaceButton(self, 36, 36) if self.barConfig.mckeybinds then f:SetAttribute("bindings-mc", self.barConfig.mckeybinds[self.idx]) end self:RefreshPages() end function Button:GetFrame() return self.frame end function Button:GetName() return self.name end function Button:GetActionID() return SecureButton_GetModifiedAttribute(self.frame, "action") end function Button:RefreshPages() local nPages = 1 --self.bar:GetNumPages() if nPages ~= self.nPages then local f = self:GetFrame() local c = self.config.pages if nPages > 1 and not c then c = { } self.config.pages = c end for i = 1, nPages do c[i] = ActionIDList[c[i]] -- gets a free one if none configured f:SetAttribute(("action-page%d"):format(i)) end for i = nPages+1, #c do ActionIDList[c[i]] = nil c[i] = nil f:SetAttribute(("action-page%d"):format(i)) end -- TODO: -- apply next-page, prev-page, and direct-page keybinds (via bar:SetStateKeybind abstraction) end end -- export as a class-factory to module module.BtnClass = { New = function(self, ...) local x = { } for k,v in pairs(Button) do x[k] = v end Constructor(x, ...) return x end }