flickerstreak@28: -- ReAction.lua flickerstreak@28: -- See modules/ReAction_ModuleTemplate for Module API listing flickerstreak@28: -- See Bar.lua for Bar object listing flickerstreak@25: flickerstreak@28: ------ LIBRARIES ------ flickerstreak@28: local L = LibStub("AceLocale-3.0"):GetLocale("ReAction") flickerstreak@27: flickerstreak@27: ------ CORE ------ flickerstreak@28: local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction" ) flickerstreak@27: ReAction.revision = tonumber(("$Revision: 1 $"):match("%d+")) flickerstreak@27: ReAction.L = L flickerstreak@27: flickerstreak@28: ------ GLOBALS ------ flickerstreak@28: _G["ReAction"] = ReAction flickerstreak@27: flickerstreak@28: ------ DEBUGGING ------ flickerstreak@25: ReAction.debug = true flickerstreak@25: if ReAction.debug then flickerstreak@25: ReAction.print = function(msg) flickerstreak@25: DEFAULT_CHAT_FRAME:AddMessage(msg) flickerstreak@25: end flickerstreak@25: --seterrorhandler(ReAction.print) flickerstreak@25: else flickerstreak@25: ReAction.print = function() end flickerstreak@25: end flickerstreak@25: flickerstreak@28: ------ PRIVATE ------ flickerstreak@28: local SelectBar, DestroyBar, InitializeBars, TearDownBars, DeepCopy, SafeCall, CheckMethod flickerstreak@28: do flickerstreak@28: local pcall = pcall flickerstreak@28: local geterrorhandler = geterrorhandler flickerstreak@28: flickerstreak@28: SelectBar = function(x) flickerstreak@28: local bar, name flickerstreak@28: if type(x) == "string" then flickerstreak@28: name = x flickerstreak@28: bar = ReAction:GetBar(name) flickerstreak@28: elseif ReAction.Bar:IsInstance(x) then flickerstreak@28: bar = x flickerstreak@28: for k,v in pairs(ReAction.bars) do flickerstreak@28: if v == bar then flickerstreak@28: name = k flickerstreak@28: end flickerstreak@28: end flickerstreak@28: else flickerstreak@28: error("bad argument to SelectBar") flickerstreak@28: end flickerstreak@28: return bar, name flickerstreak@28: end flickerstreak@28: flickerstreak@28: DestroyBar = function(x) flickerstreak@28: local bar, name = SelectBar(x) flickerstreak@28: if name and bar then flickerstreak@28: ReAction.bars[name] = nil flickerstreak@28: ReAction:CallMethodOnAllModules("RemoveFromBar", bar) flickerstreak@28: bar:Destroy() flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: InitializeBars = function () flickerstreak@28: if not(ReAction.inited) then flickerstreak@28: for name, config in pairs(ReAction.db.profile.bars) do flickerstreak@28: if config then flickerstreak@28: ReAction:CreateBar(name, config) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: ReAction:CallMethodOnAllBars("ApplyAnchor") -- re-anchor in the case of oddball ordering flickerstreak@28: ReAction.inited = true flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: TearDownBars = function() flickerstreak@28: for name, bar in pairs(ReAction.bars) do flickerstreak@28: if bar then flickerstreak@28: ReAction.bars[name] = DestroyBar(bar) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: ReAction.inited = false flickerstreak@28: end flickerstreak@28: flickerstreak@28: DeepCopy = function(x) flickerstreak@28: if type(x) ~= "table" then flickerstreak@28: return x flickerstreak@28: end flickerstreak@28: local r = {} flickerstreak@28: for k,v in pairs(x) do flickerstreak@28: r[k] = DeepCopy(v) flickerstreak@28: end flickerstreak@28: return r flickerstreak@28: end flickerstreak@28: flickerstreak@28: SafeCall = function(f, ...) flickerstreak@28: if f then flickerstreak@28: local success, err = pcall(f,...) flickerstreak@28: if not success then flickerstreak@28: geterrorhandler()(err) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: CheckMethod = function(m) flickerstreak@28: if type(m) == "function" then flickerstreak@28: return m flickerstreak@28: end flickerstreak@28: if type(m) ~= "string" then flickerstreak@28: error("Invalid method") flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: flickerstreak@28: ------ HANDLERS ------ flickerstreak@28: function ReAction:OnInitialize() flickerstreak@28: self.db = LibStub("AceDB-3.0"):New("ReAction_DB", flickerstreak@28: { flickerstreak@28: profile = { flickerstreak@28: bars = { }, flickerstreak@28: defaultBar = { } flickerstreak@28: } flickerstreak@28: } flickerstreak@28: -- default profile is character-specific flickerstreak@28: ) flickerstreak@28: self.db.RegisterCallback(self,"OnProfileChanged") flickerstreak@28: flickerstreak@28: self.bars = {} flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:OnEnable() flickerstreak@28: InitializeBars() flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:OnDisable() flickerstreak@28: TearDownBars() flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:OnProfileChanged() flickerstreak@28: self.TearDownBars() flickerstreak@28: self.InitializeBars() flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:OnModuleEnable(module) flickerstreak@28: if module.ApplyToBar then flickerstreak@28: for _, b in pairs(bars) do flickerstreak@28: if b then flickerstreak@28: module:ApplyToBar(b) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:OnModuleDisable(module) flickerstreak@28: if module.RemoveFromBar then flickerstreak@28: for _, b in pairs(bars) do flickerstreak@28: if b then flickerstreak@28: module:RemoveFromBar(b) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: flickerstreak@28: ------ API ------ flickerstreak@28: function ReAction:CallMethodOnAllModules(method, ...) flickerstreak@28: local m = CheckMethod(method) flickerstreak@28: for _, x in self:IterateModules() do flickerstreak@28: if x then flickerstreak@28: SafeCall(m or x[method], x, ...) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:CallMethodOnAllBars(method,...) flickerstreak@28: local m = CheckMethod(method) flickerstreak@28: for _, x in pairs(self.bars) do flickerstreak@28: if x then flickerstreak@28: SafeCall(m or x[method], x, ...) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:CreateBar(name, defaultConfig, prefix) flickerstreak@28: local profile = self.db.profile flickerstreak@28: defaultConfig = defaultConfig or profile.defaultBar flickerstreak@28: prefix = prefix or L["Bar "] flickerstreak@28: if not name then flickerstreak@28: i = 1 flickerstreak@28: repeat flickerstreak@28: name = prefix..i flickerstreak@28: i = i + 1 flickerstreak@28: until self.bars[name] == nil flickerstreak@28: end flickerstreak@28: profile.bars[name] = profile.bars[name] or DeepCopy(defaultConfig) flickerstreak@28: local bar = self.Bar:new( name, profile.bars[name] ) -- ReAction.Bar defined in Bar.lua flickerstreak@28: self:CallMethodOnAllModules("ApplyToBar", bar) flickerstreak@28: self.bars[name] = bar flickerstreak@28: return bar flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:EraseBar(x) flickerstreak@28: local bar, name = SelectBar(x) flickerstreak@28: if name and bar then flickerstreak@28: DestroyBar(bar) flickerstreak@28: self.db.profile.bars[name] = nil flickerstreak@28: self:CallMethodOnAllModules("EraseBarConfig", name) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:GetBar(name) flickerstreak@28: return self.bars[name] flickerstreak@28: end flickerstreak@28: flickerstreak@28: function ReAction:RenameBar(x, newname) flickerstreak@28: local bar, name = SelectBar(x) flickerstreak@28: if bar and name and newname then flickerstreak@28: if self.bars[newname] then flickerstreak@28: error(L["ReAction: name already in use"]) flickerstreak@28: end flickerstreak@28: self.bars[newname] = self.bars[name] flickerstreak@28: self.bars[name] = nil flickerstreak@28: bar.name = newname or "" flickerstreak@28: local cfg = self.db.profile.bars flickerstreak@28: cfg[newname], cfg[name] = cfg[name], nil flickerstreak@28: self:CallMethodOnAllModules("RenameBarConfig", name, newname) flickerstreak@28: end flickerstreak@28: end flickerstreak@28: flickerstreak@28: