local lib = LibStub:NewLibrary("zzAddOn", 11) if not lib then return end local config = LibStub:GetLibrary("zzConfig") lib['callbacks'] = lib['callbacks'] or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib) lib['addons'] = lib['addons'] or {} lib['managerframe'] = lib['managerframe'] or { ['hide'] = {}, ['show'] = {} } lib['events'] = lib['events'] or CreateFrame("FRAME") local function errormsg(err) print(format("|cffff0000Error:|r %s",err)) end local mixins = {'NewAddOn', 'GetAddOn', 'AddChild', 'HasChild', 'IsChild', 'HasParent', 'GetParent', 'GetOptions', 'RegisterEvent','UnregisterEvent','IsClassic','IsBCC','IsRetail', 'GetSpecs', 'Fire', 'RegisterOpen', 'RegisterClose'} function lib:Fire(...) lib['callbacks']:Fire(...) end function lib:GetAddOn(childName) return lib['addons'][childName] end function lib:GetOptions() return self['options'] end function lib:GetParent() return self['parent'] end function lib:HasParent() return self['parent'] and true or false end function lib:IsChild() return self:HasParent() end function lib:HasChild() return self['children'] and #self['children'] > 0 end function lib:GetSpecs(childName) return lib['addons'][childName]['specs'] end local function joinTables(tab1, tab2, prefix) prefix = prefix or '' for k, v in pairs(tab2) do if(tab1[k] and type(v) == 'table') then joinTables(tab1[k], v, format("%s ", prefix)) else tab1[k] = v end end end local function childExists(parent, child) if(parent['children']) then for i = 1, #parent['children'] do if(parent['children'][i]['specs']['name'] == child['specs']['name']) then return true end end end end function lib:AddChild(parentName, child) local parent = self:GetAddOn(parentName) if(parent) then parent['children'] = parent['children'] or {} if(childExists(parent, child)) then return end child['parent'] = parent parent['children'][#parent['children'] + 1] = child if(child['specs']['defaults']) then joinTables(parent['specs']['defaults'], child['specs']['defaults']) end end end function lib:RegisterEvent(event, globalfunc) if(type(event) == 'table') then for k, v in pairs(event) do local ev = k local func = v if(type(v) == 'string') then ev = v func = globalfunc end if(type(ev) == 'string' and type(func) == 'function' and not self['events'][ev]) then self['events'][ev] = func end self:RegisterEvent(ev, func) end elseif(type(event) == 'string') then if(not lib['events']:IsEventRegistered(event)) then lib['events']:RegisterEvent(event) end lib.RegisterCallback(self, event, globalfunc) else errormsg("ign reg", type(event), event) end end function lib:UnregisterEvent(event) if(type(event) == 'table') then for k, v in pairs(event) do local ev = type(v) == 'string' and v or k self:UnregisterEvent(ev) end else lib['UnregisterCallback'](self, event) end end function lib:IsBCC() return WOW_PROJECT_ID == WOW_PROJECT_BURNING_CRUSADE_CLASSIC end function lib:IsClassic() return WOW_PROJECT_ID == WOW_PROJECT_CLASSIC end function lib:IsRetail() return WOW_PROJECT_ID == WOW_PROJECT_MAINLINE end local function handleManagerFrameShow(event, self, event, num) lib['callbacks']:Fire(format("show-%i", num), self, 'show', num) end local function handleManagerFrameHide(event, self, event, num) lib['callbacks']:Fire(format("hide-%i", num), self, 'hide', num) end local function addManagerFrame(self, mode, num, globalfunc) if(type(num) == 'table') then for k, v in pairs(num) do local n = k local func = v if(type(v) == 'number') then n = v func = globalfunc end addManagerFrame(self, mode, n, func) end elseif(type(num) == 'number') then lib.RegisterCallback(self, format("%s-%i", mode, num), globalfunc) end end function lib:RegisterOpen(num, func) if(not num) then return end local event = "PLAYER_INTERACTION_MANAGER_FRAME_SHOW" if(not lib['events']:IsEventRegistered(event)) then self:RegisterEvent(event, handleManagerFrameShow) end addManagerFrame(self, 'show', num, func) end function lib:RegisterClose(num, func) if(not num) then return end local event = "PLAYER_INTERACTION_MANAGER_FRAME_HIDE" if(not lib['events']:IsEventRegistered(event)) then self:RegisterEvent(event, handleManagerFrameHide) end addManagerFrame(self, 'hide', num, func) end function lib:NewAddOn(addonName, addonTable) local specs = self['specs'] local childName = specs['name'] if(type(childName) == 'string') then self.GetAddOnTable = function() return addonTable end lib['addons'][childName] = self local child = lib['addons'][childName] lib:Embed(self) if(childName ~= addonName) then local parent = lib['addons'][addonName] parent:AddChild(parent['specs']['name'], self) end if(self['events']) then for ev, func in pairs(self['events']) do if(type(func) == 'function') then self:RegisterEvent(ev, func) end end end return self end end function lib:Embed(target) for _,name in pairs(mixins) do target[name] = lib[name] end end for _, target in pairs(lib['addons']) do lib:Embed(target) end lib['events']:RegisterEvent('ADDON_LOADED') local function addLDB(...) return LibStub:GetLibrary("zzLDB"):AddLDB(...) end local function addConfig(addonName, child, specs) local at = child:GetAddOnTable() if(addonName == child['specs']['name']) then config:InitConfig(child, addonName) child['options']['args']['profile'] = LibStub("AceDBOptions-3.0"):GetOptionsTable(at['db']) else config:AddConfig(child, addonName) end if(type(specs['cfgReset']) == 'function') then specs['cfgReset'](child) at['db'].RegisterCallback(specs, "OnProfileReset", 'cfgReset') end end local function SetupSpecs(addonName, child) local specs = child['specs'] if(specs and specs['sv'] and not child['db']) then local dbname = format('%sDB', type(specs['sv']) == 'boolean' and addonName or specs['sv']) local at = child:GetAddOnTable() at['db'] = LibStub("AceDB-3.0"):New(dbname, type(specs['defaults']) == 'table' and specs['defaults'] or {}, 'Default') if(specs['ldb']) then addLDB(specs['name'], specs['ldb'], at['db']) end if(specs['cfg']) then addConfig(addonName, child, specs) end if(child:HasChild()) then for i = 1, #child['children'] do local child = child['children'][i] local childSpecs = child['specs'] if(childSpecs['ldb']) then addLDB(childSpecs['name'], childSpecs['ldb'], at['db']) end if(childSpecs['cfg']) then addConfig(addonName, child, childSpecs) end end end end end lib['events']:SetScript("OnEvent", function(self, event, ...) local addonName = ... local child = lib['addons'][addonName] if(child) then if(event == 'ADDON_LOADED') then SetupSpecs(addonName, child) end end lib['callbacks']:Fire(event, self, event, ...) end)