flickerstreak@24: --[[ flickerstreak@24: ReAction Action-button module. flickerstreak@24: flickerstreak@24: The button module implements standard action button functionality by wrapping Blizzard's flickerstreak@24: ActionButton frame and associated functions. It also provides some button layout flickerstreak@24: modification tools. flickerstreak@24: flickerstreak@24: --]] flickerstreak@24: flickerstreak@24: -- local imports flickerstreak@24: local ReAction = ReAction flickerstreak@24: local L = ReAction.L flickerstreak@24: local _G = _G flickerstreak@24: local AceOO = AceLibrary("AceOO-2.0") flickerstreak@24: local CreateFrame = CreateFrame flickerstreak@24: local print = ReAction.print flickerstreak@24: flickerstreak@24: -- module declaration flickerstreak@24: local moduleID = "Action" flickerstreak@24: local module = ReAction:NewModule( moduleID, flickerstreak@24: "AceEvent-2.0" flickerstreak@24: ) flickerstreak@24: flickerstreak@24: -- flickerstreak@24: -- action button class declaration flickerstreak@24: -- flickerstreak@24: local BtnClass = AceOO.Class() flickerstreak@24: local Button = BtnClass.prototype flickerstreak@24: module.BtnClass = BtnClass flickerstreak@24: flickerstreak@24: flickerstreak@24: flickerstreak@24: -- module methods flickerstreak@24: function module:OnInitialize() flickerstreak@24: self.db = ReAction:AcquireDBNamespace(moduleID) flickerstreak@24: ReAction:RegisterDefaults(moduleID,"profile", flickerstreak@24: { flickerstreak@24: buttons = { } flickerstreak@24: } flickerstreak@24: ) flickerstreak@24: flickerstreak@24: self.buttons = { } flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:OnEnable() flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:OnDisable() flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:OnProfileEnable() flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:ApplyToBar(bar) flickerstreak@24: self:RefreshBar(bar) flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:RefreshBar(bar) flickerstreak@24: if self.buttons[bar] == nil then flickerstreak@24: self.buttons[bar] = { } flickerstreak@24: end flickerstreak@24: local btns = self.buttons[bar] flickerstreak@24: local profile = self.db.profile flickerstreak@24: local barName = bar:GetName() flickerstreak@24: if profile.buttons[barName] == nil then flickerstreak@24: profile.buttons[barName] = {} flickerstreak@24: end flickerstreak@24: local btnCfg = profile.buttons[barName] flickerstreak@24: flickerstreak@24: local r, c = bar:GetButtonGrid() flickerstreak@24: local n = r*c flickerstreak@24: for i = 1, n do flickerstreak@24: if btnCfg[i] == nil then flickerstreak@24: btnCfg[i] = {} flickerstreak@24: end flickerstreak@24: if btns[i] == nil then flickerstreak@24: btns[i] = self.BtnClass:new(bar,i,btnCfg[i]) flickerstreak@24: else flickerstreak@24: btns[i]:Refresh(bar,i) flickerstreak@24: end flickerstreak@24: end flickerstreak@24: for i = n+1, #btns do flickerstreak@24: btns[i] = btns[i]:Destroy() flickerstreak@24: if btnCfg[i] then flickerstreak@24: btnCfg[i] = nil flickerstreak@24: end flickerstreak@24: end flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:RemoveFromBar(bar) flickerstreak@24: if self.buttons[bar] then flickerstreak@24: local btns = self.buttons[bar] flickerstreak@24: for _,b in pairs(btns) do flickerstreak@24: if b then flickerstreak@24: b:Destroy() flickerstreak@24: end flickerstreak@24: end flickerstreak@24: self.buttons[bar] = nil flickerstreak@24: end flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:EraseBarConfig(barName) flickerstreak@24: self.db.profile.buttons[barName] = nil flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:ApplyConfigMode(mode,bars) flickerstreak@24: for _, btns in pairs(self.buttons) do flickerstreak@24: if btn then flickerstreak@24: for _, b in pairs(btns) do flickerstreak@24: if b then flickerstreak@24: if mode then flickerstreak@24: if not b.actionIDLabel then flickerstreak@24: local label = b:GetFrame():CreateFontString(nil,"OVERLAY","GameFontNormalLarge") flickerstreak@24: label:SetAllPoints() flickerstreak@24: label:SetJustifyH("CENTER") flickerstreak@24: label:SetShadowColor(0,0,0,1) flickerstreak@24: label:SetShadowOffset(2,-2) flickerstreak@24: label:SetText(tostring(b:GetActionID())) flickerstreak@24: b.actionIDLabel = label flickerstreak@24: end flickerstreak@24: b.actionIDLabel:Show() flickerstreak@24: elseif b.actionIDLabel then flickerstreak@24: b.actionIDLabel:Hide() flickerstreak@24: end flickerstreak@24: end flickerstreak@24: end flickerstreak@24: end flickerstreak@24: end flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:GetGlobalBarOptions(opts) flickerstreak@24: if self.globalBarOpts == nil then flickerstreak@24: self.globalBarOpts = { flickerstreak@24: newActionBar = { flickerstreak@24: type = "execute", flickerstreak@24: name = L["New Action Bar"], flickerstreak@24: desc = L["Create a new bar of standard action buttons"], flickerstreak@24: func = function() flickerstreak@24: ReAction:GetModule("Bar"):CreateBar() flickerstreak@24: end, flickerstreak@24: disabled = InCombatLockdown, flickerstreak@24: } flickerstreak@24: } flickerstreak@24: end flickerstreak@24: return self.globalBarOpts flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:GetBarMenuOptions(bar) flickerstreak@24: if not bar.modMenuOpts[moduleID] then flickerstreak@24: bar.modMenuOpts[moduleID] = { flickerstreak@24: } flickerstreak@24: end flickerstreak@24: return bar.modMenuOpts[moduleID] flickerstreak@24: end flickerstreak@24: flickerstreak@24: function module:GetBarConfigOptions(bar) flickerstreak@24: if not bar.modConfigOpts[moduleID] then flickerstreak@24: bar.modConfigOpts[moduleID] = { flickerstreak@24: } flickerstreak@24: end flickerstreak@24: return bar.modConfigOpts[moduleID] flickerstreak@24: end flickerstreak@24: flickerstreak@24: flickerstreak@24: flickerstreak@24: -- use-count of action IDs flickerstreak@24: local ActionIDList = setmetatable( {}, { flickerstreak@24: __index = function(self, idx) flickerstreak@24: if idx == nil then flickerstreak@24: for i = 1, 120 do flickerstreak@24: if rawget(self,i) == nil then flickerstreak@24: rawset(self,i,1) flickerstreak@24: return i flickerstreak@24: end flickerstreak@24: end flickerstreak@24: else flickerstreak@24: local c = rawget(self,idx) or 0 flickerstreak@24: rawset(self,idx,c+1) flickerstreak@24: return idx flickerstreak@24: end flickerstreak@24: end, flickerstreak@24: __newindex = function(self,idx,value) flickerstreak@24: if value == nil then flickerstreak@24: value = rawget(self,idx) flickerstreak@24: if value == 1 then flickerstreak@24: value = nil flickerstreak@24: elseif value then flickerstreak@24: value = value - 1 flickerstreak@24: end flickerstreak@24: end flickerstreak@24: rawset(self,idx,value) flickerstreak@24: end flickerstreak@24: }) flickerstreak@24: flickerstreak@24: flickerstreak@24: flickerstreak@24: -- button class methods flickerstreak@24: function Button:init( bar, idx, config ) flickerstreak@24: BtnClass.super.prototype.init(self) flickerstreak@24: self.bar, self.idx, self.config = bar, idx, config flickerstreak@24: flickerstreak@24: local barFrame = bar:GetFrame() flickerstreak@24: flickerstreak@24: self.name = config.name or "ReAction_"..bar:GetName().."_"..idx flickerstreak@24: config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured flickerstreak@24: flickerstreak@24: local f = CreateFrame("CheckButton", self.name, barFrame, "ActionBarButtonTemplate") flickerstreak@24: -- TODO: re-implement ActionButton event handlers that don't do secure stuff flickerstreak@24: flickerstreak@24: -- this will probably cause taint, using right now for display/debugging purposes flickerstreak@24: f:SetScript("OnAttributeChanged", flickerstreak@24: function() flickerstreak@24: ActionButton_UpdateAction() flickerstreak@24: end flickerstreak@24: ) flickerstreak@24: f:SetAttribute("action", config.actionID) flickerstreak@24: barFrame:SetAttribute("addchild",f) flickerstreak@24: self.frame = f flickerstreak@24: self:Refresh(bar,idx) flickerstreak@24: end flickerstreak@24: flickerstreak@24: function Button:Destroy() flickerstreak@24: local f = self.frame flickerstreak@24: f:UnregisterAllEvents() flickerstreak@24: f:Hide() flickerstreak@24: f:SetParent(UIParent) flickerstreak@24: f:ClearAllPoints() flickerstreak@24: if self.config.name then flickerstreak@24: _G[self.config.name] = nil flickerstreak@24: end flickerstreak@24: ActionIDList[self.config.actionID] = nil flickerstreak@24: self.frame = nil flickerstreak@24: self.config = nil flickerstreak@24: self.bar = nil flickerstreak@24: end flickerstreak@24: flickerstreak@24: function Button:Refresh(bar,idx) flickerstreak@24: bar:PlaceButton(self.frame, idx, 36, 36) flickerstreak@24: end flickerstreak@24: flickerstreak@24: function Button:GetFrame() flickerstreak@24: return self.frame flickerstreak@24: end flickerstreak@24: flickerstreak@24: function Button:GetName() flickerstreak@24: return self.name flickerstreak@24: end flickerstreak@24: flickerstreak@24: function Button:GetActionID() flickerstreak@24: return self.config.actionID flickerstreak@24: end