# HG changeset patch # User Nenue # Date 1472308308 14400 # Node ID d8bb2629fea83e1dc3aab380efffeb8fc44a15f0 # Parent 39cfd8e142f9ae51aec2700c746b2d44f4a4d53c LKT - organized addon templates a little - centralized ticker diff -r 39cfd8e142f9 -r d8bb2629fea8 LibKraken/LibKraken.iml --- a/LibKraken/LibKraken.iml Mon Aug 22 09:24:33 2016 -0400 +++ b/LibKraken/LibKraken.iml Sat Aug 27 10:31:48 2016 -0400 @@ -1,11 +1,9 @@ - + - - - - + + \ No newline at end of file diff -r 39cfd8e142f9 -r d8bb2629fea8 LibKraken/LibKraken.lua --- a/LibKraken/LibKraken.lua Mon Aug 22 09:24:33 2016 -0400 +++ b/LibKraken/LibKraken.lua Sat Aug 27 10:31:48 2016 -0400 @@ -41,54 +41,39 @@ --GLOBALS: KTErrorFrame, LibKTError, SlashCmdList, SLASH_RL1, SLASH_UI1 local CreateFrame, debugstack, tostring, select = CreateFrame, debugstack, tostring, select -local max, unpack, tinsert = max, unpack, tinsert -local ipairs, xpcall, next, safecall = ipairs, xpcall, next, safecall -local UI_TOGGLE = false +local max, unpack, tinsert, tremove = max, unpack, tinsert, tremove +local ipairs, pairs, xpcall = ipairs, pairs, xpcall +local type, assert = type, assert +local IsLoggedIn = IsLoggedIn local db +local print = DEVIAN_WORKSPACE and function(...) _G.print('LKT', ...) end or function() end +local noFunc = function() end KT.handler = CreateFrame('Frame', 'LibKTHostFrame', UIParent) KT.addons = {} KT.initStack = {} -KT.varsStack = {} -local print = DEVIAN_WORKSPACE and function(...) _G.print('LKT', ...) end or function() end +local libInitialized = false local registeredHandles = {} +local initialized = {} +local enabled = {} local handlers = {} ---- /rl --- ReloadUI shortcut -SLASH_RL1 = "/rl" -SlashCmdList.RL = function () - ReloadUI() -end ---- /ui --- Run any addon:ui() methods -SLASH_UI1 = "/ui" -SlashCmdList.UI = function () - if UI_TOGGLE then - UI_TOGGLE = false - else - UI_TOGGLE = true - end - for i, frame in pairs(KT.frames) do - if UI_TOGGLE then - if frame.close then - frame.close() - else - frame:Hide() - end - else - if frame.ui then - frame.ui() - end - frame:Show() +local debuggers = {} +local pending = {} + + +local Embed = function (target, template) + for k,v in pairs(template) do + if not target[k] then + target[k] = template[k] end end end -LibKTError = function(msg) +local LibKT_Error = function(msg) local dstack = debugstack(2) :gsub("Interface\\AddOns\\",'') :gsub("<(.-)>", function(a) return '|cFF00FFFF<'.. a ..'>|r' end) @@ -101,226 +86,81 @@ KTErrorFrame:Show() end -local debuggers = {} -local pending = {} -local processing = false -local isHandled = false -local nodebug = false -function KT.OnEvent (addon, event, ...) - if processing then - local args = {...} - C_Timer.After(0, function() KT.OnEvent(addon, event, unpack(args)) end) - return - else +local LibKT_OnLoad = function(self) + --- /rl + -- ReloadUI shortcut + SLASH_RL1 = "/rl" + SlashCmdList.RL = function () + ReloadUI() + end + libInitialized = true +end - end - --- reset state - processing = true - isHandled = false - nodebug = false - - - if addon.event then - nodebug = addon.event(addon, event, ...) - end - - if addon[event] then - nodebug = addon[event](addon, event, ...) or nodebug - addon.missed = 0 - addon.handled = addon.handled + 1 - isHandled = true - else - addon.firstEvent = false - addon.unhandled = addon.unhandled + 1 - addon.missed = addon.missed + 1 - end - - for i, module in ipairs(addon.modules) do - --print(i, module) - if module[event] then - nodebug = module[event](addon, event, ...) or nodebug - addon.missed = 0 - addon.handled = addon.handled + 1 - isHandled = true - else - addon.firstEvent = false - addon.unhandled = addon.unhandled + 1 - addon.missed = addon.missed + 1 +local LibKT_OnEvent = function(self, event, arg1) + print(event, arg1) + if (event == 'ADDON_LOADED' and arg1 ~= 'Blizzard_DebugTools') or event == 'PLAYER_LOGIN' then + if not libInitialized then + LibKT_OnLoad(self) end - end - --if nodebug then - processing = false - return - --else - -- KT.UpdateEventStatus(addon, event, ...) - -- processing = false - --end -end + -- run any init blocks left in the queue + for i, addon in ipairs(KT.initStack) do + if not initialized[addon] then + print('|cFF0088FF'..tostring(addon)..'|r:init()') + if addon.init then + xpcall(addon.init, LibKT_Error) + end -KT.UpdateEventStatus = function(addon, event, ...) - if (addon.DEVIAN_PNAME and addon.DEVIAN_PNAME == DEVIAN_PNAME) or ((not addon.DEVIAN_PNAME) and DEVIAN_WORKSPACE) then - print(addon:GetName(), event, ...) - end + if addon.event then + addon:SetScript('OnEvent', addon.event) + end - -- debug outputs - if addon.status then - addon.status:SetText(event .. '\n|cFF00FF00' .. addon.handled .. '|r |cFFFF8800' .. addon.missed .. '|r |cFFFF4400' .. addon.unhandled .. '|r') - if isHandled then - addon.status:SetTextColor(0,1,0) - if addon.log then - local logtext = event - for i = 1, select('#',...) do - logtext = logtext .. '\n' .. i .. ':' .. tostring(select(i,...)) - end - addon.log:SetText('|cFFFFFF00last|r\n' .. logtext) - local newWidth = addon.log:GetStringWidth() + initialized[addon] = true + end - if addon.logfirst then - if not addon.firstEvent then - addon.firstEvent = event - addon.logfirst:SetText('|cFF00FF88first|r\n' .. logtext) - end + if #addon.modules >= 1 then + for i, module in ipairs(addon.modules) do + if not initialized[module] then + print(i .. ' |cFF0088FF'..tostring(addon)..'|r.|cFF00FFFF'..tostring(module)..'|r:init()') + if module.init then + xpcall(module.init, LibKT_Error) + end - newWidth = newWidth + addon.logfirst:GetStringWidth() - end - if addon.logdiff then - if not event ~= addon.firstEvent then - addon.firstEvent = event - addon.logdiff:SetText('|cFF0088FFdiff|r\n' .. logtext) - end - newWidth = newWidth + addon.logdiff:GetStringWidth() - end - --addon:SetWidth(newWidth) - end - else - addon.status:SetTextColor(1,0,0) - end - end -end - -KT.map = function(addon, addonTable) - setmetatable(addonTable, { - __index = function(_,k) - return addon[k] - end, - __newindex = function(_, k, v) - addon[k] = v - end - }) -end - -local emptyFunc = function() end - -KT.register = function(addon, arg, noGUI) - - local name, handler - if type(addon) == 'string' and type(arg) == 'table' then - -- it's a string, i.e. file vararg was passed - if _G[addon] then - -- check if it's the name of a frame and use that - handler = _G[addon] - else - -- re-arrange - name = addon - handler = arg - end - else - handler = addon - assert(type(handler) == 'table', 'Unable to parse ('..tostring(type(addon))..', '..tostring(type(arg))..')') - end - - - local loadedName - local printName - local isModule - - -- if exists, then second argument is probably a module name - if registeredHandles[handler] then - if type(arg) == 'table' then - tinsert(handler.modules, arg) - else - name = arg or debugstack(2,1,0):match(".+\\(%S+)%.lua") - end - isModule = true - - if not name then - name = debugstack(2,1,0):match(".+\\(%S+)%.lua") - end - local handlerName = handler:GetName() - loadedName = '|cFF00FF88'.. tostring(handlerName) .. '|r:|cFFFFFF00'.. tostring(name) - else - if handler.GetName then - name = handler:GetName() - elseif not name then - name = debugstack(2,1,0):match(".+\\(%S+)%.lua") - end - - loadedName = '|cFF00FFFF'.. tostring(name) .. '|r' - - registeredHandles[handler] = name - if handler.SetScript then - handler:SetScript('OnEvent', KT.OnEvent) - end - handler.unhandled = 0 - handler.missed = 0 - handler.handled = 0 - handler.firstEvent = false - handler.modules = {} - tinsert(KT.initStack, handler) - tinsert(KT.varsStack, handler) - - if handler.GetName and (not noGUI) then - handler.UIPanelAnchor = {'TOPLEFT', handler, 'TOPLEFT', 12, -12 } - handler.UIPanelGrowth = {'TOPLEFT', 'TOPRIGHT', 14, 0} - handler.button = KT.button - handler.uibutton = KT.uibutton - handler.tab = KT.tab - handler.print = KT.print - end - end - - local debugFunc = emptyFunc - --@debug@ - local debugID = isModule and name or handler - if (handler.DEVIAN_PNAME and DEVIAN_PNAME == handler.DEVIAN_PNAME) or ((not handler.DEVIAN_PNAME) and DEVIAN_WORKSPACE) then - debuggers[debugID] = debuggers[debugID] or function(...) _G.print(name, ...) end - debugFunc = debuggers[debugID] - end - print(loadedName) - --@end-debug@ - return handler, debugFunc, KT.wrap -end - - - -local onEvent = function(self, event, arg1) - if (event == 'ADDON_LOADED' and arg1 ~= 'Blizzard_DebugTools') or event == 'PLAYER_LOGIN' then - -- run any init blocks left in the queue - while #KT.initStack >= 1 do - local addon = tremove(KT.initStack, 1) - print('KT', addon:GetName(), 'init') - if addon.init then - xpcall(addon.init, LibKTError) - for i, module in ipairs(addon.modules) do - if module.init then - xpcall(module.init, LibKTError) + if module.event then + module:SetScript('OnEvent', module.event) + end + initialized[module] = true end end end + end -- run any variables blocks if player variables are ready - if IsLoggedIn() and #KT.varsStack >= 1 then - while #KT.varsStack >= 1 do - local addon = tremove(KT.varsStack, 1) - print(addon:GetName()) - if addon.variables then - xpcall(addon.variables, LibKTError) - for i, module in ipairs(addon.modules) do - if module.variables then - xpcall(module.variables, LibKTError) + if IsLoggedIn() then + + for i, addon in ipairs(KT.initStack) do + print('|cFF88FF00'..tostring(addon)..'|r') + if initialized[addon] then + if not enabled[addon] then + print('|cFF88FF00'..tostring(addon)..'|r:variables()') + if addon.variables then + xpcall(addon.variables, LibKT_Error) + end + enabled[addon] = true + end + + if addon.modules and enabled[addon] then + for i, module in ipairs(addon.modules) do + print(i .. ' |cFF88FF00'..tostring(module)..'|r') + if not enabled[module] then + if module.variables then + print(i..' |cFF88FF00'..tostring(addon)..'|r.|cFF00FFFF'.. tostring(module)..'|r:variables()') + xpcall(module.variables, LibKT_Error) + end + enabled[module] = true + end end end end @@ -329,96 +169,99 @@ end end -KT.print = function(module, ...) - local msg = '|cFF00FFFF'..module:GetName()..'|r:' - for i = 1, select('#', ...) do - msg = msg .. ' ' .. tostring(select(i, ...)) - end - DEFAULT_CHAT_FRAME:AddMessage(msg) -end +--- GUI bits +local defaultGUIAddon = {} +do + local GetButtonTemplate = function(name, parent, template, onClick) + if _G[name] then + return _G[name] + end ---- Button generators - -local GetButtonTemplate = function(name, parent, template, onClick) - if _G[name] then - return _G[name] + local button = CreateFrame('Button', name, parent, template) + button:RegisterForClicks('AnyUp') + button:SetScript('OnClick', onClick) + return button end - local button = CreateFrame('Button', name, parent, template) - button:RegisterForClicks('AnyUp') - button:SetScript('OnClick', onClick) - return button -end + local SetButtonAnchor = function(self, collector, anchor, growth) + if self:GetID() == 0 then + self:SetID(#collector) + print('registered TabButton #', self:GetID()) + end -local SetButtonAnchor = function(self, collector, anchor, growth) - if self:GetID() == 0 then - self:SetID(#collector) - print('registered TabButton #', self:GetID()) + if self:GetID() == 1 then + self:SetPoint(unpack(anchor)) + else + growth[2] = collector[self:GetID()-1] + self:SetPoint(unpack(growth)) + end end - if self:GetID() == 1 then - self:SetPoint(unpack(anchor)) - else - growth[2] = collector[self:GetID()-1] - self:SetPoint(unpack(growth)) + defaultGUIAddon.tab = function(self, name, tooltip, texture, coords) + local button = GetButtonTemplate(name, self, 'KTTabButton', self.SelectTab) + button.icon:SetTexture(texture) + button.tooltip = tooltip + button:SetSize(unpack(self.tabSize)) + if coords then + button.icon:SetTexCoord(unpack(coords)) + end + SetButtonAnchor(button, self.tabButtons, self.tabAnchor, self.tabGrowth) + return button + end + + defaultGUIAddon.button = function(self, name, text, tooltip, onClick) + local button = GetButtonTemplate(name, self, 'KTButton', onClick) + + button.tooltip = tooltip + button:SetText(text) + button:SetWidth(max(button:GetWidth(), button:GetFontString():GetStringWidth() + 12)) + + SetButtonAnchor(button, self.controls, self.controlsAnchor, self.controlsGrowth) + return button + end + + defaultGUIAddon.uibutton = function(self, name, text, tooltip, onClick, texture, coords) + local button = GetButtonTemplate(name, self, 'KTUIPanelButton', onClick) + + button.tooltip = tooltip + button:SetText(text) + + if self.UIPanelIcon then + local w, h, anchor, x, y = unpack(self.UIPanelIcon) + button.icon:SetTexture(texture) + button.icon:SetSize(w, h) + button.icon:ClearAllPoints() + button.icon:SetPoint(anchor, button, anchor, x, y) + end + + if not self.UIPanelSize then + button:SetWidth(button:GetFontString():GetStringWidth() + button.icon:GetWidth()/1.5) + else + button:SetSize(unpack(self.UIPanelSize)) + end + if coords then + button.icon:SetTexCoord(unpack(coords)) + end + SetButtonAnchor(button, self.UIPanels, self.UIPanelAnchor, self.UIPanelGrowth) + return button end end -KT.tab = function(self, name, tooltip, texture, coords) - local button = GetButtonTemplate(name, self, 'KTTabButton', self.SelectTab) - button.icon:SetTexture(texture) - button.tooltip = tooltip - button:SetSize(unpack(self.tabSize)) - if coords then - button.icon:SetTexCoord(unpack(coords)) - end - SetButtonAnchor(button, self.tabButtons, self.tabAnchor, self.tabGrowth) - return button -end -KT.button = function(self, name, text, tooltip, onClick) - local button = GetButtonTemplate(name, self, 'KTButton', onClick) - - button.tooltip = tooltip - button:SetText(text) - button:SetWidth(max(button:GetWidth(), button:GetFontString():GetStringWidth() + 12)) - - SetButtonAnchor(button, self.controls, self.controlsAnchor, self.controlsGrowth) - return button -end - -KT.uibutton = function(self, name, text, tooltip, onClick, texture, coords) - local button = GetButtonTemplate(name, self, 'KTUIPanelButton', onClick) - - button.tooltip = tooltip - button:SetText(text) - - if self.UIPanelIcon then - local w, h, anchor, x, y = unpack(self.UIPanelIcon) - button.icon:SetTexture(texture) - button.icon:SetSize(w, h) - button.icon:ClearAllPoints() - button.icon:SetPoint(anchor, button, anchor, x, y) +local defaultAddon = {} +do + defaultAddon.print = function(module, ...) + local msg = '|cFF00FFFF'..module:GetName()..'|r:' + for i = 1, select('#', ...) do + msg = msg .. ' ' .. tostring(select(i, ...)) + end + DEFAULT_CHAT_FRAME:AddMessage(msg) end - if not self.UIPanelSize then - button:SetWidth(button:GetFontString():GetStringWidth() + button.icon:GetWidth()/1.5) - else - button:SetSize(unpack(self.UIPanelSize)) - end - if coords then - button.icon:SetTexCoord(unpack(coords)) - end - SetButtonAnchor(button, self.UIPanels, self.UIPanelAnchor, self.UIPanelGrowth) - return button -end ---- Co-routine Handler kajigger -do local tickerQueue = {} local ticker - local instant = false - KT.tick = function() + defaultAddon.tick = function() if #tickerQueue == 0 then ticker:Cancel() @@ -431,18 +274,169 @@ end end - KT.wrap = function(f) + defaultAddon.next = function(f) if not ticker then --print('create ticker') - ticker = C_Timer.NewTicker(.001, KT.tick) + ticker = C_Timer.NewTicker(.001, defaultAddon.tick) end tinsert(tickerQueue, f) return #tickerQueue + end + + +--- default OnEvent + + local processing = false + local isHandled = false + local nodebug = false + defaultAddon.event = function (addon, event, ...) + if processing then + local args = {...} + C_Timer.After(0, function() KT.OnEvent(addon, event, unpack(args)) end) + return + else + + end + --- reset state + processing = true + isHandled = false + nodebug = false + + + if addon.event then + nodebug = addon.event(addon, event, ...) + elseif addon[event] then + nodebug = addon[event](addon, event, ...) or nodebug + addon.missed = 0 + addon.handled = addon.handled + 1 + isHandled = true + else + addon.firstEvent = false + addon.unhandled = addon.unhandled + 1 + addon.missed = addon.missed + 1 + end + + if addon.modules then + for i, module in ipairs(addon.modules) do + --print(i, module, event) + if module.event then + module.event(module, event, ...) + elseif module[event] then + nodebug = module[event](addon, event, ...) or nodebug + addon.missed = 0 + addon.handled = addon.handled + 1 + isHandled = true + else + addon.firstEvent = false + addon.unhandled = addon.unhandled + 1 + addon.missed = addon.missed + 1 + end + end + end + --if nodebug then + processing = false + return + --else + -- KT.UpdateEventStatus(addon, event, ...) + -- processing = false + --end end + defaultAddon.wrap = function(addon, module, name) + local moduleName = name or tostring(module) + print(addon, module) + print('|cFF0088FF'..tostring(addon)..'|r:wrap(|cFF00FFFF'.. moduleName .. '|r|cFFFFFF00)|r') + + addon.modules = addon.modules or {} + tinsert(addon.modules, module) + + + if (module.DEVIAN_PNAME and DEVIAN_PNAME == module.DEVIAN_PNAME) or ((not module.DEVIAN_PNAME) and DEVIAN_WORKSPACE) then + debuggers[module] = function(...) _G.print(moduleName, ...) end + else + debuggers[module] = noFunc + end + return debuggers[module] + end + + defaultAddon.GetName = function(self) return tostring(self) end +end + +--- Frame registration +KT.register = function(addon, arg, noGUI) + --print('register(', addon, arg, ')') + local name, handler + if type(addon) == 'string' and type(arg) == 'table' then + name = addon + -- it's a string, i.e. file vararg was passed + if _G[addon] then + -- check if it's the name of a frame and use that + handler = _G[addon] + else + -- re-arrange + handler = arg + end + else + handler = addon + assert(type(handler) == 'table', 'Usage: KT.register(name, table) or KT.register(table, plugin)') + end + + + local printName + local isModule + + local scriptName = debugstack(2,1,0):match(".+\\(%S+)%.lua") + if registeredHandles[handler] then + -- addon is already register; treat second argument as plugin target + isModule = true + if type(arg) == 'table' then + local mt = getmetatable(arg) + setmetatable(arg, {__index = mt.__index, __tostring = function() return scriptName end}) + local debugger = handler:wrap(arg) + return handler, debugger + else + print(' + "|cFF00FFFF'..scriptName..'|r"') + end + else + -- new addon + --local scriptName = debugstack(2,1,0):match(".+\\(%S+)%.lua") + local mt = getmetatable(handler) + local nmt = {__index = mt.__index, __tostring = function() return scriptName end } + handler = setmetatable(handler, nmt) + Embed(handler, defaultAddon) + name = tostring(handler) + registeredHandles[handler] = name + if handler.SetScript then + handler:SetScript('OnEvent', handler.event) + end + handler.unhandled = 0 + handler.missed = 0 + handler.handled = 0 + handler.firstEvent = false + handler.modules = {} + tinsert(KT.initStack, handler) + + if not noGUI then + handler.UIPanelAnchor = {'TOPLEFT', handler, 'TOPLEFT', 12, -12 } + handler.UIPanelGrowth = {'TOPLEFT', 'TOPRIGHT', 14, 0} + Embed(handler, defaultGUIAddon) + end + + print('|cFF0088FF'..tostring(addon)..'|r') + end + + local debugFunc = noFunc + --@debug@ + local debugID = isModule and name or handler + if (handler.DEVIAN_PNAME and DEVIAN_PNAME == handler.DEVIAN_PNAME) or ((not handler.DEVIAN_PNAME) and DEVIAN_WORKSPACE) then + debuggers[debugID] = debuggers[debugID] or function(...) _G.print(name, ...) end + debugFunc = debuggers[debugID] + end + --@end-debug@ + return handler, debugFunc end KT.handler:RegisterEvent('ADDON_LOADED') KT.handler:RegisterEvent('PLAYER_LOGIN') -KT.handler:SetScript('OnEvent', onEvent) \ No newline at end of file +KT.handler:SetScript('OnEvent', LibKT_OnEvent) \ No newline at end of file diff -r 39cfd8e142f9 -r d8bb2629fea8 SkeletonKey/HotKey.lua --- a/SkeletonKey/HotKey.lua Mon Aug 22 09:24:33 2016 -0400 +++ b/SkeletonKey/HotKey.lua Sat Aug 27 10:31:48 2016 -0400 @@ -5,11 +5,11 @@ -- Module for fixing actionbar hotkey text local _G, wipe, tContains, tinsert = _G, table.wipe, tContains, tinsert -local kb, print, wrap = LibStub("LibKraken").register(KeyBinder, 'HotKey') -local hotkey = {} +local kb, print, wrap = LibStub("LibKraken").register(KeyBinder, "HotKey") local hotkeyText = {} local blizHotKey = {} local bindings +local hotkey = {} -- frames obtained via post-load hooks, created by addons like Dominos or BarTender4 local loadedFrames = {} @@ -20,7 +20,7 @@ local actionFrames = {} local actionIndex = {} -kb.wrap(hotkey) +kb:wrap(hotkey) --- Used to determine which groups of action buttons need updating local hotkeyEvents = { diff -r 39cfd8e142f9 -r d8bb2629fea8 SkeletonKey/Import.lua --- a/SkeletonKey/Import.lua Mon Aug 22 09:24:33 2016 -0400 +++ b/SkeletonKey/Import.lua Sat Aug 27 10:31:48 2016 -0400 @@ -4,7 +4,7 @@ -- %file-revision% -- Tools for first-time setup and migration from other addons. -local kb = LibStub("LibKraken").register(KeyBinder) +local kb = LibStub("LibKraken").register(KeyBinder, 'Import') local print = DEVIAN_WORKSPACE and function(...) print('kbi', ...) end or function() end diff -r 39cfd8e142f9 -r d8bb2629fea8 SkeletonKey/SkeletonKey.lua --- a/SkeletonKey/SkeletonKey.lua Mon Aug 22 09:24:33 2016 -0400 +++ b/SkeletonKey/SkeletonKey.lua Sat Aug 27 10:31:48 2016 -0400 @@ -305,11 +305,6 @@ end -kb.wrap = function(module) - kb.modules = kb.modules or {} - tinsert(kb.modules, module) -end - -- Volatiles Access kb.FormatActionID = function(actionType, actionID) return tostring(actionType) .. '_' .. tostring(actionID) end kb.GetBindings = function() return kb.bindings end