Merge pull request #45 from ElvUI-Vanilla/ace3

ace3
This commit is contained in:
Loaal
2018-07-22 16:36:10 +03:00
committed by GitHub
62 changed files with 1963 additions and 1918 deletions
+75 -1
View File
@@ -7,7 +7,7 @@ local select = select
local tonumber = tonumber local tonumber = tonumber
local type = type local type = type
local unpack = unpack local unpack = unpack
local find, format, gmatch, gsub, lower, match, upper = string.find, string.format, string.gmatch, string.gsub, string.lower, string.match, string.upper local find, format, gmatch, gsub, len, lower, match, upper, sub = string.find, string.format, string.gmatch, string.gsub, string.len, string.lower, string.match, string.upper, string.sub
local getn = table.getn local getn = table.getn
--WoW API --WoW API
local debugstack = debugstack local debugstack = debugstack
@@ -412,6 +412,80 @@ function CreateStatusBarTexturePointer(statusbar)
return f return f
end end
local function removeScript(self, script)
local func = self:GetScript(script)
if func then
self:SetScript(script, nil)
end
return func
end
local nbsp = string.char(255)
function EditBoxGetCursorPosition(self)
if self == WowLuaFrameEditBox or self == WowLuaFrameCommandEditBox then return 0 end
if self:GetText() == "" then return 0 end
local occ = removeScript(self, "OnCursorChanged")
local otc = removeScript(self, "OnTextChanged")
local ots = removeScript(self, "OnTextSet")
self:Insert(nbsp)
local pos = find(self:GetText(), nbsp)
if not pos then
pos = len(self:GetText())
print(format("CursorPosition position for `%s` not found!", self.GetName and self:GetName() or tostring(self)))
else
self:HighlightText(pos - 1, pos)
self:Insert("")
end
if occ then self:SetScript("OnCursorChanged", occ) end
if otc then self:SetScript("OnTextChanged", otc) end
if ots then self:SetScript("OnTextSet", ots) end
return pos - 1
end
function EditBoxSetCursorPosition(self, pos)
if self == WowLuaFrameEditBox or self == WowLuaFrameCommandEditBox then return end
if self:GetText() == "" then return end
local occ = removeScript(self, "OnCursorChanged")
local otc = removeScript(self, "OnTextChanged")
local ots = removeScript(self, "OnTextSet")
local text = self:GetText()
local size = len(text)
if pos < 0 then
pos = 0
elseif pos > size then
pos = size
end
if pos == 0 then
text = sub(text, 0, 1)
self:HighlightText(0, 1)
self:Insert(nbsp)
self:Insert(text)
self:HighlightText(0, 1)
self:Insert("")
else
text = sub(text, pos, pos)
self:HighlightText(pos - 1, pos)
self:Insert(text)
end
if occ then self:SetScript("OnCursorChanged", occ) end
if otc then self:SetScript("OnTextChanged", otc) end
if ots then self:SetScript("OnTextSet", ots) end
end
local threatColors = { local threatColors = {
[0] = {0.69, 0.69, 0.69}, [0] = {0.69, 0.69, 0.69},
[1] = {1, 1, 0.47}, [1] = {1, 1, 0.47},
+1 -1
View File
@@ -590,8 +590,8 @@ function ScriptErrorsFrame_Update ()
editBox.text = text; editBox.text = text;
if (prevText ~= text) then if (prevText ~= text) then
editBox:SetText(text); editBox:SetText(text);
EditBoxSetCursorPosition(editBox, 0);
editBox:HighlightText(0); editBox:HighlightText(0);
-- editBox:SetCursorPosition(0);
else else
ScriptErrorsFrameScrollFrame:UpdateScrollChildRect(); ScriptErrorsFrameScrollFrame:UpdateScrollChildRect();
end end
+1 -1
View File
@@ -114,7 +114,7 @@ function E:DelayScriptCall(msg)
self:Print("usage: /in <seconds> <command>") self:Print("usage: /in <seconds> <command>")
self:Print("example: /in 1.5 /say hi") self:Print("example: /in 1.5 /say hi")
else else
E:ScheduleTimer(OnCallback, secs, 1, command) E:ScheduleTimer(OnCallback, secs, command)
end end
end end
+108 -104
View File
@@ -35,10 +35,6 @@ local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceAddon then return end -- No Upgrade needed. if not AceAddon then return end -- No Upgrade needed.
local AceCore = LibStub("AceCore-3.0")
local new, del = AceCore.new, AceCore.del
local wipe, truncate = AceCore.wipe, AceCore.truncate
AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
AceAddon.addons = AceAddon.addons or {} -- addons in general AceAddon.addons = AceAddon.addons or {} -- addons in general
AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon. AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
@@ -47,8 +43,8 @@ AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized
AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
-- Lua APIs -- Lua APIs
local tinsert, tconcat, tremove, tgetn = table.insert, table.concat, table.remove, table.getn local tinsert, tconcat, tremove, getn = table.insert, table.concat, table.remove, table.getn
local strfmt, tostring = string.format, tostring local fmt, gsub, tostring = string.format, string.gsub, tostring
local pairs, next, type, unpack = pairs, next, type, unpack local pairs, next, type, unpack = pairs, next, type, unpack
local loadstring, assert, error = loadstring, assert, error local loadstring, assert, error = loadstring, assert, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
@@ -60,7 +56,51 @@ local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, r
--[[ --[[
xpcall safecall implementation xpcall safecall implementation
]] ]]
local safecall = AceCore.safecall local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = xpcall, function(err) return geterrorhandler()(err) end
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = unpack(arg)
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = gsub(code,"ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
-- we check to see if the func is passed is actually a function here and don't error when it isn't
-- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
-- present execution should continue without hinderance
if type(func) == "function" then
return Dispatchers[arg.n](func, unpack(arg))
end
end
-- local functions that will be implemented further down -- local functions that will be implemented further down
local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
@@ -70,7 +110,7 @@ local function addontostring( self ) return self.name end
-- Check if the addon is queued for initialization -- Check if the addon is queued for initialization
local function queuedForInitialization(addon) local function queuedForInitialization(addon)
for i = 1, tgetn(AceAddon.initializequeue) do for i = 1, getn(AceAddon.initializequeue) do
if AceAddon.initializequeue[i] == addon then if AceAddon.initializequeue[i] == addon then
return true return true
end end
@@ -93,34 +133,23 @@ end
-- -- Create a Addon object based on the table of a frame -- -- Create a Addon object based on the table of a frame
-- local MyFrame = CreateFrame("Frame") -- local MyFrame = CreateFrame("Frame")
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0") -- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
function AceAddon:NewAddon(objectorname,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) function AceAddon:NewAddon(objectorname, ...)
local object,name local object,name
local i=1
if type(objectorname)=="table" then if type(objectorname)=="table" then
object=objectorname object=objectorname
name=a0 name=arg[1]
i=2
else else
name=objectorname name=objectorname
end end
if type(name)~="string" then if type(name)~="string" then
error(strfmt("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'.", type(name)), 2) error(fmt("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'.", type(name)), 2)
end end
if self.addons[name] then if self.addons[name] then
error(strfmt("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists.", name), 2) error(fmt("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists.", name), 2)
end end
local args = new()
args[1] = a1
args[2] = a2
args[3] = a3
args[4] = a4
args[5] = a5
args[6] = a6
args[7] = a7
args[8] = a8
args[9] = a9
args[10] = a10
object = object or {} object = object or {}
object.name = name object.name = name
@@ -137,18 +166,20 @@ function AceAddon:NewAddon(objectorname,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
object.orderedModules = {} object.orderedModules = {}
object.defaultModuleLibraries = {} object.defaultModuleLibraries = {}
Embed( object ) -- embed NewModule, GetModule methods Embed( object ) -- embed NewModule, GetModule methods
if type(objectorname)=="table" then
self:EmbedLibraries(object,nil,args) if i == 1 then
elseif a0 then self:EmbedLibraries(object, unpack(arg))
self:EmbedLibraries(object,a0,args) else
table.remove(arg, 1)
self:EmbedLibraries(object, unpack(arg))
end end
del(args)
-- add to queue of addons to be initialized upon ADDON_LOADED -- add to queue of addons to be initialized upon ADDON_LOADED
tinsert(self.initializequeue, object) tinsert(self.initializequeue, object)
return object return object
end end
--- Get the addon object by its name from the internal AceAddon registry. --- Get the addon object by its name from the internal AceAddon registry.
-- Throws an error if the addon object cannot be found (except if silent is set). -- Throws an error if the addon object cannot be found (except if silent is set).
-- @param name unique name of the addon object -- @param name unique name of the addon object
@@ -158,7 +189,7 @@ end
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon") -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
function AceAddon:GetAddon(name, silent) function AceAddon:GetAddon(name, silent)
if not silent and not self.addons[name] then if not silent and not self.addons[name] then
error(strfmt("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'.", tostring(name)), 2) error(fmt("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'.", tostring(name)), 2)
end end
return self.addons[name] return self.addons[name]
end end
@@ -171,12 +202,10 @@ end
-- @paramsig addon, [lib, ...] -- @paramsig addon, [lib, ...]
-- @param addon addon object to embed the libs in -- @param addon addon object to embed the libs in
-- @param lib List of libraries to embed into the addon -- @param lib List of libraries to embed into the addon
function AceAddon:EmbedLibraries(addon,a1,arg) function AceAddon:EmbedLibraries(addon, ...)
if a1 then self:EmbedLibrary(addon, a1, false, 4) end for i=1,arg.n do
-- 10 is the max number of variable arguments in the function NewAddon and NewModule local libname = arg[i]
for i=1,10 do self:EmbedLibrary(addon, libname, false, 4)
if not arg[i] then return end
self:EmbedLibrary(addon, arg[i], false, 4)
end end
end end
@@ -194,13 +223,13 @@ end
function AceAddon:EmbedLibrary(addon, libname, silent, offset) function AceAddon:EmbedLibrary(addon, libname, silent, offset)
local lib = LibStub:GetLibrary(libname, true) local lib = LibStub:GetLibrary(libname, true)
if not lib and not silent then if not lib and not silent then
error(strfmt("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q.", tostring(libname)), offset or 2) error(fmt("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q.", tostring(libname)), offset or 2)
elseif lib and type(lib.Embed) == "function" then elseif lib and type(lib.Embed) == "function" then
lib:Embed(addon) lib:Embed(addon)
tinsert(self.embeds[addon], libname) tinsert(self.embeds[addon], libname)
return true return true
elseif lib then elseif lib then
error(strfmt("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable", libname), offset or 2) error(fmt("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable", libname), offset or 2)
end end
end end
@@ -217,7 +246,7 @@ end
-- MyModule = MyAddon:GetModule("MyModule") -- MyModule = MyAddon:GetModule("MyModule")
function GetModule(self, name, silent) function GetModule(self, name, silent)
if not self.modules[name] and not silent then if not self.modules[name] and not silent then
error(strfmt("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'.", tostring(name)), 2) error(fmt("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'.", tostring(name)), 2)
end end
return self.modules[name] return self.modules[name]
end end
@@ -240,39 +269,26 @@ local function IsModuleTrue(self) return true end
-- -- Create a module with a prototype -- -- Create a module with a prototype
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end } -- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
-- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0") -- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
function NewModule(self, name, prototype, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) function NewModule(self, name, prototype, ...)
if type(name) ~= "string" then error(strfmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'.", type(name)), 2) end if type(name) ~= "string" then error(fmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'.", type(name)), 2) end
if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(strfmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'.", type(prototype)), 2) end if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(fmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'.", type(prototype)), 2) end
if self.modules[name] then error(strfmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists.", name), 2) end if self.modules[name] then error(fmt("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists.", name), 2) end
-- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well. -- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
-- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is. -- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
local module = AceAddon:NewAddon(strfmt("%s_%s", self.name or tostring(self), name)) local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
module.IsModule = IsModuleTrue module.IsModule = IsModuleTrue
module:SetEnabledState(self.defaultModuleState) module:SetEnabledState(self.defaultModuleState)
module.moduleName = name module.moduleName = name
local args = new()
args[1] = a1
args[2] = a2
args[3] = a3
args[4] = a4
args[5] = a5
args[6] = a6
args[7] = a7
args[8] = a8
args[9] = a9
args[10] = a10
if type(prototype) == "string" then if type(prototype) == "string" then
AceAddon:EmbedLibraries(module, prototype, args) AceAddon:EmbedLibraries(module, prototype, unpack(arg))
else else
AceAddon:EmbedLibraries(module, nil, args) AceAddon:EmbedLibraries(module, unpack(arg))
end end
del(args) AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
AceAddon:EmbedLibraries(module, nil, self.defaultModuleLibraries)
if not prototype or type(prototype) == "string" then if not prototype or type(prototype) == "string" then
prototype = self.defaultModulePrototype or nil prototype = self.defaultModulePrototype or nil
@@ -284,7 +300,7 @@ function NewModule(self, name, prototype, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
setmetatable(module, mt) -- More of a Base class type feel. setmetatable(module, mt) -- More of a Base class type feel.
end end
safecall(self.OnModuleCreated, 2, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy. safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
self.modules[name] = module self.modules[name] = module
tinsert(self.orderedModules, module) tinsert(self.orderedModules, module)
@@ -385,23 +401,11 @@ end
-- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0") -- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
-- -- Create a module -- -- Create a module
-- MyModule = MyAddon:NewModule("MyModule") -- MyModule = MyAddon:NewModule("MyModule")
function SetDefaultModuleLibraries(self,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) function SetDefaultModuleLibraries(self, ...)
if next(self.modules) then if next(self.modules) then
error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2) error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
end end
local args = self.defaultModuleLibraries or {} self.defaultModuleLibraries = arg
args[1] = a1
args[2] = a2
args[3] = a3
args[4] = a4
args[5] = a5
args[6] = a6
args[7] = a7
args[8] = a8
args[9] = a9
args[10] = a10
self.defaultModuleLibraries = args
end end
--- Set the default state in which new modules are being created. --- Set the default state in which new modules are being created.
@@ -444,7 +448,7 @@ function SetDefaultModulePrototype(self, prototype)
error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2) error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
end end
if type(prototype) ~= "table" then if type(prototype) ~= "table" then
error(strfmt("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'.", type(prototype)), 2) error(fmt("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'.", type(prototype)), 2)
end end
self.defaultModulePrototype = prototype self.defaultModulePrototype = prototype
end end
@@ -528,12 +532,12 @@ end
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing. -- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
-- @param addon addon object to intialize -- @param addon addon object to intialize
function AceAddon:InitializeAddon(addon) function AceAddon:InitializeAddon(addon)
safecall(addon.OnInitialize, 1, addon) safecall(addon.OnInitialize, addon)
local embeds = self.embeds[addon] local embeds = self.embeds[addon]
for i = 1, tgetn(embeds) do for i = 1, getn(embeds) do
local lib = LibStub:GetLibrary(embeds[i], true) local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedInitialize, 2, lib, addon) end if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
end end
-- we don't call InitializeAddon on modules specifically, this is handled -- we don't call InitializeAddon on modules specifically, this is handled
@@ -557,19 +561,19 @@ function AceAddon:EnableAddon(addon)
-- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable. -- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
self.statuses[addon.name] = true self.statuses[addon.name] = true
safecall(addon.OnEnable, 1, addon) safecall(addon.OnEnable, addon)
-- make sure we're still enabled before continueing -- make sure we're still enabled before continueing
if self.statuses[addon.name] then if self.statuses[addon.name] then
local embeds = self.embeds[addon] local embeds = self.embeds[addon]
for i = 1, tgetn(embeds) do for i = 1, getn(embeds) do
local lib = LibStub:GetLibrary(embeds[i], true) local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedEnable, 2, lib, addon) end if lib then safecall(lib.OnEmbedEnable, lib, addon) end
end end
-- enable possible modules. -- enable possible modules.
local modules = addon.orderedModules local modules = addon.orderedModules
for i = 1, tgetn(modules) do for i = 1, getn(modules) do
self:EnableAddon(modules[i]) self:EnableAddon(modules[i])
end end
end end
@@ -592,18 +596,18 @@ function AceAddon:DisableAddon(addon)
-- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable. -- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
self.statuses[addon.name] = false self.statuses[addon.name] = false
safecall(addon.OnDisable, 1, addon) safecall( addon.OnDisable, addon )
-- make sure we're still disabling... -- make sure we're still disabling...
if not self.statuses[addon.name] then if not self.statuses[addon.name] then
local embeds = self.embeds[addon] local embeds = self.embeds[addon]
for i = 1, tgetn(embeds) do for i = 1, getn(embeds) do
local lib = LibStub:GetLibrary(embeds[i], true) local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedDisable, 2, lib, addon) end if lib then safecall(lib.OnEmbedDisable, lib, addon) end
end end
-- disable possible modules. -- disable possible modules.
local modules = addon.orderedModules local modules = addon.orderedModules
for i = 1, tgetn(modules) do for i = 1, getn(modules) do
self:DisableAddon(modules[i]) self:DisableAddon(modules[i])
end end
end end
@@ -634,22 +638,13 @@ function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
local onEvent
do
local IsLoggedIn = false
-- Event Handling -- Event Handling
function onEvent() local IsLoggedIn
-- 2011-08-17 nevcairiel - ignore the load event of Blizzard_DebugTools, so a potential startup error isn't swallowed up local function onEvent()
-- Ace3v: When the ADDON_LOADED event is triggerd, global arg1 is the loaded addon name -- 2011-08-17 nevcairiel - ignore the load event of !DebugTools, so a potential startup error isn't swallowed up
-- so onEvent(event, arg1) won't work because it will cover the global variables if (event == "ADDON_LOADED" and arg1 ~= "!DebugTools") or event == "PLAYER_LOGIN" then
if (event == "ADDON_LOADED" and arg1 ~= "Blizzard_DebugTools") or event == "PLAYER_LOGIN" then
-- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration -- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
-- Ace3v: When an Ace3 addons is loaded, then he initializeque should not be empty unless while(getn(AceAddon.initializequeue) > 0) do
-- the addon does not use the library. If an addon that does not use Ace3 library
-- is loaded, we will also receive the ADDON_LOADED event but in this case the
-- queue will be empty so we have nothing to do.
while(tgetn(AceAddon.initializequeue) > 0) do
local addon = tremove(AceAddon.initializequeue, 1) local addon = tremove(AceAddon.initializequeue, 1)
-- this might be an issue with recursion - TODO: validate -- this might be an issue with recursion - TODO: validate
if event == "ADDON_LOADED" then addon.baseName = arg1 end if event == "ADDON_LOADED" then addon.baseName = arg1 end
@@ -662,14 +657,13 @@ function onEvent()
end end
if IsLoggedIn then if IsLoggedIn then
while(tgetn(AceAddon.enablequeue) > 0) do while(getn(AceAddon.enablequeue) > 0) do
local addon = tremove(AceAddon.enablequeue, 1) local addon = tremove(AceAddon.enablequeue, 1)
AceAddon:EnableAddon(addon) AceAddon:EnableAddon(addon)
end end
end end
end end
end end
end -- onEvent
AceAddon.frame:RegisterEvent("ADDON_LOADED") AceAddon.frame:RegisterEvent("ADDON_LOADED")
AceAddon.frame:RegisterEvent("PLAYER_LOGIN") AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
@@ -679,3 +673,13 @@ AceAddon.frame:SetScript("OnEvent", onEvent)
for name, addon in pairs(AceAddon.addons) do for name, addon in pairs(AceAddon.addons) do
Embed(addon, true) Embed(addon, true)
end end
-- 2010-10-27 nevcairiel - add new "orderedModules" table
if oldminor and oldminor < 10 then
for name, addon in pairs(AceAddon.addons) do
addon.orderedModules = {}
for module_name, module in pairs(addon.modules) do
tinsert(addon.orderedModules, module)
end
end
end
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceAddon-3.0.lua"/> <Script file="AceAddon-3.0.lua"/>
</Ui> </Ui>
+67 -65
View File
@@ -9,7 +9,7 @@
-- make into AceComm. -- make into AceComm.
-- @class file -- @class file
-- @name AceComm-3.0 -- @name AceComm-3.0
-- @release $Id: AceComm-3.0.lua 1107 2014-02-19 16:40:32Z nevcairiel $ -- @release $Id: AceComm-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
--[[ AceComm-3.0 --[[ AceComm-3.0
@@ -17,25 +17,23 @@ TODO: Time out old data rotting around from dead senders? Not a HUGE deal since
]] ]]
local MAJOR, MINOR = "AceComm-3.0", 9 local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib")
local MAJOR, MINOR = "AceComm-3.0", 10
local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR) local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceComm then return end if not AceComm then return end
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib")
-- Lua APIs -- Lua APIs
local type, next, pairs, tostring = type, next, pairs, tostring local type, next, pairs, tostring, unpack = type, next, pairs, tostring, unpack
local strlen, strsub, strfind = string.len, string.sub, string.find local strsub, strfind, strlen = string.sub, string.find, string.len
local tinsert, tconcat, tgetn, tremove = table.insert, table.concat, table.getn, table.remove local tinsert, tconcat, tremove = table.insert, table.concat, table.remove
local error, assert = error, assert local error, assert = error, assert
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script -- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler, RegisterAddonMessagePrefix -- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler
AceComm.embeds = AceComm.embeds or {} AceComm.embeds = AceComm.embeds or {}
@@ -43,27 +41,21 @@ AceComm.embeds = AceComm.embeds or {}
local MSG_MULTI_FIRST = "\001" local MSG_MULTI_FIRST = "\001"
local MSG_MULTI_NEXT = "\002" local MSG_MULTI_NEXT = "\002"
local MSG_MULTI_LAST = "\003" local MSG_MULTI_LAST = "\003"
local MSG_ESCAPE = "\004"
-- remove old structures (pre WoW 4.0) AceComm.multipart_origprefixes = AceComm.multipart_origprefixes or {} -- e.g. "Prefix\001"="Prefix", "Prefix\002"="Prefix"
AceComm.multipart_origprefixes = nil AceComm.multipart_reassemblers = AceComm.multipart_reassemblers or {} -- e.g. "Prefix\001"="OnReceiveMultipartFirst"
AceComm.multipart_reassemblers = nil
-- the multipart message spool: indexed by a combination of sender+distribution+ -- the multipart message spool: indexed by a combination of sender+distribution+
AceComm.multipart_spool = AceComm.multipart_spool or {} AceComm.multipart_spool = AceComm.multipart_spool or {}
--- Register for Addon Traffic on a specified prefix --- Register for Addon Traffic on a specified prefix
-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent), max 16 characters -- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived" -- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived"
function AceComm:RegisterComm(prefix, method) function AceComm:RegisterComm(prefix, method)
if method == nil then if method == nil then
method = "OnCommReceived" method = "OnCommReceived"
end end
if strlen(prefix) > 16 then -- TODO: 15?
error("AceComm:RegisterComm(prefix,method): prefix length is limited to 16 characters")
end
return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler
end end
@@ -88,10 +80,19 @@ function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callb
error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2) error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2)
end end
if strfind(prefix, "[\001-\009]") then
if strfind(prefix, "[\001-\003]") then
error("SendCommMessage: Characters \\001--\\003 in prefix are reserved for AceComm metadata", 2)
elseif not warnedPrefix then
-- I have some ideas about future extensions that require more control characters /mikk, 20090808
geterrorhandler()("SendCommMessage: Heads-up developers: Characters \\004--\\009 in prefix are reserved for AceComm future extension")
warnedPrefix = true
end
end
local textlen = strlen(text) local textlen = strlen(text)
-- Yes, the max is 255 even if the dev post said 256. I tested. Char 256+ get silently truncated. /Mikk, 20110327 local maxtextlen = 254 - strlen(prefix) -- 254 is the max length of prefix + text that can be sent in one message
-- Ace3v: substract the prefix length
local maxtextlen = 254 - strlen(prefix)
local queueName = prefix..distribution..(target or "") local queueName = prefix..distribution..(target or "")
local ctlCallback = nil local ctlCallback = nil
@@ -101,38 +102,29 @@ function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callb
end end
end end
local forceMultipart if textlen <= maxtextlen then
if strfind(text, "^[\001-\009]") then -- 4.1+: see if the first character is a control character
-- we need to escape the first character with a \004
if textlen+1 > maxtextlen then -- would we go over the size limit?
forceMultipart = true -- just make it multipart, no escape problems then
else
text = "\004" .. text
end
end
if not forceMultipart and textlen <= maxtextlen then
-- fits all in one message -- fits all in one message
CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen) CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen)
else else
maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix(4.0)/start of message(4.1) maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix
-- first part -- first part
local chunk = strsub(text, 1, maxtextlen) local chunk = strsub(text, 1, maxtextlen)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_FIRST..chunk, distribution, target, queueName, ctlCallback, maxtextlen) CTL:SendAddonMessage(prio, prefix..MSG_MULTI_FIRST, chunk, distribution, target, queueName, ctlCallback, maxtextlen)
-- continuation -- continuation
local pos = 1+maxtextlen local pos = 1+maxtextlen
local prefix2 = prefix..MSG_MULTI_NEXT
while pos+maxtextlen <= textlen do while pos+maxtextlen <= textlen do
chunk = strsub(text, pos, pos+maxtextlen-1) chunk = strsub(text, pos, pos+maxtextlen-1)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_NEXT..chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1) CTL:SendAddonMessage(prio, prefix2, chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1)
pos = pos + maxtextlen pos = pos + maxtextlen
end end
-- final part -- final part
chunk = strsub(text, pos) chunk = strsub(text, pos)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_LAST..chunk, distribution, target, queueName, ctlCallback, textlen) CTL:SendAddonMessage(prio, prefix..MSG_MULTI_LAST, chunk, distribution, target, queueName, ctlCallback, textlen)
end end
end end
@@ -147,8 +139,8 @@ do
local t = next(compost) local t = next(compost)
if t then if t then
compost[t]=nil compost[t]=nil
for i=tgetn(t),3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten for i=getn(t),3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten
tremove(t) -- Ace3v: t[i] = nil wont affect the tgetn return value tremove(t, i)
end end
return t return t
end end
@@ -210,11 +202,11 @@ do
if type(olddata) == "table" then if type(olddata) == "table" then
-- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat -- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat
tinsert(olddata, message) tinsert(olddata, message)
AceComm.callbacks:Fire(prefix, 3, tconcat(olddata, ""), distribution, sender) AceComm.callbacks:Fire(prefix, tconcat(olddata, ""), distribution, sender)
compost[olddata] = true compost[olddata] = true
else else
-- if we've only received a "first", the spooled data will still only be a string -- if we've only received a "first", the spooled data will still only be a string
AceComm.callbacks:Fire(prefix, 3, olddata..message, distribution, sender) AceComm.callbacks:Fire(prefix, olddata..message, distribution, sender)
end end
end end
end end
@@ -229,40 +221,50 @@ end
---------------------------------------- ----------------------------------------
if not AceComm.callbacks then if not AceComm.callbacks then
-- ensure that 'prefix to watch' table is consistent with registered
-- callbacks
AceComm.__prefixes = {}
AceComm.callbacks = CallbackHandler:New(AceComm, AceComm.callbacks = CallbackHandler:New(AceComm,
"_RegisterComm", "_RegisterComm",
"UnregisterComm", "UnregisterComm",
"UnregisterAllComm") "UnregisterAllComm")
end end
AceComm.callbacks.OnUsed = nil function AceComm.callbacks:OnUsed(target, prefix)
AceComm.callbacks.OnUnused = nil AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = prefix
AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = "OnReceiveMultipartFirst"
-- Ace3v: in vanilla, global vars: AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = prefix
-- event -> event type AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = "OnReceiveMultipartNext"
-- arg1 -> prefix
-- arg2 -> message AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = prefix
-- arg3 -> channel AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = "OnReceiveMultipartLast"
-- arg4 -> sender
local function OnEvent()
local prefix, message, distribution, sender = arg1, arg2, arg3, arg4
if event == "CHAT_MSG_ADDON" then
local _, _, control, rest = strfind(message, "^([\001-\009])(.*)")
if control then
if control==MSG_MULTI_FIRST then
AceComm:OnReceiveMultipartFirst(prefix, rest, distribution, sender)
elseif control==MSG_MULTI_NEXT then
AceComm:OnReceiveMultipartNext(prefix, rest, distribution, sender)
elseif control==MSG_MULTI_LAST then
AceComm:OnReceiveMultipartLast(prefix, rest, distribution, sender)
elseif control==MSG_ESCAPE then
AceComm.callbacks:Fire(prefix, 3, rest, distribution, sender)
else
-- unknown control character, ignore SILENTLY (dont warn unnecessarily about future extensions!)
end end
function AceComm.callbacks:OnUnused(target, prefix)
AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = nil
AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = nil
AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = nil
end
local function OnEvent()
if event == "CHAT_MSG_ADDON" then
local prefix,message,distribution,sender = unpack(arg)
local reassemblername = AceComm.multipart_reassemblers[prefix]
if reassemblername then
-- multipart: reassemble
local aceCommReassemblerFunc = AceComm[reassemblername]
local origprefix = AceComm.multipart_origprefixes[prefix]
aceCommReassemblerFunc(AceComm, origprefix, message, distribution, sender)
else else
-- single part: fire it off immediately and let CallbackHandler decide if it's registered or not -- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
AceComm.callbacks:Fire(prefix, 3, message, distribution, sender) AceComm.callbacks:Fire(prefix, message, distribution, sender)
end end
else else
assert(false, "Received "..tostring(event).." event?!") assert(false, "Received "..tostring(event).." event?!")
+2 -1
View File
@@ -1,4 +1,5 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="ChatThrottleLib.lua"/> <Script file="ChatThrottleLib.lua"/>
<Script file="AceComm-3.0.lua"/> <Script file="AceComm-3.0.lua"/>
</Ui> </Ui>
+25 -48
View File
@@ -20,15 +20,10 @@
-- --
-- Can run as a standalone addon also, but, really, just embed it! :-) -- Can run as a standalone addon also, but, really, just embed it! :-)
-- --
-- LICENSE: ChatThrottleLib is released into the Public Domain
--
local CTL_VERSION = 23 local CTL_VERSION = 21
local AceCore = LibStub("AceCore-3.0") local _G = _G
local _G = AceCore._G
local hooksecurefunc = AceCore.hooksecurefunc
local wipe = AceCore.wipe
if _G.ChatThrottleLib then if _G.ChatThrottleLib then
if _G.ChatThrottleLib.version >= CTL_VERSION then if _G.ChatThrottleLib.version >= CTL_VERSION then
@@ -69,8 +64,8 @@ ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) i
local setmetatable = setmetatable local setmetatable = setmetatable
local table_insert = table.insert
local table_remove = table.remove local table_remove = table.remove
local tinsert = table.insert
local tostring = tostring local tostring = tostring
local GetTime = GetTime local GetTime = GetTime
local math_min = math.min local math_min = math.min
@@ -78,9 +73,7 @@ local math_max = math.max
local next = next local next = next
local strlen = string.len local strlen = string.len
local GetFramerate = GetFramerate local GetFramerate = GetFramerate
local strlower = string.lower
local unpack,type,pairs,wipe = unpack,type,pairs,wipe
local UnitInRaid,UnitInParty = UnitInRaid,UnitInParty
----------------------------------------------------------------------- -----------------------------------------------------------------------
@@ -123,20 +116,24 @@ end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Recycling bin for pipes -- Recycling bin for pipes
-- A pipe is a plain integer-indexed queue of messages -- A pipe is a plain integer-indexed queue, which also happens to be a ring member
-- Pipes normally live in Rings of pipes (3 rings total, one per priority)
ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
local PipeBin = setmetatable({}, {__mode="k"}) local PipeBin = setmetatable({}, {__mode="k"})
local function DelPipe(pipe) local function DelPipe(pipe)
for i = getn(pipe), 1, -1 do
pipe[i] = nil
end
pipe.prev = nil
pipe.next = nil
PipeBin[pipe] = true PipeBin[pipe] = true
end end
local function NewPipe() local function NewPipe()
local pipe = next(PipeBin) local pipe = next(PipeBin)
if pipe then if pipe then
wipe(pipe)
PipeBin[pipe] = nil PipeBin[pipe] = nil
return pipe return pipe
end end
@@ -230,7 +227,7 @@ end
local bMyTraffic = false local bMyTraffic = false
function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination) function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...)
if bMyTraffic then if bMyTraffic then
return return
end end
@@ -239,7 +236,7 @@ function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destinat
self.avail = self.avail - size self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic self.nBypass = self.nBypass + size -- just a statistic
end end
function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination) function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...)
if bMyTraffic then if bMyTraffic then
return return
end end
@@ -266,7 +263,7 @@ function ChatThrottleLib:UpdateAvail()
-- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then -- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5) avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5)
self.bChoking = true self.bChoking = true
elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs elseif GetFramerate() < self.MIN_FPS then -- GetFramerate call takes ~0.002 secs
avail = math_min(MAX_CPS, avail + newavail*0.5) avail = math_min(MAX_CPS, avail + newavail*0.5)
self.bChoking = true -- just a statistic self.bChoking = true -- just a statistic
else else
@@ -285,16 +282,12 @@ end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Despooling logic -- Despooling logic
-- Reminder:
-- - We have 3 Priorities, each containing a "Ring" construct ...
-- - ... made up of N "Pipe"s (1 for each destination/pipename)
-- - and each pipe contains messages
function ChatThrottleLib:Despool(Prio) function ChatThrottleLib:Despool(Prio)
local ring = Prio.Ring local ring = Prio.Ring
while ring.pos and Prio.avail > ring.pos[1].nSize do while ring.pos and Prio.avail > ring.pos[1].nSize do
local msg = table_remove(ring.pos, 1) local msg = table_remove(Prio.Ring.pos, 1)
if not ring.pos[1] then -- did we remove last msg in this pipe? if not Prio.Ring.pos[1] then
local pipe = Prio.Ring.pos local pipe = Prio.Ring.pos
Prio.Ring:Remove(pipe) Prio.Ring:Remove(pipe)
Prio.ByName[pipe.name] = nil Prio.ByName[pipe.name] = nil
@@ -302,26 +295,15 @@ function ChatThrottleLib:Despool(Prio)
else else
Prio.Ring.pos = Prio.Ring.pos.next Prio.Ring.pos = Prio.Ring.pos.next
end end
local didSend=false
local lowerDest = strlower(msg[3] or "")
if lowerDest == "raid" and not UnitInRaid("player") then
-- do nothing
elseif lowerDest == "party" and not UnitInParty("player") then
-- do nothing
else
Prio.avail = Prio.avail - msg.nSize Prio.avail = Prio.avail - msg.nSize
bMyTraffic = true bMyTraffic = true
msg.f(unpack(msg, 1, msg.n)) msg.f(unpack(msg, 1, msg.n))
bMyTraffic = false bMyTraffic = false
Prio.nTotalSent = Prio.nTotalSent + msg.nSize Prio.nTotalSent = Prio.nTotalSent + msg.nSize
DelMsg(msg) DelMsg(msg)
didSend = true
end
-- notify caller of delivery (even if we didn't send it)
if msg.callbackFn then if msg.callbackFn then
msg.callbackFn (msg.callbackArg, didSend) msg.callbackFn (msg.callbackArg)
end end
-- USER CALLBACK MAY ERROR
end end
end end
@@ -393,6 +375,7 @@ end
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- Spooling logic -- Spooling logic
function ChatThrottleLib:Enqueue(prioname, pipename, msg) function ChatThrottleLib:Enqueue(prioname, pipename, msg)
local Prio = self.Prio[prioname] local Prio = self.Prio[prioname]
local pipe = Prio.ByName[pipename] local pipe = Prio.ByName[pipename]
@@ -404,11 +387,13 @@ function ChatThrottleLib:Enqueue(prioname, pipename, msg)
Prio.Ring:Add(pipe) Prio.Ring:Add(pipe)
end end
tinsert(pipe,msg) table_insert(pipe, msg)
self.bQueueing = true self.bQueueing = true
end end
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg) function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not self.Prio[prio] then if not self or not prio or not prefix or not text or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2) error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2)
@@ -433,9 +418,8 @@ function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, languag
bMyTraffic = false bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then if callbackFn then
callbackFn (callbackArg, true) callbackFn (callbackArg)
end end
-- USER CALLBACK MAY ERROR
return return
end end
@@ -463,18 +447,11 @@ function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target,
error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2) error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
end end
local nSize = strlen(text); local nSize = strlen(prefix) + 1 + strlen(text);
if RegisterAddonMessagePrefix then
if nSize>255 then
error("ChatThrottleLib:SendAddonMessage(): message length cannot exceed 255 bytes", 2)
end
else
nSize = nSize + strlen(prefix) + 1
if nSize>255 then if nSize>255 then
error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2) error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2)
end end
end
nSize = nSize + self.MSG_OVERHEAD; nSize = nSize + self.MSG_OVERHEAD;
@@ -486,9 +463,8 @@ function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target,
bMyTraffic = false bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then if callbackFn then
callbackFn (callbackArg, true) callbackFn (callbackArg)
end end
-- USER CALLBACK MAY ERROR
return return
end end
@@ -525,3 +501,4 @@ if(WOWB_VER) then
end end
]] ]]
@@ -16,49 +16,36 @@ local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConsole then return end -- No upgrade needed if not AceConsole then return end -- No upgrade needed
local AceCore = LibStub("AceCore-3.0")
AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in. AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
AceConsole.commands = AceConsole.commands or {} -- table containing commands registered AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
-- Lua APIs -- Lua APIs
local tinsert, tconcat, tgetn, tsetn = table.insert, table.concat, table.getn, table.setn local tconcat, tostring = table.concat, tostring
local tostring = tostring
local type, pairs, error = type, pairs, error local type, pairs, error = type, pairs, error
local format, strfind, strsub = string.format, string.find, string.sub local format, strfind, strsub, upper, lower = string.format, string.find, string.sub, string.upper, string.lower
local max = math.max local max = math.max
local strupper, strlower = string.upper, string.lower
-- WoW APIs -- WoW APIs
local _G = AceCore._G local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script -- List them here for Mikk's FindGlobals script
-- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList -- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
local Print
do
local tmp={} local tmp={}
function Print(self, frame, arg) local function Print(self,frame,...)
local n=0
if self ~= AceConsole then if self ~= AceConsole then
tmp[1] = "|cff33ff99"..tostring(self).."|r:" n=n+1
else tmp[n] = "|cff33ff99"..tostring( self ).."|r:"
tmp[1] = ''
end end
if type(arg) == "string" then for i=1, arg.n do
frame:AddMessage(tmp[1]..arg) n=n+1
else -- arg is table and may contain frame as first element if argument frame is nil tmp[n] = tostring(arg[i])
local b, e = frame and 1 or 2, tgetn(arg)
if e >= b then
frame = frame or arg[1]
for i=0,e-b do
tmp[2+i] = tostring(arg[b+i])
end end
frame:AddMessage(tconcat(tmp," ",1,e-b+2)) -- explicitly, because the length is not affected by assignment frame:AddMessage( tconcat(tmp," ",1,n) )
end end
end
end
end -- Print
--- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function) --- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
-- @paramsig [chatframe ,] ... -- @paramsig [chatframe ,] ...
@@ -67,59 +54,50 @@ end -- Print
function AceConsole:Print(...) function AceConsole:Print(...)
local frame = arg[1] local frame = arg[1]
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member? if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
return Print(self, nil, arg) return Print(self, unpack(arg))
else else
return Print(self, DEFAULT_CHAT_FRAME, arg) return Print(self, DEFAULT_CHAT_FRAME, unpack(arg))
end end
end end
--- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function) --- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
-- @paramsig [chatframe ,] "format"[, ...] -- @paramsig [chatframe ,] "format"[, ...]
-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function) -- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
-- @param format Format string - same syntax as standard Lua format() -- @param format Format string - same syntax as standard Lua format()
-- @param ... Arguments to the format string -- @param ... Arguments to the format string
function AceConsole:Printf(a1, ...) function AceConsole:Printf(...)
local frame, succ, s local frame = arg[1]
if type(a1) == "table" and a1.AddMessage then -- Is first argument something with an .AddMessage member? if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
frame, succ, s = a1, pcall(format, unpack(arg)) tremove(arg, 1)
return Print(self, frame, format(unpack(arg)))
else else
frame, succ, s = DEFAULT_CHAT_FRAME, pcall(format, a1, unpack(arg)) return Print(self, DEFAULT_CHAT_FRAME, format(unpack(arg)))
end end
if not succ then error(s,2) end
return Print(self, frame, s)
end end
--- Register a simple chat command --- Register a simple chat command
-- @param command Chat command to be registered WITHOUT leading "/" -- @param command Chat command to be registered WITHOUT leading "/"
-- @param func Function to call when the slash command is being used (funcref or methodname) -- @param func Function to call when the slash command is being used (funcref or methodname)
-- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true) -- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
function AceConsole:RegisterChatCommand( command, func, persist ) function AceConsole:RegisterChatCommand( command, func, persist )
if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand(command, func[, persist ]): 'command' - expected a string]], 2) end if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand( "command", func[, persist ]): 'command' - expected a string]], 2) end
if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
local name = "ACECONSOLE_"..strupper(command) local name = "ACECONSOLE_"..upper(command)
local t = type(func) if type( func ) == "string" then
if t == "string" then
-- Ace3v: prevent user from using AceConSole as self
if self == AceConsole then
error([[Usage: RegisterChatCommand(command, func[, persist]): 'self' - use your own 'self']], 2)
end
SlashCmdList[name] = function(input, editBox) SlashCmdList[name] = function(input, editBox)
self[func](self, input, editBox) self[func](self, input, editBox)
end end
elseif t == "function" then
SlashCmdList[name] = func
else else
error([[Usage: AceConsole:RegisterChatCommand(command, func[, persist ]): 'func' - expected a string or a function]], 2) SlashCmdList[name] = func
end end
_G["SLASH_"..name.."1"] = "/"..strlower(command) _G["SLASH_"..name.."1"] = "/"..lower(command)
AceConsole.commands[command] = name AceConsole.commands[command] = name
-- non-persisting commands are registered for enabling disabling -- non-persisting commands are registered for enabling disabling
if not persist then if not persist then
@@ -136,6 +114,7 @@ function AceConsole:UnregisterChatCommand( command )
if name then if name then
SlashCmdList[name] = nil SlashCmdList[name] = nil
_G["SLASH_" .. name .. "1"] = nil _G["SLASH_" .. name .. "1"] = nil
hash_SlashCmdList["/" .. upper(command)] = nil
AceConsole.commands[command] = nil AceConsole.commands[command] = nil
end end
end end
@@ -144,16 +123,18 @@ end
-- @return Iterator (pairs) over all commands -- @return Iterator (pairs) over all commands
function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
local function nils(n,argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
if n >= 1 then local function nils(n, ...)
return nil, nils(n-1,argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) if n>1 then
elseif not argc or argc == 0 then return nil, nils(n-1, unpack(arg))
return elseif n==1 then
return nil, unpack(arg)
else else
return a1, nils(0,argc-1,a2,a3,a4,a5,a6,a7,a8,a9,a10) return unpack(arg)
end end
end end
--- Retreive one or more space-separated arguments from a string. --- Retreive one or more space-separated arguments from a string.
-- Treats quoted strings and itemlinks as non-spaced. -- Treats quoted strings and itemlinks as non-spaced.
-- @param str The raw argument string -- @param str The raw argument string
@@ -170,7 +151,7 @@ function AceConsole:GetArgs(str, numargs, startpos)
-- find start of new arg -- find start of new arg
pos = strfind(str, "[^ ]", pos) pos = strfind(str, "[^ ]", pos)
if not pos then -- whoops, end of string if not pos then -- whoops, end of string
return nils(numargs, 1, 1e9) return nils(numargs, 1e9)
end end
if numargs<1 then if numargs<1 then
@@ -225,7 +206,7 @@ function AceConsole:GetArgs(str, numargs, startpos)
end end
-- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink) -- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
return strsub(str, startpos), nils(numargs-1, 1, 1e9) return strsub(str, startpos), nils(numargs-1, 1e9)
end end
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceConsole-3.0.lua"/> <Script file="AceConsole-3.0.lua"/>
</Ui> </Ui>
-204
View File
@@ -1,204 +0,0 @@
local ACECORE_MAJOR, ACECORE_MINOR = "AceCore-3.0", 1
local AceCore, oldminor = LibStub:NewLibrary(ACECORE_MAJOR, ACECORE_MINOR)
if not AceCore then return end -- No upgrade needed
AceCore._G = AceCore._G or _G
local _G = AceCore._G
local strsub, strgsub, strfind = string.sub, string.gsub, string.find
local tremove, tconcat = table.remove, table.concat
local tgetn, tsetn = table.getn, table.setn
local new, del
do
local list = setmetatable({}, {__mode = "k"})
function new()
local t = next(list)
if not t then
return {}
end
list[t] = nil
return t
end
function del(t)
setmetatable(t, nil)
for k in pairs(t) do
t[k] = nil
end
tsetn(t,0)
list[t] = true
end
-- debug
function AceCore.listcount()
local count = 0
for k in list do
count = count + 1
end
return count
end
end -- AceCore.new, AceCore.del
AceCore.new, AceCore.del = new, del
local function errorhandler(err)
return geterrorhandler()(err)
end
AceCore.errorhandler = errorhandler
local function CreateSafeDispatcher(argCount)
local code = [[
local errorhandler = LibStub("AceCore-3.0").errorhandler
local method, UP_ARGS
local function call()
local func, ARGS = method, UP_ARGS
method, UP_ARGS = nil, NILS
return func(ARGS)
end
return function(func, ARGS)
method, UP_ARGS = func, ARGS
return xpcall(call, errorhandler)
end
]]
local c = 4*argCount-1
local s = "b01,b02,b03,b04,b05,b06,b07,b08,b09,b10,b11,b12,b13,b14,b15,b16,b17,b18,b19,b20"
code = strgsub(code, "UP_ARGS", string.sub(s,1,c))
s = "a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20"
code = strgsub(code, "ARGS", string.sub(s,1,c))
s = "nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil"
code = strgsub(code, "NILS", string.sub(s,1,c))
return assert(loadstring(code, "safecall SafeDispatcher["..tostring(argCount).."]"))()
end
local SafeDispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher
if argCount > 0 then
dispatcher = CreateSafeDispatcher(argCount)
else
dispatcher = function(func) return xpcall(func,errorhandler) end
end
rawset(self, argCount, dispatcher)
return dispatcher
end})
local function safecall(func,argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
-- we check to see if the func is passed is actually a function here and don't error when it isn't
-- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
-- present execution should continue without hinderance
if type(func) == "function" then
return SafeDispatchers[argc](func,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
end
end
AceCore.safecall = safecall
local function CreateDispatcher(argCount)
local code = [[
return function(func,ARGS)
return func(ARGS)
end
]]
local s = "a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20"
code = strgsub(code, "ARGS", string.sub(s,1,4*argCount-1))
return assert(loadstring(code, "call Dispatcher["..tostring(argCount).."]"))()
end
AceCore.Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher
if argCount > 0 then
dispatcher = CreateDispatcher(argCount)
else
dispatcher = function(func) return func() end
end
rawset(self, argCount, dispatcher)
return dispatcher
end})
-- some string functions
-- vanilla available string operations:
-- sub, gfind, rep, gsub, char, dump, find, upper, len, format, byte, lower
-- we will just replace every string.match with string.find in the code
function AceCore.strtrim(s)
return strgsub(s, "^%s*(.-)%s*$", "%1")
end
local function strsplit(delim, s, n)
if n and n < 2 then return s end
local beg = beg or 1
local i,j = string.find(s,delim,beg)
if not i then
return s, nil
end
return string.sub(s,1,j-1), strsplit(delim, string.sub(s,j+1), n and n-1 or nil)
end
AceCore.strsplit = strsplit
-- Ace3v: fonctions copied from AceHook-2.1
local protFuncs = {
CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true,
TurnOrActionStart = true, TurnOrActionStop = true,
PitchUpStart = true, PitchUpStop = true,
PitchDownStart = true, PitchDownStop = true,
MoveBackwardStart = true, MoveBackwardStop = true,
MoveForwardStart = true, MoveForwardStop = true,
Jump = true, StrafeLeftStart = true,
StrafeLeftStop = true, StrafeRightStart = true,
StrafeRightStop = true, ToggleMouseMove = true,
ToggleRun = true, TurnLeftStart = true,
TurnLeftStop = true, TurnRightStart = true,
TurnRightStop = true,
}
local function issecurevariable(x)
return protFuncs[x] and 1 or nil
end
AceCore.issecurevariable = issecurevariable
local function hooksecurefunc(arg1, arg2, arg3)
if type(arg1) == "string" then
arg1, arg2, arg3 = _G, arg1, arg2
end
local orig = arg1[arg2]
if type(orig) ~= "function" then
error("The function "..arg2.." does not exist", 2)
end
arg1[arg2] = function(...)
local tmp = {orig(unpack(arg))}
arg3(unpack(arg))
return unpack(tmp)
end
end
AceCore.hooksecurefunc = hooksecurefunc
-- pickfirstset() - picks the first non-nil value and returns it
local function pickfirstset(argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
if (argc <= 1) or (a1 ~= nil) then
return a1
else
return pickfirstset(argc-1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
end
end
AceCore.pickfirstset = pickfirstset
local function countargs(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
if (a1 == nil) then return 0 end
return 1 + countargs(a2,a3,a4,a5,a6,a7,a8,a9,a10)
end
AceCore.countargs = countargs
-- wipe preserves metatable
function AceCore.wipe(t)
for k,v in pairs(t) do t[k] = nil end
tsetn(t,0)
return t
end
function AceCore.truncate(t,e)
e = e or tgetn(t)
for i=1,e do
if t[i] == nil then
tsetn(t,i-1)
return
end
end
tsetn(t,e)
end
@@ -1,3 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script file="AceCore-3.0.lua"/>
</Ui>
+20 -27
View File
@@ -40,22 +40,19 @@
-- end -- end
-- @class file -- @class file
-- @name AceDB-3.0.lua -- @name AceDB-3.0.lua
-- @release $Id: AceDB-3.0.lua 1142 2016-07-11 08:36:19Z nevcairiel $ -- @release $Id: AceDB-3.0.lua 1124 2014-10-27 21:00:07Z funkydude $
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 26 local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 26
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR) local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
if not AceDB then return end -- No upgrade needed if not AceDB then return end -- No upgrade needed
local AceCore = LibStub("AceCore-3.0")
local new, del = AceCore.new, AceCore.del
-- Lua APIs -- Lua APIs
local type, pairs, next, error = type, pairs, next, error local type, pairs, next, error = type, pairs, next, error
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
local format, lower = string.format, string.lower local format = string.format
-- WoW APIs -- WoW APIs
local _G = AceCore._G local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script -- List them here for Mikk's FindGlobals script
@@ -69,13 +66,6 @@ local CallbackDummy = { Fire = function() end }
local DBObjectLib = {} local DBObjectLib = {}
-- Ace3v: for all recursive functions we must declare the iterator as local again, this step is necessary in vanilla
-- Example:
-- for k,v in pairs(table) do
-- local v = v
-- ...
--[[------------------------------------------------------------------------- --[[-------------------------------------------------------------------------
AceDB Utility Functions AceDB Utility Functions
---------------------------------------------------------------------------]] ---------------------------------------------------------------------------]]
@@ -227,9 +217,10 @@ local dbmt = {
local defaults = defaultTbl and defaultTbl[section] local defaults = defaultTbl and defaultTbl[section]
if section == "profile" then if section == "profile" then
if initSection(t, section, "profiles", key, defaults) then local new = initSection(t, section, "profiles", key, defaults)
if new then
-- Callback: OnNewProfile, database, newProfileKey -- Callback: OnNewProfile, database, newProfileKey
t.callbacks:Fire("OnNewProfile", 2, t, key) t.callbacks:Fire("OnNewProfile", t, key)
end end
elseif section == "profiles" then elseif section == "profiles" then
local sv = rawget(t, "sv") local sv = rawget(t, "sv")
@@ -273,10 +264,11 @@ local realmKey = GetRealmName()
local charKey = UnitName("player") .. " - " .. realmKey local charKey = UnitName("player") .. " - " .. realmKey
local _, classKey = UnitClass("player") local _, classKey = UnitClass("player")
local _, raceKey = UnitRace("player") local _, raceKey = UnitRace("player")
local _, factionKey = UnitFactionGroup("player") local factionKey = UnitFactionGroup("player")
-- Ace3v: the faction key may error when in GM mode
factionKey = factionKey or "Others" factionKey = factionKey or "Others"
local localeKey = lower(GetLocale()) local factionrealmKey = factionKey .. " - " .. realmKey
local factionrealmregionKey = factionrealmKey .. " - " .. string.upper(string.sub(GetCVar("realmList"), 1, 2))
local localeKey = string.lower(GetLocale())
-- Actual database initialization function -- Actual database initialization function
local function initdb(sv, defaults, defaultProfile, olddb, parent) local function initdb(sv, defaults, defaultProfile, olddb, parent)
@@ -312,7 +304,8 @@ local function initdb(sv, defaults, defaultProfile, olddb, parent)
["class"] = classKey, ["class"] = classKey,
["race"] = raceKey, ["race"] = raceKey,
["faction"] = factionKey, ["faction"] = factionKey,
["factionrealm"] = factionKey .. " - " .. realmKey, ["factionrealm"] = factionrealmKey,
["factionrealmregion"] = factionrealmregionKey,
["profile"] = profileKey, ["profile"] = profileKey,
["locale"] = localeKey, ["locale"] = localeKey,
["global"] = true, ["global"] = true,
@@ -369,7 +362,7 @@ end
local function logoutHandler() local function logoutHandler()
if event == "PLAYER_LOGOUT" then if event == "PLAYER_LOGOUT" then
for db in pairs(AceDB.db_registry) do for db in pairs(AceDB.db_registry) do
db.callbacks:Fire("OnDatabaseShutdown", 1, db) db.callbacks:Fire("OnDatabaseShutdown", db)
db:RegisterDefaults(nil) db:RegisterDefaults(nil)
-- cleanup sections that are empty without defaults -- cleanup sections that are empty without defaults
@@ -449,7 +442,7 @@ function DBObjectLib:SetProfile(name)
local defaults = self.defaults and self.defaults.profile local defaults = self.defaults and self.defaults.profile
-- Callback: OnProfileShutdown, database -- Callback: OnProfileShutdown, database
self.callbacks:Fire("OnProfileShutdown", 1, self) self.callbacks:Fire("OnProfileShutdown", self)
if oldProfile and defaults then if oldProfile and defaults then
-- Remove the defaults from the old profile -- Remove the defaults from the old profile
@@ -473,7 +466,7 @@ function DBObjectLib:SetProfile(name)
end end
-- Callback: OnProfileChanged, database, newProfileKey -- Callback: OnProfileChanged, database, newProfileKey
self.callbacks:Fire("OnProfileChanged", 2, self, name) self.callbacks:Fire("OnProfileChanged", self, name)
end end
--- Returns a table with the names of the existing profiles in the database. --- Returns a table with the names of the existing profiles in the database.
@@ -549,7 +542,7 @@ function DBObjectLib:DeleteProfile(name, silent)
end end
-- Callback: OnProfileDeleted, database, profileKey -- Callback: OnProfileDeleted, database, profileKey
self.callbacks:Fire("OnProfileDeleted", 2, self, name) self.callbacks:Fire("OnProfileDeleted", self, name)
end end
--- Copies a named profile into the current profile, overwriting any conflicting --- Copies a named profile into the current profile, overwriting any conflicting
@@ -585,7 +578,7 @@ function DBObjectLib:CopyProfile(name, silent)
end end
-- Callback: OnProfileCopied, database, sourceProfileKey -- Callback: OnProfileCopied, database, sourceProfileKey
self.callbacks:Fire("OnProfileCopied", 2, self, name) self.callbacks:Fire("OnProfileCopied", self, name)
end end
--- Resets the current profile to the default values (if specified). --- Resets the current profile to the default values (if specified).
@@ -612,7 +605,7 @@ function DBObjectLib:ResetProfile(noChildren, noCallbacks)
-- Callback: OnProfileReset, database -- Callback: OnProfileReset, database
if not noCallbacks then if not noCallbacks then
self.callbacks:Fire("OnProfileReset", 2, self, self.keys["profile"]) self.callbacks:Fire("OnProfileReset", self)
end end
end end
@@ -643,9 +636,9 @@ function DBObjectLib:ResetDB(defaultProfile)
end end
-- Callback: OnDatabaseReset, database -- Callback: OnDatabaseReset, database
self.callbacks:Fire("OnDatabaseReset", 1, self) self.callbacks:Fire("OnDatabaseReset", self)
-- Callback: OnProfileChanged, database, profileKey -- Callback: OnProfileChanged, database, profileKey
self.callbacks:Fire("OnProfileChanged", 2, self, self.keys["profile"]) self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
return self return self
end end
+2 -1
View File
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceDB-3.0.lua"/> <Script file="AceDB-3.0.lua"/>
</Ui> </Ui>
@@ -10,7 +10,9 @@
-- @class file -- @class file
-- @name AceEvent-3.0 -- @name AceEvent-3.0
-- @release $Id: AceEvent-3.0.lua 975 2010-10-23 11:26:18Z nevcairiel $ -- @release $Id: AceEvent-3.0.lua 975 2010-10-23 11:26:18Z nevcairiel $
local MAJOR, MINOR = "AceEvent-3.0", 3 local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
local MAJOR, MINOR = "AceEvent-3.0", 4
local AceEvent = LibStub:NewLibrary(MAJOR, MINOR) local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
if not AceEvent then return end if not AceEvent then return end
@@ -18,8 +20,6 @@ if not AceEvent then return end
-- Lua APIs -- Lua APIs
local pairs = pairs local pairs = pairs
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame
AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib
@@ -115,9 +115,6 @@ function AceEvent:OnEmbedDisable(target)
end end
-- Script to fire blizzard events into the event listeners -- Script to fire blizzard events into the event listeners
-- Ace3v: in vanilla the arguments are set to global:
-- event, arg1, arg2, arg3 ...
-- the user have always access to them, so we save the table cost here
local events = AceEvent.events local events = AceEvent.events
AceEvent.frame:SetScript("OnEvent", function() AceEvent.frame:SetScript("OnEvent", function()
events:Fire(event) events:Fire(event)
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceEvent-3.0.lua"/> <Script file="AceEvent-3.0.lua"/>
</Ui> </Ui>
+16 -44
View File
@@ -15,9 +15,6 @@ local AceHook, oldminor = LibStub:NewLibrary(ACEHOOK_MAJOR, ACEHOOK_MINOR)
if not AceHook then return end -- No upgrade needed if not AceHook then return end -- No upgrade needed
local AceCore = LibStub("AceCore-3.0")
local new, del = AceCore.new, AceCore.del
AceHook.embeded = AceHook.embeded or {} AceHook.embeded = AceHook.embeded or {}
AceHook.registry = AceHook.registry or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) AceHook.registry = AceHook.registry or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end })
AceHook.handlers = AceHook.handlers or {} AceHook.handlers = AceHook.handlers or {}
@@ -34,14 +31,17 @@ local scripts = AceHook.scripts
local onceSecure = AceHook.onceSecure local onceSecure = AceHook.onceSecure
-- Lua APIs -- Lua APIs
local pairs, next, type = pairs, next, type local pairs, next, type, unpack = pairs, next, type, unpack
local format = string.format local format = string.format
local assert, error = assert, error local assert, error = assert, error
-- WoW APIs -- WoW APIs
local hooksecurefunc, issecurevariable = AceCore.hooksecurefunc, AceCore.issecurevariable local HookScript = HookScript
local issecurevariable, hooksecurefunc = issecurevariable, hooksecurefunc
local _G = _G
local _G = AceCore._G -- functions for later definition
local donothing, createHook, hook
local protectedScripts = { local protectedScripts = {
OnClick = true, OnClick = true,
@@ -80,14 +80,9 @@ function AceHook:OnEmbedDisable( target )
target:UnhookAll() target:UnhookAll()
end end
-- failsafe means even the hooking method fails, the original method will function createHook(self, handler, orig, secure, failsafe)
-- always be called
local function createHook(self, handler, orig, secure, failsafe)
local uid local uid
local method = type(handler) == "string" local method = type(handler) == "string"
-- Ace3v: when this function called in the "hook" function, we have
-- failsafe = not (raw or secure), so the first check condition
-- is same as "if failsafe" or "if not raw and not secure"
if failsafe and not secure then if failsafe and not secure then
-- failsafe hook creation -- failsafe hook creation
uid = function(...) uid = function(...)
@@ -119,18 +114,9 @@ local function createHook(self, handler, orig, secure, failsafe)
return uid return uid
end end
local function donothing() end function donothing() end
-- @param self function hook(self, obj, method, handler, script, secure, raw, forceSecure, usage)
-- @param obj nil or a frame object, use with script = true
-- @param method string, the name of a global function or the name of an object method
-- @param handler function, or string when it's a method of 'self', if nil then will use the same value as method
-- @param script boolean, must be true, if the hooked object is a frame
-- @param secure boolean, if hooking a secure script, if true the original script will be called first, else later
-- @param raw boolean, if raw hooking (replacing the original method)
-- @param forceSecure boolean, if forcing to hook a secure method
-- @param usage
local function hook(self, obj, method, handler, script, secure, raw, forceSecure, usage)
if not handler then handler = method end if not handler then handler = method end
-- These asserts make sure AceHooks's devs play by the rules. -- These asserts make sure AceHooks's devs play by the rules.
@@ -215,7 +201,6 @@ local function hook(self, obj, method, handler, script, secure, raw, forceSecure
local orig local orig
if script then if script then
-- Sometimes there is not a original function for a script.
orig = obj:GetScript(method) or donothing orig = obj:GetScript(method) or donothing
elseif obj then elseif obj then
orig = obj[method] orig = obj[method]
@@ -230,11 +215,11 @@ local function hook(self, obj, method, handler, script, secure, raw, forceSecure
uid = createHook(self, handler, orig, secure, not (raw or secure)) uid = createHook(self, handler, orig, secure, not (raw or secure))
if obj then if obj then
registry[self][obj] = registry[self][obj] or new() self.hooks[obj] = self.hooks[obj] or {}
registry[self][obj] = registry[self][obj] or {}
registry[self][obj][method] = uid registry[self][obj][method] = uid
if not secure then if not secure then
self.hooks[obj] = self.hooks[obj] or new()
self.hooks[obj][method] = orig self.hooks[obj][method] = orig
end end
@@ -242,12 +227,7 @@ local function hook(self, obj, method, handler, script, secure, raw, forceSecure
if not secure then if not secure then
obj:SetScript(method, uid) obj:SetScript(method, uid)
else else
obj:SetScript(method, function(...) HookScript(obj, method, uid)
local tmp = {orig(unpack(arg))}
uid(unpack(arg))
return unpack(tmp)
end)
--obj:HookScript(method, uid) -- Ace3v: vanilla frame has no HookScript
end end
else else
if not secure then if not secure then
@@ -464,12 +444,8 @@ function AceHook:Unhook(obj, method)
actives[uid], handlers[uid] = nil, nil actives[uid], handlers[uid] = nil, nil
if obj then if obj then
local tmp = registry[self][obj] registry[self][obj][method] = nil
tmp[method] = nil registry[self][obj] = next(registry[self][obj]) and registry[self][obj] or nil
if not next(tmp) then
del(tmp)
registry[self][obj] = nil
end
-- if the hook reference doesnt exist, then its a secure hook, just bail out and dont do any unhooking -- if the hook reference doesnt exist, then its a secure hook, just bail out and dont do any unhooking
if not self.hooks[obj] or not self.hooks[obj][method] then return true end if not self.hooks[obj] or not self.hooks[obj][method] then return true end
@@ -481,12 +457,8 @@ function AceHook:Unhook(obj, method)
obj[method] = self.hooks[obj][method] obj[method] = self.hooks[obj][method]
end end
tmp = self.hooks[obj] self.hooks[obj][method] = nil
tmp[method] = nil self.hooks[obj] = next(self.hooks[obj]) and self.hooks[obj] or nil
if not next(tmp) then
del(tmp)
self.hooks[obj] = nil
end
else else
registry[self][method] = nil registry[self][method] = nil
+2 -1
View File
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceHook-3.0.lua"/> <Script file="AceHook-3.0.lua"/>
</Ui> </Ui>
@@ -97,7 +97,7 @@ function AceLocale:NewLocale(application, locale, isDefault, silent)
local app = AceLocale.apps[application] local app = AceLocale.apps[application]
if silent and app and getmetatable(app) ~= readmetasilent then if silent and app and getmetatable(app) ~= readmetasilent and not isDefault then
geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered") geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
end end
@@ -112,7 +112,7 @@ function AceLocale:NewLocale(application, locale, isDefault, silent)
end end
if locale ~= gameLocale and not isDefault then if locale ~= gameLocale and not isDefault then
return nil -- nop, we don't need these translations return -- nop, we don't need these translations
end end
registering = app -- remember globally for writeproxy and writedefaultproxy registering = app -- remember globally for writeproxy and writedefaultproxy
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceLocale-3.0.lua"/> <Script file="AceLocale-3.0.lua"/>
</Ui> </Ui>
@@ -117,7 +117,8 @@ function AceSerializer:Serialize(...)
local nres = 1 local nres = 1
for i=1,arg.n do for i=1,arg.n do
nres = SerializeValue(arg[i], serializeTbl, nres) local v = arg[i]
nres = SerializeValue(v, serializeTbl, nres)
end end
serializeTbl[nres+1] = "^^" -- "^^" = End of serialized data serializeTbl[nres+1] = "^^" -- "^^" = End of serialized data
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceSerializer-3.0.lua"/> <Script file="AceSerializer-3.0.lua"/>
</Ui> </Ui>
+326 -229
View File
@@ -1,12 +1,12 @@
--- **AceTimer-3.0** provides a central facility for registering timers. --- **AceTimer-3.0** provides a central facility for registering timers.
-- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient -- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient
-- data structure that allows easy dispatching and fast rescheduling. Timers can be registered -- data structure that allows easy dispatching and fast rescheduling. Timers can be registered, rescheduled
-- or canceled at any time, even from within a running timer, without conflict or large overhead.\\ -- or canceled at any time, even from within a running timer, without conflict or large overhead.\\
-- AceTimer is currently limited to firing timers at a frequency of 0.01s as this is what the WoW timer API -- AceTimer is currently limited to firing timers at a frequency of 0.1s. This constant may change
-- restricts us to. -- in the future, but for now it seemed like a good compromise in efficiency and accuracy.
-- --
-- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you -- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you
-- need to cancel the timer you just registered. -- need to cancel or reschedule the timer you just registered.
-- --
-- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer:Embed(MyAddon) or by -- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object -- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
@@ -15,33 +15,55 @@
-- make into AceTimer. -- make into AceTimer.
-- @class file -- @class file
-- @name AceTimer-3.0 -- @name AceTimer-3.0
-- @release $Id: AceTimer-3.0.lua 1119 2014-10-14 17:23:29Z nevcairiel $ -- @release $Id: AceTimer-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
local MAJOR, MINOR = "AceTimer-3.0", 17 -- Bump minor on changes --[[
Basic assumptions:
* In a typical system, we do more re-scheduling per second than there are timer pulses per second
* Regardless of timer implementation, we cannot guarantee timely delivery due to FPS restriction (may be as low as 10)
This implementation:
CON: The smallest timer interval is constrained by HZ (currently 1/10s).
PRO: It will still correctly fire any timer slower than HZ over a length of time, e.g. 0.11s interval -> 90 times over 10 seconds
PRO: In lag bursts, the system simly skips missed timer intervals to decrease load
CON: Algorithms depending on a timer firing "N times per minute" will fail
PRO: (Re-)scheduling is O(1) with a VERY small constant. It's a simple linked list insertion in a hash bucket.
CAUTION: The BUCKETS constant constrains how many timers can be efficiently handled. With too many hash collisions, performance will decrease.
Major assumptions upheld:
- ALLOWS scheduling multiple timers with the same funcref/method
- ALLOWS scheduling more timers during OnUpdate processing
- ALLOWS unscheduling ANY timer (including the current running one) at any time, including during OnUpdate processing
]]
local MAJOR, MINOR = "AceTimer-3.0", 6
local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR) local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceTimer then return end -- No upgrade needed if not AceTimer then return end -- No upgrade needed
local AceCore = LibStub("AceCore-3.0") AceTimer.hash = AceTimer.hash or {} -- Array of [0..BUCKET-1] = linked list of timers (using .next member)
local safecall = AceCore.safecall -- Linked list gets around ACE-88 and ACE-90.
AceTimer.selfs = AceTimer.selfs or {} -- Array of [self]={[handle]=timerobj, [handle2]=timerobj2, ...}
AceTimer.counter = AceTimer.counter or {}
AceTimer.hash = AceTimer.hash or {} -- Array of [1..BUCKETS] = linked list of timers (using .next member)
AceTimer.activeTimers = AceTimer.activeTimers or {} -- Active timer list
AceTimer.frame = AceTimer.frame or CreateFrame("Frame", "AceTimer30Frame") AceTimer.frame = AceTimer.frame or CreateFrame("Frame", "AceTimer30Frame")
local counter = AceTimer.counter
local activeTimers = AceTimer.activeTimers -- Upvalue our private data
local timerFrame = AceTimer.frame
-- Lua APIs -- Lua APIs
local type, unpack, next, error = type, unpack, next, error local assert, error, loadstring = assert, error, loadstring
local floor, max, min, mod = math.floor, math.max, math.min, math.mod local setmetatable, rawset, rawget = setmetatable, rawset, rawget
local tostring = tostring local pairs, type, next, tostring, unpack = pairs, type, next, tostring, unpack
local gsub = string.gsub
local floor, max, min, fmod = math.floor, math.max, math.min, math.fmod
local tconcat = table.concat
-- WoW APIs -- WoW APIs
local GetTime = GetTime local GetTime = GetTime
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: DEFAULT_CHAT_FRAME, geterrorhandler
-- Simple ONE-SHOT timer cache. Much more efficient than a full compost for our purposes.
local timerCache = nil
--[[ --[[
Timers will not be fired more often than HZ-1 times per second. Timers will not be fired more often than HZ-1 times per second.
Keep at intended speed PLUS ONE or we get bitten by floating point rounding errors (n.5 + 0.1 can be n.599999) Keep at intended speed PLUS ONE or we get bitten by floating point rounding errors (n.5 + 0.1 can be n.599999)
@@ -49,7 +71,6 @@ local GetTime = GetTime
If this number is ever changed, all entries need to be rehashed on lib upgrade. If this number is ever changed, all entries need to be rehashed on lib upgrade.
]] ]]
local HZ = 11 local HZ = 11
local minDelay = 1/(HZ-1)
--[[ --[[
Prime for good distribution Prime for good distribution
@@ -62,122 +83,215 @@ for i=1,BUCKETS do
hash[i] = hash[i] or false -- make it an integer-indexed array; it's faster than hashes hash[i] = hash[i] or false -- make it an integer-indexed array; it's faster than hashes
end end
local new, del --[[
do xpcall safecall implementation
local list = setmetatable({}, {__mode = "k"}) ]]
function new(self, loop, func, delay, argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) local xpcall = xpcall
local name = loop and "ScheduleRepeatingTimer" or "ScheduleTimer"
if self == AceTimer then local function errorhandler(err)
error(MAJOR..": " .. name .. "(callback, delay, argc, args...): use your own 'self'", 3) return geterrorhandler()(err)
end
if not func or not delay then
error(MAJOR..": " .. name .. "(callback, delay, argc, args...): 'callback' and 'delay' must have set values.", 3)
end
if argc and (type(argc) ~= "number" or floor(argc) ~= argc) then
error(MAJOR..": " .. name .. "(callback, delay, argc, args...): 'argc' must be an integer.", 3)
end
if type(func) == "string" then
if type(self) ~= "table" then
error(MAJOR..": " .. name .. "(callback, delay, argc, args...): 'self' - must be a table.", 3)
elseif type(self[func]) ~= "function" then
error(MAJOR..": " .. name .. "(callback, delay, argc, args...): Tried to register '"..func.."' as the callback, but it is not a method.", 3)
end
elseif type(func) ~= "function" then
error(MAJOR..": " .. name .. "(callback, delay, argc, args...): Tried to register '"..tostring(func).."' as the callback, but it is not a function.", 3)
end end
if delay < minDelay then local function CreateDispatcher(argCount)
delay = minDelay local code = [[
local xpcall, eh = xpcall, function(err) return geterrorhandler()(err) end -- our arguments are received as unnamed values in "..." since we don't have a proper function declaration
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = unpack(arg)
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = gsub(code, "ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {
__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end
})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
return Dispatchers[arg.n](func, unpack(arg))
end
local lastint = floor(GetTime() * HZ)
-- --------------------------------------------------------------------
-- OnUpdate handler
--
-- traverse buckets, always chasing "now", and fire timers that have expired
local function OnUpdate()
local now = GetTime()
local nowint = floor(now * HZ)
-- Have we passed into a new hash bucket?
if nowint == lastint then return end
local soon = now + 1 -- +1 is safe as long as 1 < HZ < BUCKETS/2
-- Pass through each bucket at most once
-- Happens on e.g. instance loads, but COULD happen on high local load situations also
for curint = (max(lastint, nowint - BUCKETS) + 1), nowint do -- loop until we catch up with "now", usually only 1 iteration
local curbucket = (fmod(curint, BUCKETS))+1
-- Yank the list of timers out of the bucket and empty it. This allows reinsertion in the currently-processed bucket from callbacks.
local nexttimer = hash[curbucket]
hash[curbucket] = false -- false rather than nil to prevent the array from becoming a hash
while nexttimer do
local timer = nexttimer
nexttimer = timer.next
local when = timer.when
if when < soon then
-- Call the timer func, either as a method on given object, or a straight function ref
local callback = timer.callback
if type(callback) == "string" then
safecall(timer.object[callback], timer.object, timer.arg)
elseif callback then
safecall(callback, timer.arg)
else
-- probably nilled out by CancelTimer
timer.delay = nil -- don't reschedule it
end
local delay = timer.delay -- NOW make a local copy, can't do it earlier in case the timer cancelled itself in the callback
if not delay then
-- single-shot timer (or cancelled)
AceTimer.selfs[timer.object][tostring(timer)] = nil
timerCache = timer
else
-- repeating timer
local newtime = when + delay
if newtime < now then -- Keep lag from making us firing a timer unnecessarily. (Note that this still won't catch too-short-delay timers though.)
newtime = now + delay
end
timer.when = newtime
-- add next timer execution to the correct bucket
local bucket = (fmod(floor(newtime * HZ), BUCKETS)) + 1
timer.next = hash[bucket]
hash[bucket] = timer
end
else -- if when>=soon
-- reinsert (yeah, somewhat expensive, but shouldn't be happening too often either due to hash distribution)
timer.next = hash[curbucket]
hash[curbucket] = timer
end -- if when<soon ... else
end -- while nexttimer do
end -- for curint=lastint,nowint
lastint = nowint
end
-- ---------------------------------------------------------------------
-- Reg( callback, delay, arg, repeating )
--
-- callback( function or string ) - direct function ref or method name in our object for the callback
-- delay(int) - delay for the timer
-- arg(variant) - any argument to be passed to the callback function
-- repeating(boolean) - repeating timer, or oneshot
--
-- returns the handle of the timer for later processing (canceling etc)
local function Reg(self, callback, delay, argument, repeating)
if type(callback) ~= "string" and type(callback) ~= "function" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(callback, delay, arg): 'callback' - function or method name expected.", 3)
end
if type(callback) == "string" then
if type(self)~="table" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'self' - must be a table.", 3)
end
if type(self[callback]) ~= "function" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'methodName' - method not found on target object.", 3)
end
end
if delay < (1 / (HZ - 1)) then
delay = 1 / (HZ - 1)
end end
-- Create and stuff timer in the correct hash bucket -- Create and stuff timer in the correct hash bucket
local now = GetTime() local now = GetTime()
local timer = next(list) or {} local timer = timerCache or {} -- Get new timer object (from cache if available)
list[timer] = nil timerCache = nil
timer.object = self timer.object = self
timer.func = func timer.callback = callback
timer.delay = delay timer.delay = (repeating and delay)
timer.status = loop and "loop" or "once" timer.arg = argument
timer.ends = now + delay timer.when = now + delay
timer.argsCount = argc or 0
timer[1] = a1
timer[2] = a2
timer[3] = a3
timer[4] = a4
timer[5] = a5
timer[6] = a6
timer[7] = a7
timer[8] = a8
timer[9] = a9
timer[10] = a10
local bucket = floor(mod((now+delay)*HZ,BUCKETS)) + 1 local bucket = (fmod(floor((now+delay)*HZ), BUCKETS)) + 1
timer.next = hash[bucket] timer.next = hash[bucket]
hash[bucket] = timer hash[bucket] = timer
local id = tostring(timer) -- user has only access to the id but not the table itself -- Insert timer in our self->handle->timer registry
activeTimers[id] = timer local handle = tostring(timer)
counter[self] = (counter[self] or 0) + 1 local selftimers = AceTimer.selfs[self]
if not selftimers then
selftimers = {}
AceTimer.selfs[self] = selftimers
end
selftimers[handle] = timer
selftimers.__ops = (selftimers.__ops or 0) + 1
timerFrame:Show() return handle
return id
end end
function del(t)
local id = tostring(t)
activeTimers[id] = nil
if not next(activeTimers) then
timerFrame:Hide()
end
local self = t.object
for k in pairs(t) do t[k] = nil end
list[t] = true
if counter[self] then
counter[self] = counter[self] - 1
else
counter[self] = nil
end
end
end -- new, del
--- Schedule a new one-shot timer. --- Schedule a new one-shot timer.
-- The timer will fire once in `delay` seconds, unless canceled before. -- The timer will fire once in `delay` seconds, unless canceled before.
-- @param callback Callback function for the timer pulse (funcref or method name). -- @param callback Callback function for the timer pulse (funcref or method name).
-- @param delay Delay for the timer, in seconds. -- @param delay Delay for the timer, in seconds.
-- @param argc The numbers of arguments to be passed to the callback function -- @param arg An optional argument to be passed to the callback function.
-- @param a1,...,a10 The arguments
-- @usage -- @usage
-- MyAddOn = LibStub("AceAddon-3.0"):NewAddon("MyAddOn", "AceTimer-3.0") -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
-- --
-- function MyAddOn:OnEnable() -- function MyAddon:OnEnable()
-- self:ScheduleTimer("TimerFeedback", 5) -- self:ScheduleTimer("TimerFeedback", 5)
-- end -- end
-- --
-- function MyAddOn:TimerFeedback() -- function MyAddon:TimerFeedback()
-- print("5 seconds passed") -- print("5 seconds passed")
-- end -- end
function AceTimer:ScheduleTimer(func, delay, argc, ...) function AceTimer:ScheduleTimer(callback, delay, argument)
return new(self, nil, func, delay, argc, unpack(arg)) return Reg(self, callback, delay, argument)
end end
--- Schedule a repeating timer. --- Schedule a repeating timer.
-- The timer will fire every `delay` seconds, until canceled. -- The timer will fire every `delay` seconds, until canceled.
-- @param callback Callback function for the timer pulse (funcref or method name). -- @param callback Callback function for the timer pulse (funcref or method name).
-- @param delay Delay for the timer, in seconds. -- @param delay Delay for the timer, in seconds.
-- @param argc The numbers of arguments to be passed to the callback function -- @param arg An optional argument to be passed to the callback function.
-- @param a1,...,a10 The arguments
-- @usage -- @usage
-- MyAddOn = LibStub("AceAddon-3.0"):NewAddon("MyAddOn", "AceTimer-3.0") -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
-- --
-- function MyAddOn:OnEnable() -- function MyAddon:OnEnable()
-- self.timerCount = 0 -- self.timerCount = 0
-- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5) -- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5)
-- end -- end
-- --
-- function MyAddOn:TimerFeedback() -- function MyAddon:TimerFeedback()
-- self.timerCount = self.timerCount + 1 -- self.timerCount = self.timerCount + 1
-- print(format("%d seconds passed", 5 * self.timerCount)) -- print(format("%d seconds passed", 5 * self.timerCount))
-- -- run 30 seconds in total -- -- run 30 seconds in total
@@ -185,65 +299,131 @@ end
-- self:CancelTimer(self.testTimer) -- self:CancelTimer(self.testTimer)
-- end -- end
-- end -- end
function AceTimer:ScheduleRepeatingTimer(func, delay, argc, ...) function AceTimer:ScheduleRepeatingTimer(callback, delay, argument)
return new(self, true, func, delay, argc, unpack(arg)) return Reg(self, callback, delay, argument, true)
end end
--- Cancels a timer with the given id, registered by the same addon object as used for `:ScheduleTimer` --- Cancels a timer with the given handle, registered by the same addon object as used for `:ScheduleTimer`
-- Both one-shot and repeating timers can be canceled with this function, as long as the `id` is valid -- Both one-shot and repeating timers can be canceled with this function, as long as the `handle` is valid
-- and the timer has not fired yet or was canceled before. -- and the timer has not fired yet or was canceled before.
-- @param id The id of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer` -- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
function AceTimer:CancelTimer(id) -- @param silent If true, no error is raised if the timer handle is invalid (expired or already canceled)
local timer = activeTimers[id] -- @return True if the timer was successfully cancelled.
function AceTimer:CancelTimer(handle, silent)
if not timer then if not handle then return end -- nil handle -> bail out without erroring
return false if type(handle) ~= "string" then
error(MAJOR..": CancelTimer(handle): 'handle' - expected a string", 2) -- for now, anyway
end
local selftimers = AceTimer.selfs[self]
local timer = selftimers and selftimers[handle]
if silent then
if timer then
timer.callback = nil -- don't run it again
timer.delay = nil -- if this is the currently-executing one: don't even reschedule
-- The timer object is removed in the OnUpdate loop
end
return not not timer -- might return "true" even if we double-cancel. we'll live.
else else
-- Ace3v: the timer will always be collected in the next update but not here if not timer then
-- this is necessary for AceBucket to determinate if the bucket has been unregistered geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - no such timer registered")
-- in the callback return false
timer.status = nil end
activeTimers[id] = nil if not timer.callback then
geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - timer already cancelled or expired")
return false
end
timer.callback = nil -- don't run it again
timer.delay = nil -- if this is the currently-executing one: don't even reschedule
return true return true
end end
end end
--- Cancels all timers registered to the current addon object ('self') --- Cancels all timers registered to the current addon object ('self')
function AceTimer:CancelAllTimers() function AceTimer:CancelAllTimers()
if type(self) ~= "table" then if not(type(self) == "string" or type(self) == "table") then
error(MAJOR..": CancelAllTimers(): 'self' - must be a table",2) error(MAJOR..": CancelAllTimers(): 'self' - must be a string or a table",2)
end end
if self == AceTimer then if self == AceTimer then
error(MAJOR..": CancelAllTimers(): supply a meaningful 'self'", 2) error(MAJOR..": CancelAllTimers(): supply a meaningful 'self'", 2)
end end
for k,v in pairs(activeTimers) do local selftimers = AceTimer.selfs[self]
if v.object == self then if selftimers then
AceTimer.CancelTimer(self, k) for handle,v in pairs(selftimers) do
if type(v) == "table" then -- avoid __ops, etc
AceTimer.CancelTimer(self, handle, true)
end
end end
end end
end end
--- Returns the time left for a timer with the given id, registered by the current addon object ('self'). --- Returns the time left for a timer with the given handle, registered by the current addon object ('self').
-- This function will return 0 when the id is invalid. -- This function will raise a warning when the handle is invalid, but not stop execution.
-- @param id The id of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer` -- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
-- @return The time left on the timer. -- @return The time left on the timer, or false if the handle is invalid.
function AceTimer:TimeLeft(id) function AceTimer:TimeLeft(handle)
local timer = activeTimers[id] if not handle then return end
if not timer then if type(handle) ~= "string" then
return 0 error(MAJOR..": TimeLeft(handle): 'handle' - expected a string", 2) -- for now, anyway
else
return timer.ends - GetTime()
end end
local selftimers = AceTimer.selfs[self]
local timer = selftimers and selftimers[handle]
if not timer then
geterrorhandler()(MAJOR..": TimeLeft(handle): '"..tostring(handle).."' - no such timer registered")
return false
end
return timer.when - GetTime()
end end
function AceTimer:TimerStatus(id)
local timer = activeTimers[id] -- ---------------------------------------------------------------------
if not timer then -- PLAYER_REGEN_ENABLED: Run through our .selfs[] array step by step
return nil -- and clean it out - otherwise the table indices can grow indefinitely
else -- if an addon starts and stops a lot of timers. AceBucket does this!
return timer.status --
-- See ACE-94 and tests/AceTimer-3.0-ACE-94.lua
local lastCleaned = nil
local function OnEvent()
if event~="PLAYER_REGEN_ENABLED" then
return
end end
-- Get the next 'self' to process
local selfs = AceTimer.selfs
local self = next(selfs, lastCleaned)
if not self then
self = next(selfs)
end
lastCleaned = self
if not self then -- should only happen if .selfs[] is empty
return
end
-- Time to clean it out?
local list = selfs[self]
if (list.__ops or 0) < 250 then -- 250 slosh indices = ~10KB wasted (worst case!). For one 'self'.
return
end
-- Create a new table and copy all members over
local newlist = {}
local n=0
for k,v in pairs(list) do
newlist[k] = v
if type(v)=="table" and v.callback then -- if the timer is actually live: count it
n=n+1
end
end
newlist.__ops = 0 -- Reset operation count
-- And since we now have a count of the number of live timers, check that it's reasonable. Emit a warning if not.
if n>BUCKETS then
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: The addon/module '"..tostring(self).."' has "..n.." live timers. Surely that's not intended?")
end
selfs[self] = newlist
end end
-- --------------------------------------------------------------------- -- ---------------------------------------------------------------------
@@ -273,107 +453,24 @@ function AceTimer:OnEmbedDisable(target)
target:CancelAllTimers() target:CancelAllTimers()
end end
for addon in pairs(AceTimer.embeds) do for addon in pairs(AceTimer.embeds) do
AceTimer:Embed(addon) AceTimer:Embed(addon)
end end
-- -------------------------------------------------------------------- -- ---------------------------------------------------------------------
-- OnUpdate handler -- Debug tools (expose copies of internals to test suites)
-- AceTimer.debug = AceTimer.debug or {}
-- traverse buckets, always chasing "now", and fire timers that have expired AceTimer.debug.HZ = HZ
local lastint = floor(GetTime() * HZ) AceTimer.debug.BUCKETS = BUCKETS
local function OnUpdate()
local now = GetTime()
local nowint = floor(now * HZ)
-- Have we passed into a new hash bucket? -- ---------------------------------------------------------------------
if nowint == lastint then return end -- Finishing touchups
local soon = now + 1 -- +1 is safe as long as 1 < HZ < BUCKETS/2 AceTimer.frame:SetScript("OnUpdate", OnUpdate)
AceTimer.frame:SetScript("OnEvent", OnEvent)
AceTimer.frame:RegisterEvent("PLAYER_REGEN_ENABLED")
-- Pass through each bucket at most once -- In theory, we could hide&show the frame based on there being timers or not.
-- Happens on e.g. instance loads, but COULD happen on high local load situations also -- However, this job is fairly expensive, and the chance that there will
for curint = (max(lastint, nowint-BUCKETS) + 1), nowint do -- loop until we catch up with "now", usually only 1 iteratio -- actually be zero timers running is diminuitive to say the least.
local curbucket = mod(curint,BUCKETS) + 1 -- Ace3v: both int so no floor here
-- Yank the list of timers out of the bucket and empty it. This allows reinsertion in the currently-processed bucket from callbacks.
local nexttimer = hash[curbucket]
hash[curbucket] = false -- false rather than nil to prevent the array from becoming a hash
while nexttimer do
local timer = nexttimer
nexttimer = timer.next
local status = timer.status
if not status then
del(timer)
else
local ends = timer.ends
if (status == "loop" or status == "once") and ends < soon then
local object = timer.object
local callback = timer.func
if type(callback) == "string" then
callback = (type(object) == "table") and object[callback]
if type(callback) == "function" then
safecall(callback, timer.argsCount+1, object,
timer[1], timer[2], timer[3], timer[4], timer[5],
timer[6], timer[7], timer[8], timer[9], timer[10])
else
status = "once"
end
elseif type(callback) == "function" then
safecall(callback, timer.argsCount,
timer[1], timer[2], timer[3], timer[4], timer[5],
timer[6], timer[7], timer[8], timer[9], timer[10])
else
-- probably nilled out by CancelTimer
status = "once" -- don't reschedule it
end
if status == "once" then
del(timer)
else
local delay = timer.delay
local newends = ends + delay
if newends < now then -- Keep lag from making us firing a timer unnecessarily. (Note that this still won't catch too-short-delay timers though.)
newends = now + delay
end
timer.ends = newends
-- add next timer execution to the correct bucket
local bucket = floor(mod(newends*HZ,BUCKETS)) + 1
timer.next = hash[bucket]
hash[bucket] = timer
end
else
-- reinsert (yeah, somewhat expensive, but shouldn't be happening too often either due to hash distribution)
timer.next = hash[curbucket]
hash[curbucket] = timer
end
end
end
end
lastint = nowint
end
local lastchecked = nil
local function OnEvent()
if event ~= "PLAYER_REGEN_ENABLED" then return end
local addon = next(counter, lastchecked)
if not addon then
addon = next(counter)
end
lastchecked = addon
if not addon then -- should only happen if counter is empty
return
end
local n = counter[addon]
if n > BUCKETS then
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: The addon/module '"..tostring(addon).."' has "..tostring(n).." live timers. Surely that's not intended?")
end
end
timerFrame:SetScript("OnUpdate", OnUpdate)
timerFrame:SetScript("OnEvent", OnEvent)
timerFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
timerFrame:Hide()
@@ -1,3 +1,4 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="AceTimer-3.0.lua"/> <Script file="AceTimer-3.0.lua"/>
</Ui> </Ui>
@@ -1,4 +1,4 @@
--[[ $Id: CallbackHandler-1.0.lua 18 2014-10-16 02:52:20Z mikk $ ]] --[[ $Id: CallbackHandler-1.0.lua 1131 2015-06-04 07:29:24Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 6 local MAJOR, MINOR = "CallbackHandler-1.0", 6
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
@@ -7,7 +7,7 @@ if not CallbackHandler then return end -- No upgrade needed
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-- Lua APIs -- Lua APIs
local tconcat = table.concat local tconcat, getn = table.concat, table.getn
local assert, error, loadstring = assert, error, loadstring local assert, error, loadstring = assert, error, loadstring
local setmetatable, rawset, rawget = setmetatable, rawset, rawget local setmetatable, rawset, rawget = setmetatable, rawset, rawget
local next, pairs, type, tostring = next, pairs, type, tostring local next, pairs, type, tostring = next, pairs, type, tostring
@@ -24,6 +24,8 @@ end
local function CreateDispatcher(argCount) local function CreateDispatcher(argCount)
local code = [[ local code = [[
local next, xpcall, eh = next, xpcall, function(err) return geterrorhandler()(err) end
local method, ARGS local method, ARGS
local function call() method(ARGS) end local function call() method(ARGS) end
@@ -34,7 +36,7 @@ local function CreateDispatcher(argCount)
local OLD_ARGS = ARGS local OLD_ARGS = ARGS
ARGS = unpack(arg) ARGS = unpack(arg)
repeat repeat
xpcall(call, function(err) return geterrorhandler()(err) end) xpcall(call, eh)
index, method = next(handlers, index) index, method = next(handlers, index)
until not method until not method
ARGS = OLD_ARGS ARGS = OLD_ARGS
@@ -137,7 +139,8 @@ function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAll
end end
if getn(arg)>=1 then -- this is not the same as testing for arg==nil! if getn(arg)>=1 then -- this is not the same as testing for arg==nil!
regfunc = function(...) self[method](self,arg1,unpack(arg)) end local a1=arg[1]
regfunc = function(...) self[method](self,a1,unpack(arg)) end
else else
regfunc = function(...) self[method](self,unpack(arg)) end regfunc = function(...) self[method](self,unpack(arg)) end
end end
@@ -148,7 +151,8 @@ function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAll
end end
if getn(arg)>=1 then -- this is not the same as testing for arg==nil! if getn(arg)>=1 then -- this is not the same as testing for arg==nil!
regfunc = function(...) method(arg1,unpack(arg)) end local a1=arg[1]
regfunc = function(...) method(arg,unpack(arg)) end
else else
regfunc = method regfunc = method
end end
@@ -197,7 +201,7 @@ function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAll
if getn(arg)<1 then if getn(arg)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end end
if getn(arg)==1 and arg1==target then if getn(arg)==1 and arg[1]==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end end
+3 -3
View File
@@ -2,7 +2,7 @@
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke -- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
local _G = _G local _G = _G
local strfind, strfmt = string.find, string.format local find, format = string.find, string.format
local LibStub = _G[LIBSTUB_MAJOR] local LibStub = _G[LIBSTUB_MAJOR]
if not LibStub or LibStub.minor < LIBSTUB_MINOR then if not LibStub or LibStub.minor < LIBSTUB_MINOR then
@@ -12,7 +12,7 @@ if not LibStub or LibStub.minor < LIBSTUB_MINOR then
function LibStub:NewLibrary(major, minor) function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
local _,_,num = strfind(minor, "(%d+)") local _, _, num = find(minor, "(%d+)")
minor = assert(tonumber(num), "Minor version must either be a number or contain a number.") minor = assert(tonumber(num), "Minor version must either be a number or contain a number.")
local oldminor = self.minors[major] local oldminor = self.minors[major]
@@ -23,7 +23,7 @@ if not LibStub or LibStub.minor < LIBSTUB_MINOR then
function LibStub:GetLibrary(major, silent) function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then if not self.libs[major] and not silent then
error(strfmt("Cannot find a library instance of %q.", tostring(major)), 2) error(format("Cannot find a library instance of %q.", tostring(major)), 2)
end end
return self.libs[major], self.minors[major] return self.libs[major], self.minors[major]
end end
-1
View File
@@ -1,7 +1,6 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"> <Ui xmlns="http://www.blizzard.com/wow/ui/">
<Include file="LibStub\LibStub.xml"/> <Include file="LibStub\LibStub.xml"/>
<Include file="CallbackHandler-1.0\CallbackHandler-1.0.xml"/> <Include file="CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="AceCore-3.0\AceCore-3.0.xml"/>
<Include file="AceAddon-3.0\AceAddon-3.0.xml"/> <Include file="AceAddon-3.0\AceAddon-3.0.xml"/>
<Include file="AceEvent-3.0\AceEvent-3.0.xml"/> <Include file="AceEvent-3.0\AceEvent-3.0.xml"/>
<Include file="AceConsole-3.0\AceConsole-3.0.xml"/> <Include file="AceConsole-3.0\AceConsole-3.0.xml"/>
+2 -2
View File
@@ -107,7 +107,7 @@ local function ChatFrame_OnMouseScroll()
CH:CancelTimer(this.ScrollTimer, true) CH:CancelTimer(this.ScrollTimer, true)
end end
this.ScrollTimer = CH:ScheduleTimer("ScrollToBottom", CH.db.scrollDownInterval, 1, this) this.ScrollTimer = CH:ScheduleTimer("ScrollToBottom", CH.db.scrollDownInterval, this)
end end
end end
else else
@@ -133,7 +133,7 @@ local function ChatFrame_OnMouseScroll()
CH:CancelTimer(this.ScrollTimer, true) CH:CancelTimer(this.ScrollTimer, true)
end end
this.ScrollTimer = CH:ScheduleTimer("ScrollToBottom", CH.db.scrollDownInterval, 1, this) this.ScrollTimer = CH:ScheduleTimer("ScrollToBottom", CH.db.scrollDownInterval, this)
end end
end end
end end
+1 -1
View File
@@ -467,7 +467,7 @@ function mod:UpdateElement_All(frame, noTargetFrame)
self:UpdateElement_Level(frame) self:UpdateElement_Level(frame)
if not noTargetFrame then if not noTargetFrame then
mod:ScheduleTimer("ForEachPlate", 0.25, 1, "SetTargetFrame") mod:ScheduleTimer("ForEachPlate", 0.25, "SetTargetFrame")
end end
end end
+4 -4
View File
@@ -311,7 +311,7 @@ function S:SkinAce3()
if TYPE == "ScrollFrame" then if TYPE == "ScrollFrame" then
local frame = widget.scrollbar local frame = widget.scrollbar
SkinScrollBar(frame) SkinScrollBar(frame)
elseif TYPE == "InlineGroup" or TYPE == "TreeGroup" or TYPE == "TabGroup-ElvUI" or TYPE == "Frame" or TYPE == "DropdownGroup" or TYPE == "Window" then elseif TYPE == "InlineGroup" or TYPE == "TreeGroup" or TYPE == "TabGroup" or TYPE == "Frame" or TYPE == "DropdownGroup" or TYPE == "Window" then
local frame = widget.content:GetParent() local frame = widget.content:GetParent()
if TYPE == "Frame" then if TYPE == "Frame" then
E:StripTextures(frame) E:StripTextures(frame)
@@ -378,16 +378,16 @@ function S:SkinAce3()
end end
end end
if TYPE == "TabGroup-ElvUI" then if TYPE == "TabGroup" then
local oldCreateTab = widget.CreateTab local oldCreateTab = widget.CreateTab
widget.CreateTab = function(self, id) widget.CreateTab = function(self, id)
local tab = oldCreateTab(self, id) local tab = oldCreateTab(self, id)
E:StripTextures(tab) E:StripTextures(tab)
tab.backdrop = CreateFrame("Frame", nil, tab) --[[tab.backdrop = CreateFrame("Frame", nil, tab)
E:SetTemplate(tab.backdrop, "Transparent") E:SetTemplate(tab.backdrop, "Transparent")
tab.backdrop:SetFrameLevel(tab:GetFrameLevel() - 1) tab.backdrop:SetFrameLevel(tab:GetFrameLevel() - 1)
E:Point(tab.backdrop, "TOPLEFT", 10, -3) E:Point(tab.backdrop, "TOPLEFT", 10, -3)
E:Point(tab.backdrop, "BOTTOMRIGHT", -10, 0) E:Point(tab.backdrop, "BOTTOMRIGHT", -10, 0)]]
return tab return tab
end end
end end
@@ -12,15 +12,14 @@ Very light wrapper library that combines all the AceConfig subcomponents into on
]] ]]
local MAJOR, MINOR = "AceConfig-3.0", 2 local cfgreg = LibStub("AceConfigRegistry-3.0")
local cfgcmd = LibStub("AceConfigCmd-3.0")
local MAJOR, MINOR = "AceConfig-3.0", 3
local AceConfig = LibStub:NewLibrary(MAJOR, MINOR) local AceConfig = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfig then return end if not AceConfig then return end
AceConfig.embeds = AceConfig.embeds or {}
local cfgreg = LibStub("AceConfigRegistry-3.0")
local cfgcmd = LibStub("AceConfigCmd-3.0")
--TODO: local cfgdlg = LibStub("AceConfigDialog-3.0", true) --TODO: local cfgdlg = LibStub("AceConfigDialog-3.0", true)
--TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0", true) --TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0", true)
@@ -44,27 +43,16 @@ local pcall, error, type, pairs = pcall, error, type, pairs
-- local AceConfig = LibStub("AceConfig-3.0") -- local AceConfig = LibStub("AceConfig-3.0")
-- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"}) -- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"})
function AceConfig:RegisterOptionsTable(appName, options, slashcmd) function AceConfig:RegisterOptionsTable(appName, options, slashcmd)
if self == AceConfig then
error([[Usage: RegisterOptionsTable(appName, options[, slashcmd]): 'self' - use your own 'self']], 2)
end
local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options) local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
if not ok then error(msg, 2) end if not ok then error(msg, 2) end
if slashcmd then if slashcmd then
if type(slashcmd) == "table" then if type(slashcmd) == "table" then
for _,cmd in pairs(slashcmd) do for _,cmd in pairs(slashcmd) do
cfgcmd.CreateChatCommand(self, cmd, appName) cfgcmd:CreateChatCommand(cmd, appName)
end end
else else
cfgcmd.CreateChatCommand(self, slashcmd, appName) cfgcmd:CreateChatCommand(slashcmd, appName)
end end
end end
end end
function AceConfig:Embed(target)
target["RegisterOptionsTable"] = self["RegisterOptionsTable"]
end
for addon in pairs(AceConfig.embeds) do
AceConfig:Embed(addon)
end
@@ -3,6 +3,6 @@
<Include file="AceConfigRegistry-3.0\AceConfigRegistry-3.0.xml"/> <Include file="AceConfigRegistry-3.0\AceConfigRegistry-3.0.xml"/>
<Include file="AceConfigCmd-3.0\AceConfigCmd-3.0.xml"/> <Include file="AceConfigCmd-3.0\AceConfigCmd-3.0.xml"/>
<Include file="AceConfigDialog-3.0\AceConfigDialog-3.0.xml"/> <Include file="AceConfigDialog-3.0\AceConfigDialog-3.0.xml"/>
<Include file="AceConfigDropdown-3.0\AceConfigDropdown-3.0.xml"/> <!--<Include file="AceConfigDropdown-3.0\AceConfigDropdown-3.0.xml"/>-->
<Script file="AceConfig-3.0.lua"/> <Script file="AceConfig-3.0.lua"/>
</Ui> </Ui>
@@ -14,37 +14,30 @@ REQUIRES: AceConsole-3.0 for command registration (loaded on demand)
-- TODO: plugin args -- TODO: plugin args
local cfgreg = LibStub("AceConfigRegistry-3.0")
local MAJOR, MINOR = "AceConfigCmd-3.0", 13 local MAJOR, MINOR = "AceConfigCmd-3.0", 14
local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR) local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfigCmd then return end if not AceConfigCmd then return end
local AceCore = LibStub("AceCore-3.0")
local Dispatchers = AceCore.Dispatchers
local strtrim = AceCore.strtrim
--local strsplit = AceCore.strsplit
local new, del = AceCore.new, AceCore.del
local wipe = AceCore.wipe
AceConfigCmd.commands = AceConfigCmd.commands or {} AceConfigCmd.commands = AceConfigCmd.commands or {}
AceConfigCmd.embeds = AceConfigCmd.embeds or {}
local commands = AceConfigCmd.commands local commands = AceConfigCmd.commands
local cfgreg = LibStub("AceConfigRegistry-3.0")
local AceConsole -- LoD local AceConsole -- LoD
local AceConsoleName = "AceConsole-3.0" local AceConsoleName = "AceConsole-3.0"
-- Lua APIs -- Lua APIs
local strbyte, strsub = string.byte, string.sub local strsub, strsplit, strlower, strmatch, strtrim = string.sub, string.split, string.lower, string.match, string.trim
local strlen, strupper, strlower = string.len, string.upper, string.lower local strgsub, strupper, strfind, strlen, strbyte, strgmatch = string.gsub, string.upper, string.find, string.len, string.byte, string.gmatch
local strfind, strgfind, strgsub = string.find, string.gfind, string.gsub local format, tonumber, tostring = string.format, tonumber, tostring
local tsort, tinsert, getn = table.sort, table.insert, table.getn
local format = string.format local fmod = math.fmod
local tsort, tinsert, tgetn, tremove = table.sort, table.insert, table.getn, table.remove local select, pairs, next, type = select, pairs, next, type
local error, assert = error, assert
-- WoW APIs -- WoW APIs
local _G = AceCore._G local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script -- List them here for Mikk's FindGlobals script
@@ -69,7 +62,17 @@ local handlermsg = "expected a table"
local functypes = {["function"]=true, ["string"]=true} local functypes = {["function"]=true, ["string"]=true}
local funcmsg = "expected function or member name" local funcmsg = "expected function or member name"
local pickfirstset = AceCore.pickfirstset
-- pickfirstset() - picks the first non-nil value and returns it
local function pickfirstset(...)
for i=1,arg.n do
if arg[i]~=nil then
return arg[i]
end
end
end
-- err() - produce real error() regarding malformed options tables etc -- err() - produce real error() regarding malformed options tables etc
@@ -89,26 +92,23 @@ end
-- callmethod() - call a given named method (e.g. "get", "set") with given arguments -- callmethod() - call a given named method (e.g. "get", "set") with given arguments
local function callmethod(info, inputpos, tab, methodtype, ...)
local function callmethod(info, inputpos, tab, methodtype, argc, a1, a2, a3, a4)
local method = info[methodtype] local method = info[methodtype]
if not method then if not method then
err(info, inputpos, "'"..methodtype.."': not set") err(info, inputpos, "'"..methodtype.."': not set")
end end
argc = argc or 0
info.arg = tab.arg info.arg = tab.arg
info.option = tab info.option = tab
info.type = tab.type info.type = tab.type
if type(method)=="function" then if type(method)=="function" then
return Dispatchers[argc+1](method, info, a1, a2, a3, a4) return method(info, unpack(arg))
elseif type(method)=="string" then elseif type(method)=="string" then
if type(info.handler[method])~="function" then if type(info.handler[method])~="function" then
err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler)) err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler))
end end
return Dispatchers[argc+2](info.handler[method], info.handler, info, a1, a2, a3, a4) return info.handler[method](info.handler, info, unpack(arg))
else else
assert(false) -- type should have already been checked on read assert(false) -- type should have already been checked on read
end end
@@ -116,8 +116,7 @@ end
-- callfunction() - call a given named function (e.g. "name", "desc") with given arguments -- callfunction() - call a given named function (e.g. "name", "desc") with given arguments
-- Ace3v: the variable arguments are currently unused, so we removed it local function callfunction(info, tab, methodtype, ...)
local function callfunction(info, tab, methodtype)
local method = tab[methodtype] local method = tab[methodtype]
info.arg = tab.arg info.arg = tab.arg
@@ -125,18 +124,21 @@ local function callfunction(info, tab, methodtype)
info.type = tab.type info.type = tab.type
if type(method)=="function" then if type(method)=="function" then
if arg.n > 0 then
return method(info, unpack(arg))
else
return method(info) return method(info)
end
else else
assert(false) -- type should have already been checked on read assert(false) -- type should have already been checked on read
end end
end end
-- do_final() - do the final step (set/execute) along with validation and confirmation -- do_final() - do the final step (set/execute) along with validation and confirmation
-- Ace3v: experimental
-- @param argc number of variable arguments local function do_final(info, inputpos, tab, methodtype, ...)
local function do_final(info, inputpos, tab, methodtype, argc, a1, a2, a3, a4) -- currently maximum 4 arguments
if info.validate then if info.validate then
local res = callmethod(info,inputpos,tab,"validate",argc,a1,a2,a3,a4) local res = callmethod(info,inputpos,tab,"validate",unpack(arg))
if type(res)=="string" then if type(res)=="string" then
usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res) usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res)
return return
@@ -144,7 +146,7 @@ local function do_final(info, inputpos, tab, methodtype, argc, a1, a2, a3, a4) -
end end
-- console ignores .confirm -- console ignores .confirm
callmethod(info,inputpos,tab,methodtype,argc,a1,a2,a3,a4) callmethod(info,inputpos,tab,methodtype, unpack(arg))
end end
@@ -167,6 +169,8 @@ end
-- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.* -- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.*
local dummytable={}
local function iterateargs(tab) local function iterateargs(tab)
if not tab.plugins then if not tab.plugins then
return pairs(tab.args) return pairs(tab.args)
@@ -191,21 +195,17 @@ local function iterateargs(tab)
end end
end end
local function getValueFromTab(info, inputpos, tab, key)
local v = tab[key]
if type(v) == "function" or type(v) == "string" then
info[key] = v
v = callmethod(info, inputpos, tab, key)
info[key] = nil
end
return v
end
local function checkhidden(info, inputpos, tab) local function checkhidden(info, inputpos, tab)
if tab.cmdHidden~=nil then if tab.cmdHidden~=nil then
return tab.cmdHidden return tab.cmdHidden
end end
return getValueFromTab(info, inputpos, tab, "hidden") local hidden = tab.hidden
if type(hidden) == "function" or type(hidden) == "string" then
info.hidden = hidden
hidden = callmethod(info, inputpos, tab, 'hidden')
info.hidden = nil
end
return hidden
end end
local function showhelp(info, inputpos, tab, depth, noHead) local function showhelp(info, inputpos, tab, depth, noHead)
@@ -213,8 +213,8 @@ local function showhelp(info, inputpos, tab, depth, noHead)
print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":") print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":")
end end
local sortTbl = new() -- [1..n]=name local sortTbl = {} -- [1..n]=name
local refTbl = new() -- [name]=tableref local refTbl = {} -- [name]=tableref
for k,v in iterateargs(tab) do for k,v in iterateargs(tab) do
if not refTbl[k] then -- a plugin overriding something in .args if not refTbl[k] then -- a plugin overriding something in .args
@@ -247,7 +247,7 @@ local function showhelp(info, inputpos, tab, depth, noHead)
return o1<o2 return o1<o2
end) end)
for i = 1, tgetn(sortTbl) do for i = 1, getn(sortTbl) do
local k = sortTbl[i] local k = sortTbl[i]
local v = refTbl[k] local v = refTbl[k]
if not checkhidden(info, inputpos, v) then if not checkhidden(info, inputpos, v) then
@@ -260,7 +260,7 @@ local function showhelp(info, inputpos, tab, depth, noHead)
if type(desc) == "function" then if type(desc) == "function" then
desc = callfunction(info, v, 'desc') desc = callfunction(info, v, 'desc')
end end
if v.type == "group" and pickfirstset(3, v.cmdInline, v.inline, false) then if v.type == "group" and pickfirstset(v.cmdInline, v.inline, false) then
print(" "..(desc or name)..":") print(" "..(desc or name)..":")
local oldhandler,oldhandler_at = getparam(info, inputpos, v, depth, "handler", handlertypes, handlermsg) local oldhandler,oldhandler_at = getparam(info, inputpos, v, depth, "handler", handlertypes, handlermsg)
showhelp(info, inputpos, v, depth, true) showhelp(info, inputpos, v, depth, true)
@@ -272,10 +272,9 @@ local function showhelp(info, inputpos, tab, depth, noHead)
end end
end end
end end
del(sortTbl) -- Ace3v: release the tables
del(refTbl)
end end
local function keybindingValidateFunc(text) local function keybindingValidateFunc(text)
if text == nil or text == "NONE" then if text == nil or text == "NONE" then
return nil return nil
@@ -376,7 +375,7 @@ local function handle(info, inputpos, tab, depth, retfalse)
if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end
-- is this child an inline group? if so, traverse into it -- is this child an inline group? if so, traverse into it
if v.type=="group" and pickfirstset(3, v.cmdInline, v.inline, false) then if v.type=="group" and pickfirstset(v.cmdInline, v.inline, false) then
tinsert(info,k) tinsert(info,k)
if handle(info, inputpos, v, depth+1, true)==false then if handle(info, inputpos, v, depth+1, true)==false then
tremove(info) tremove(info)
@@ -419,21 +418,16 @@ local function handle(info, inputpos, tab, depth, retfalse)
elseif tab.type=="input" then elseif tab.type=="input" then
------------ input -------------------------------------------- ------------ input --------------------------------------------
if str=="" and tab.nullable == false then
usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
return
end
local res = true local res = true
if tab.pattern then if tab.pattern then
if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end
if not strfind(str, tab.pattern) then if not strmatch(str, tab.pattern) then
usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"]) usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
return return
end end
end end
do_final(info, inputpos, tab, "set", 1, str) do_final(info, inputpos, tab, "set", str)
@@ -472,63 +466,47 @@ local function handle(info, inputpos, tab, depth, retfalse)
return return
end end
do_final(info, inputpos, tab, "set", 1, b) do_final(info, inputpos, tab, "set", b)
elseif tab.type=="range" then elseif tab.type=="range" then
------------ range -------------------------------------------- ------------ range --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
-- TODO: Show current value
return
end
local val = tonumber(str) local val = tonumber(str)
if not val then if not val then
usererr(info, inputpos, "'"..str.."' - "..L["expected number"]) usererr(info, inputpos, "'"..str.."' - "..L["expected number"])
return return
end end
if type(info.step)=="number" then
local step = getValueFromTab(info, inputpos, tab, "step") val = val- fmod(val, info.step)
local min = getValueFromTab(info, inputpos, tab, "min")
if type(step)=="number" then
val = min + math.floor((val-min)/step) * step
end end
if type(info.min)=="number" and val<info.min then
if type(min)=="number" and val<min then usererr(info, inputpos, val.." - "..format(L["must be equal to or higher than %s"], tostring(info.min)) )
usererr(info, inputpos, val.." - "..format(L["must be equal to or higher than %s"], tostring(min)) ) return
end
if type(info.max)=="number" and val>info.max then
usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(info.max)) )
return return
end end
local max = getValueFromTab(info, inputpos, tab, "max") do_final(info, inputpos, tab, "set", val)
if type(max)=="number" and val>max then
usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(max)) )
return
end
do_final(info, inputpos, tab, "set", 1, val)
elseif tab.type=="select" then elseif tab.type=="select" then
------------ select ------------------------------------ ------------ select ------------------------------------
local str = strtrim(strlower(str)) local str = strtrim(strlower(str))
local values = getValueFromTab(info, inputpos, tab, "values") local values = tab.values
if type(values) == "function" or type(values) == "string" then
if str == "" then info.values = values
-- Ace3v: it is possbile to not have a current value values = callmethod(info, inputpos, tab, "values")
-- we do this only for select but not for multiselect info.values = nil
local b = tab.get
if type(b) == "function" or type(b) == "string" then
b = callmethod(info, inputpos, tab, "get")
else
b = nil
end end
if str == "" then
local b = callmethod(info, inputpos, tab, "get")
local fmt = "|cffffff78- [%s]|r %s" local fmt = "|cffffff78- [%s]|r %s"
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r" local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
print(L["Options for |cffffff78"..info[tgetn(info)].."|r:"]) print(L["Options for |cffffff78"..info[getn(info)].."|r:"])
for k, v in pairs(values) do for k, v in pairs(values) do
if b == k then if b == k then
print(format(fmt_sel, k, v)) print(format(fmt_sel, k, v))
@@ -536,7 +514,6 @@ local function handle(info, inputpos, tab, depth, retfalse)
print(format(fmt, k, v)) print(format(fmt, k, v))
end end
end end
if tab.valuesTableDestroyable then del(values) end
return return
end end
@@ -548,39 +525,42 @@ local function handle(info, inputpos, tab, depth, retfalse)
break break
end end
end end
if tab.valuesTableDestroyable then del(values) end
if not ok then if not ok then
usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"]) usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"])
return return
end end
do_final(info, inputpos, tab, "set", 1, str) do_final(info, inputpos, tab, "set", str)
elseif tab.type=="multiselect" then elseif tab.type=="multiselect" then
------------ multiselect ------------------------------------------- ------------ multiselect -------------------------------------------
local str = strtrim(strlower(str)) local str = strtrim(strlower(str))
local values = getValueFromTab(info, inputpos, tab, "values") local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
if str == "" then if str == "" then
local fmt = "|cffffff78- [%s]|r %s" local fmt = "|cffffff78- [%s]|r %s"
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r" local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
print(L["Options for |cffffff78"..info[tgetn(info)].."|r (multiple possible):"]) print(L["Options for |cffffff78"..info[getn(info)].."|r (multiple possible):"])
for k, v in pairs(values) do for k, v in pairs(values) do
if callmethod(info, inputpos, tab, "get", 1, k) then if callmethod(info, inputpos, tab, "get", k) then
print(format(fmt_sel, k, v)) print(format(fmt_sel, k, v))
else else
print(format(fmt, k, v)) print(format(fmt, k, v))
end end
end end
if tab.valuesTableDestroyable then del(values) end
return return
end end
--build a table of the selections, checking that they exist --build a table of the selections, checking that they exist
--parse for =on =off =default in the process --parse for =on =off =default in the process
--table will be key = true for options that should toggle, key = [on|off|default] for options to be set --table will be key = true for options that should toggle, key = [on|off|default] for options to be set
local sels = new() local sels = {}
for v in strgfind(str, "[^ ]+") do for v in strgfind(str, "[^ ]+") do
--parse option=on etc --parse option=on etc
local _, _, opt, val = strfind(v, '(.+)=(.+)') local _, _, opt, val = strfind(v, '(.+)=(.+)')
@@ -598,7 +578,6 @@ local function handle(info, inputpos, tab, depth, retfalse)
break break
end end
end end
if tab.valuesTableDestroyable then del(values) end
if not ok then if not ok then
usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"]) usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"])
@@ -616,7 +595,6 @@ local function handle(info, inputpos, tab, depth, retfalse)
else else
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val)) usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val))
end end
del(sels)
return return
end end
else else
@@ -630,7 +608,7 @@ local function handle(info, inputpos, tab, depth, retfalse)
if (val == true) then if (val == true) then
--toggle the option --toggle the option
local b = callmethod(info, inputpos, tab, "get", 1, opt) local b = callmethod(info, inputpos, tab, "get", opt)
if tab.tristate then if tab.tristate then
--cycle in true, nil, false order --cycle in true, nil, false order
@@ -656,9 +634,8 @@ local function handle(info, inputpos, tab, depth, retfalse)
end end
end end
do_final(info, inputpos, tab, "set", 2, opt, newval) do_final(info, inputpos, tab, "set", opt, newval)
end end
del(sels)
elseif tab.type=="color" then elseif tab.type=="color" then
@@ -671,7 +648,12 @@ local function handle(info, inputpos, tab, depth, retfalse)
local _, r, g, b, a local _, r, g, b, a
local hasAlpha = getValueFromTab(info, inputpos, tab, 'hasAlpha') local hasAlpha = tab.hasAlpha
if type(hasAlpha) == "function" or type(hasAlpha) == "string" then
info.hasAlpha = hasAlpha
hasAlpha = callmethod(info, inputpos, tab, 'hasAlpha')
info.hasAlpha = nil
end
if hasAlpha then if hasAlpha then
if strlen(str) == 8 and strfind(str, "^%x*$") then if strlen(str) == 8 and strfind(str, "^%x*$") then
@@ -726,7 +708,7 @@ local function handle(info, inputpos, tab, depth, retfalse)
end end
end end
do_final(info, inputpos, tab, "set", 4, r,g,b,a) do_final(info, inputpos, tab, "set", r,g,b,a)
elseif tab.type=="keybinding" then elseif tab.type=="keybinding" then
------------ keybinding -------------------------------------------- ------------ keybinding --------------------------------------------
@@ -741,7 +723,7 @@ local function handle(info, inputpos, tab, depth, retfalse)
return return
end end
do_final(info, inputpos, tab, "set", 1, value) do_final(info, inputpos, tab, "set", value)
elseif tab.type=="description" then elseif tab.type=="description" then
------------ description -------------------- ------------ description --------------------
@@ -765,15 +747,12 @@ end
-- -- Show the GUI if no input is supplied, otherwise handle the chat input. -- -- Show the GUI if no input is supplied, otherwise handle the chat input.
-- function MyAddon:ChatCommand(input) -- function MyAddon:ChatCommand(input)
-- -- Assuming "MyOptions" is the appName of a valid options table -- -- Assuming "MyOptions" is the appName of a valid options table
-- if not input or input:trim() == "" then -- if not input or trim(input) == "" then
-- LibStub("AceConfigDialog-3.0"):Open("MyOptions") -- LibStub("AceConfigDialog-3.0"):Open("MyOptions")
-- else -- else
-- LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input) -- LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input)
-- end -- end
-- end -- end
-- Ace3v: experimental, user should copy info table if he wanna reuse it outside
-- then handler
local info_ = {}
function AceConfigCmd:HandleCommand(slashcmd, appName, input) function AceConfigCmd:HandleCommand(slashcmd, appName, input)
local optgetter = cfgreg:GetOptionsTable(appName) local optgetter = cfgreg:GetOptionsTable(appName)
@@ -782,65 +761,32 @@ function AceConfigCmd:HandleCommand(slashcmd, appName, input)
end end
local options = assert( optgetter("cmd", MAJOR) ) local options = assert( optgetter("cmd", MAJOR) )
-- Ace3v: prevent user from using AceConfigCmd as self local info = { -- Don't try to recycle this, it gets handed off to callbacks and whatnot
if self == AceConfigCmd then [0] = slashcmd,
error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'self' - use your own 'self']], 2) appName = appName,
end options = options,
input = input,
self = self,
handler = self,
uiType = "cmd",
uiName = MAJOR,
}
--local info = { -- Don't try to recycle this, it gets handed off to callbacks and whatnot handle(info, 1, options, 0) -- (info, inputpos, table, depth)
-- [0] = slashcmd,
-- appName = appName,
-- options = options,
-- input = input,
-- self = self,
-- handler = self,
-- uiType = "cmd",
-- uiName = MAJOR,
--}
wipe(info_)
info_[0] = slashcmd
info_.appName = appName
info_.options = options
info_.input = input
info_.self = self
info_.handler = self
info_.uiType = "cmd"
info_.uiName = MAJOR
handle(info_, 1, options, 0) -- (info, inputpos, table, depth)
end end
--- Utility function to create a slash command handler. --- Utility function to create a slash command handler.
-- Also registers tab completion with AceTab -- Also registers tab completion with AceTab
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output) -- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
-- @param appName The application name as given to `:RegisterOptionsTable()` -- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigCmd:CreateChatCommand(slashcmd, appName, func) function AceConfigCmd:CreateChatCommand(slashcmd, appName)
if not AceConsole then if not AceConsole then
AceConsole = LibStub(AceConsoleName) AceConsole = LibStub(AceConsoleName)
end end
if AceConsole.RegisterChatCommand(self, slashcmd, function(input)
-- Ace3v: prevent user from using AceConfigCmd as self
if self == AceConfigCmd then
error([[Usage: CreateChatCommand("slashcmd", "appName"[, "func"]): 'self' - use your own 'self']], 2)
end
local t = type(func)
-- Ace3v: make it possible to call another function
local handler
if t == "string" then
handler = function(input) self[func](self, input, slashcmd, appName) end
elseif t ~= "function" then
handler = function(input)
AceConfigCmd.HandleCommand(self, slashcmd, appName, input) -- upgradable AceConfigCmd.HandleCommand(self, slashcmd, appName, input) -- upgradable
end end,
else true) then -- succesfully registered so lets get the command -> app table in
handler = func
end
if AceConsole.RegisterChatCommand(self, slashcmd, handler, true) then
-- succesfully registered so lets get the command -> app table in
commands[slashcmd] = appName commands[slashcmd] = appName
end end
end end
@@ -852,12 +798,3 @@ end
function AceConfigCmd:GetChatCommandOptions(slashcmd) function AceConfigCmd:GetChatCommandOptions(slashcmd)
return commands[slashcmd] return commands[slashcmd]
end end
function AceConfigCmd:Embed(target)
target["HandleCommand"] = self["HandleCommand"]
target["CreateChatCommand"] = self["CreateChatCommand"]
end
for addon in pairs(AceConfigCmd.embeds) do
AceConfigCmd:Embed(addon)
end
@@ -1,20 +1,17 @@
--- AceConfigDialog-3.0 generates AceGUI-3.0 based windows based on option tables. --- AceConfigDialog-3.0 generates AceGUI-3.0 based windows based on option tables.
-- @class file -- @class file
-- @name AceConfigDialog-3.0 -- @name AceConfigDialog-3.0
-- @release $Id: AceConfigDialog-3.0.lua 1139 2016-07-03 07:43:51Z nevcairiel $ -- @release $Id: AceConfigDialog-3.0.lua 1168 2017-10-01 08:05:04Z nevcairiel $
local LibStub = LibStub local LibStub = LibStub
local MAJOR, MINOR = "AceConfigDialog-3.0", 61 local gui = LibStub("AceGUI-3.0")
local reg = LibStub("AceConfigRegistry-3.0")
local MAJOR, MINOR = "AceConfigDialog-3.0", 65
local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR) local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfigDialog then return end if not AceConfigDialog then return end
local AceCore = LibStub("AceCore-3.0")
local wipe = AceCore.wipe
local safecall = AceCore.safecall
local Dispatchers = AceCore.Dispatchers
local countargs = AceCore.countargs
AceConfigDialog.OpenFrames = AceConfigDialog.OpenFrames or {} AceConfigDialog.OpenFrames = AceConfigDialog.OpenFrames or {}
AceConfigDialog.Status = AceConfigDialog.Status or {} AceConfigDialog.Status = AceConfigDialog.Status or {}
AceConfigDialog.frame = AceConfigDialog.frame or CreateFrame("Frame") AceConfigDialog.frame = AceConfigDialog.frame or CreateFrame("Frame")
@@ -23,14 +20,11 @@ AceConfigDialog.frame.apps = AceConfigDialog.frame.apps or {}
AceConfigDialog.frame.closing = AceConfigDialog.frame.closing or {} AceConfigDialog.frame.closing = AceConfigDialog.frame.closing or {}
AceConfigDialog.frame.closeAllOverride = AceConfigDialog.frame.closeAllOverride or {} AceConfigDialog.frame.closeAllOverride = AceConfigDialog.frame.closeAllOverride or {}
local gui = LibStub("AceGUI-3.0")
local reg = LibStub("AceConfigRegistry-3.0")
-- Lua APIs -- Lua APIs
local tconcat, tinsert, tsort, tremove, tgetn, tsetn = table.concat, table.insert, table.sort, table.remove, table.getn, table.setn local tconcat, tinsert, tsort, tremove, tsort, getn, setn = table.concat, table.insert, table.sort, table.remove, table.sort, table.getn, table.setn
local format, strfind, strupper = string.format, string.find, string.upper local gsub, format, upper, find = string.gsub, string.format, string.upper, string.find
local assert, loadstring, error = assert, loadstring, error local assert, loadstring, error = assert, loadstring, error
local pairs, next, type, unpack, ipairs = pairs, next, type, unpack, ipairs local pairs, next, type, unpack, wipe, ipairs = pairs, next, type, unpack, wipe, ipairs
local rawset, tostring, tonumber = rawset, tostring, tonumber local rawset, tostring, tonumber = rawset, tostring, tonumber
local math_min, math_max, math_floor = math.min, math.max, math.floor local math_min, math_max, math_floor = math.min, math.max, math.floor
@@ -42,6 +36,50 @@ local math_min, math_max, math_floor = math.min, math.max, math.floor
local emptyTbl = {} local emptyTbl = {}
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = xpcall, function(err) return geterrorhandler()(err) end
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = unpack(arg)
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = gsub(code, "ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
return Dispatchers[arg.n](func, unpack(arg))
end
local width_multiplier = 170 local width_multiplier = 170
--[[ --[[
@@ -83,7 +121,7 @@ do
for k, v in pairs(t) do for k, v in pairs(t) do
c[k] = v c[k] = v
end end
tsetn(c, tgetn(t)) setn(c, getn(t))
return c return c
end end
function del(t) function del(t)
@@ -101,7 +139,13 @@ do
end end
-- picks the first non-nil value and returns it -- picks the first non-nil value and returns it
local pickfirstset = AceCore.pickfirstset local function pickfirstset(...)
for i=1,arg.n do
if arg[i]~=nil then
return arg[i]
end
end
end
--gets an option from a given group, checking plugins --gets an option from a given group, checking plugins
local function GetSubOption(group, key) local function GetSubOption(group, key)
@@ -151,10 +195,11 @@ local allIsLiteral = {
--gets the value for a member that could be a function --gets the value for a member that could be a function
--function refs are called with an info arg --function refs are called with an info arg
--every other type is returned --every other type is returned
local function GetOptionsMemberValue(membername, option, options, path, appName, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) local function GetOptionsMemberValue(membername, option, options, path, appName, ...)
--get definition for the member --get definition for the member
local inherits = isInherited[membername] local inherits = isInherited[membername]
--get the member of the option, traversing the tree if it can be inherited --get the member of the option, traversing the tree if it can be inherited
local member local member
@@ -163,13 +208,13 @@ local function GetOptionsMemberValue(membername, option, options, path, appName,
if group[membername] ~= nil then if group[membername] ~= nil then
member = group[membername] member = group[membername]
end end
for i = 1, tgetn(path) do for i = 1, getn(path) do
group = GetSubOption(group, path[i]) group = GetSubOption(group, path[i])
if group[membername] ~= nil then if group[membername] ~= nil then
member = group[membername] member = group[membername]
end end
end end
elseif option then else
member = option[membername] member = option[membername]
end end
@@ -182,13 +227,13 @@ local function GetOptionsMemberValue(membername, option, options, path, appName,
local group = options local group = options
handler = group.handler or handler handler = group.handler or handler
local l = tgetn(path) local x = getn(path)
for i = 1, l do for i = 1, x do
group = GetSubOption(group, path[i]) group = GetSubOption(group, path[i])
info[i] = path[i] info[i] = path[i]
handler = group.handler or handler handler = group.handler or handler
end end
tsetn(info, l) setn(info, x)
info.options = options info.options = options
info.appName = appName info.appName = appName
@@ -200,16 +245,15 @@ local function GetOptionsMemberValue(membername, option, options, path, appName,
info.uiType = "dialog" info.uiType = "dialog"
info.uiName = MAJOR info.uiName = MAJOR
argc = argc or 0
local a, b, c ,d local a, b, c ,d
--using 4 returns for the get of a color type, increase if a type needs more --using 4 returns for the get of a color type, increase if a type needs more
if type(member) == "function" then if type(member) == "function" then
--Call the function --Call the function
a,b,c,d = Dispatchers[argc+1](member,info,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) a,b,c,d = member(info, unpack(arg))
else else
--Call the method --Call the method
if handler and handler[member] then if handler and handler[member] then
a,b,c,d = Dispatchers[argc+2](handler[member],handler,info,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) a,b,c,d = handler[member](handler, info, unpack(arg))
else else
error(format("Method %s doesn't exist in handler for type %s", member, membername)) error(format("Method %s doesn't exist in handler for type %s", member, membername))
end end
@@ -281,7 +325,7 @@ local function compareOptions(a,b)
if OrderA == OrderB then if OrderA == OrderB then
local NameA = (type(tempNames[a]) == "string") and tempNames[a] or "" local NameA = (type(tempNames[a]) == "string") and tempNames[a] or ""
local NameB = (type(tempNames[b]) == "string") and tempNames[b] or "" local NameB = (type(tempNames[b]) == "string") and tempNames[b] or ""
return strupper(NameA) < strupper(NameB) return upper(NameA) < upper(NameB)
end end
if OrderA < 0 then if OrderA < 0 then
if OrderB > 0 then if OrderB > 0 then
@@ -341,7 +385,7 @@ end
local function DelTree(tree) local function DelTree(tree)
if tree.children then if tree.children then
local childs = tree.children local childs = tree.children
for i = 1, tgetn(childs) do for i = 1, getn(childs) do
DelTree(childs[i]) DelTree(childs[i])
del(childs[i]) del(childs[i])
end end
@@ -361,7 +405,7 @@ local function CleanUserData(widget, event)
local tree = user.tree local tree = user.tree
widget:SetTree(nil) widget:SetTree(nil)
if tree then if tree then
for i = 1, tgetn(tree) do for i = 1, getn(tree) do
DelTree(tree[i]) DelTree(tree[i])
del(tree[i]) del(tree[i])
end end
@@ -369,7 +413,7 @@ local function CleanUserData(widget, event)
end end
end end
if widget.type == "TabGroup-ElvUI" then if widget.type == "TabGroup" then
widget:SetTabs(nil) widget:SetTabs(nil)
if user.tablist then if user.tablist then
del(user.tablist) del(user.tablist)
@@ -403,7 +447,7 @@ function AceConfigDialog:GetStatusTable(appName, path)
status = status[appName] status = status[appName]
if path then if path then
for i = 1, tgetn(path) do for i = 1, getn(path) do
local v = path[i] local v = path[i]
if not status.children[v] then if not status.children[v] then
status.children[v] = {} status.children[v] = {}
@@ -421,11 +465,10 @@ end
-- The path specified has to match the keys of the groups in the table. -- The path specified has to match the keys of the groups in the table.
-- @param appName The application name as given to `:RegisterOptionsTable()` -- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param ... The path to the key that should be selected -- @param ... The path to the key that should be selected
do function AceConfigDialog:SelectGroup(appName, ...)
local args = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil}
function AceConfigDialog:SelectGroup(appName, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
local path = new() local path = new()
local app = reg:GetOptionsTable(appName) local app = reg:GetOptionsTable(appName)
if not app then if not app then
error(format("%s isn't registed with AceConfigRegistry, unable to open config", appName), 2) error(format("%s isn't registed with AceConfigRegistry, unable to open config", appName), 2)
@@ -440,21 +483,8 @@ function AceConfigDialog:SelectGroup(appName, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
local treevalue local treevalue
local treestatus local treestatus
args[1] = a1 for n = 1, arg.n do
args[2] = a2 local key = arg[n]
args[3] = a3
args[4] = a4
args[5] = a5
args[6] = a6
args[7] = a7
args[8] = a8
args[9] = a9
args[10] = a10
for n = 1, 10 do
local key = args[n]
args[n] = nil
if not key then break end
if group.childGroups == "tab" or group.childGroups == "select" then if group.childGroups == "tab" or group.childGroups == "select" then
--if this is a tab or select group, select the group --if this is a tab or select group, select the group
@@ -498,7 +528,6 @@ function AceConfigDialog:SelectGroup(appName, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
del(path) del(path)
reg:NotifyChange(appName) reg:NotifyChange(appName)
end end
end -- AceConfigDialog:SelectGroup
local function OptionOnMouseOver(widget, event) local function OptionOnMouseOver(widget, event)
--show a tooltip/set the status bar to the desc text --show a tooltip/set the status bar to the desc text
@@ -516,16 +545,16 @@ local function OptionOnMouseOver(widget, event)
if descStyle and descStyle ~= "tooltip" then return end if descStyle and descStyle ~= "tooltip" then return end
GameTooltip:SetText(name, 1, .82, 0, true) GameTooltip:SetText(name, 1, .82, 0, 1)
if opt.type == "multiselect" then if opt.type == "multiselect" then
GameTooltip:AddLine(user.text, 0.5, 0.5, 0.8, true) GameTooltip:AddLine(user.text,0.5, 0.5, 0.8, 1)
end end
if type(desc) == "string" then if type(desc) == "string" then
GameTooltip:AddLine(desc, 1, 1, 1, true) GameTooltip:AddLine(desc, 1, 1, 1, 1)
end end
if type(usage) == "string" then if type(usage) == "string" then
GameTooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, true) GameTooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
end end
GameTooltip:Show() GameTooltip:Show()
@@ -543,7 +572,7 @@ local function GetFuncName(option)
return "set" return "set"
end end
end end
local function confirmPopup(appName, rootframe, basepath, info, message, func, argc,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) local function confirmPopup(appName, rootframe, basepath, info, message, func, ...)
if not StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] then if not StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] then
StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] = {} StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] = {}
end end
@@ -557,7 +586,7 @@ local function confirmPopup(appName, rootframe, basepath, info, message, func, a
t.preferredIndex = STATICPOPUP_NUMDIALOGS t.preferredIndex = STATICPOPUP_NUMDIALOGS
local dialog, oldstrata local dialog, oldstrata
t.OnAccept = function() t.OnAccept = function()
safecall(func, tgetn(t), unpack(t)) safecall(func, unpack(t))
if dialog and oldstrata then if dialog and oldstrata then
dialog:SetFrameStrata(oldstrata) dialog:SetFrameStrata(oldstrata)
end end
@@ -571,23 +600,11 @@ local function confirmPopup(appName, rootframe, basepath, info, message, func, a
AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl)) AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl))
del(info) del(info)
end end
t[1] = a1 local x = arg.n
t[2] = a2 for i = 1, x do
t[3] = a3 t[i] = arg[i] or false
t[4] = a4
t[5] = a5
t[6] = a6
t[7] = a7
t[8] = a8
t[9] = a9
t[10] = a10
for i=1,argc do
t[i] = t[i] or false
end end
for i=argc+1,10 do setn(t, x)
t[i] = nil
end
tsetn(t,argc)
t.timeout = 0 t.timeout = 0
t.whileDead = 1 t.whileDead = 1
t.hideOnEscape = 1 t.hideOnEscape = 1
@@ -599,7 +616,32 @@ local function confirmPopup(appName, rootframe, basepath, info, message, func, a
end end
end end
local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) local function validationErrorPopup(message)
if not StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"] then
StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"] = {}
end
local t = StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"]
t.text = message
t.button1 = OKAY
t.preferredIndex = STATICPOPUP_NUMDIALOGS
local dialog, oldstrata
t.OnAccept = function()
if dialog and oldstrata then
dialog:SetFrameStrata(oldstrata)
end
end
t.timeout = 0
t.whileDead = 1
t.hideOnEscape = 1
dialog = StaticPopup_Show("ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG")
if dialog then
oldstrata = dialog:GetFrameStrata()
dialog:SetFrameStrata("TOOLTIP")
end
end
local function ActivateControl(widget, event, ...)
--This function will call the set / execute handler for the widget --This function will call the set / execute handler for the widget
--widget:GetUserDataTable() contains the needed info --widget:GetUserDataTable() contains the needed info
local user = widget:GetUserDataTable() local user = widget:GetUserDataTable()
@@ -622,9 +664,8 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
handler = group.handler or handler handler = group.handler or handler
confirm = group.confirm confirm = group.confirm
validate = group.validate validate = group.validate
local x = getn(path)
local l = tgetn(path) for i = 1, x do
for i = 1, l do
local v = path[i] local v = path[i]
group = GetSubOption(group, v) group = GetSubOption(group, v)
info[i] = v info[i] = v
@@ -639,7 +680,7 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
validate = group.validate validate = group.validate
end end
end end
tsetn(info, l) setn(info, x)
info.options = options info.options = options
info.appName = user.appName info.appName = user.appName
@@ -651,7 +692,6 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
info.uiName = MAJOR info.uiName = MAJOR
local name local name
if type(option.name) == "function" then if type(option.name) == "function" then
name = option.name(info) name = option.name(info)
elseif type(option.name) == "string" then elseif type(option.name) == "string" then
@@ -666,7 +706,7 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
if option.type == "input" then if option.type == "input" then
if type(pattern)=="string" then if type(pattern)=="string" then
if not strfind(a1, pattern) then if not find(arg[1], pattern) then
validated = false validated = false
end end
end end
@@ -676,42 +716,36 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
if validated and option.type ~= "execute" then if validated and option.type ~= "execute" then
if type(validate) == "string" then if type(validate) == "string" then
if handler and handler[validate] then if handler and handler[validate] then
success, validated = safecall(handler[validate], argc+2, handler, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) success, validated = safecall(handler[validate], handler, info, unpack(arg))
if not success then validated = false end if not success then validated = false end
else else
error(format("Method %s doesn't exist in handler for type execute", validate)) error(format("Method %s doesn't exist in handler for type execute", validate))
end end
elseif type(validate) == "function" then elseif type(validate) == "function" then
success, validated = safecall(validate, argc+1, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) success, validated = safecall(validate, info, unpack(arg))
if not success then validated = false end if not success then validated = false end
end end
end end
local rootframe = user.rootframe local rootframe = user.rootframe
if type(validated) == "string" then if not validated or type(validated) == "string" then
--validate function returned a message to display if not validated then
if usage then
validated = name..": "..usage
else
if pattern then
validated = name..": Expected "..pattern
else
validated = name..": Invalid Value"
end
end
end
-- show validate message
if rootframe.SetStatusText then if rootframe.SetStatusText then
rootframe:SetStatusText(validated) rootframe:SetStatusText(validated)
else else
-- TODO: do something else. validationErrorPopup(validated)
end
PlaySound("igPlayerInviteDecline")
del(info)
return true
elseif not validated then
--validate returned false
if rootframe.SetStatusText then
if usage then
rootframe:SetStatusText(name..": "..usage)
else
if pattern then
rootframe:SetStatusText(name..": Expected "..pattern)
else
rootframe:SetStatusText(name..": Invalid Value")
end
end
else
-- TODO: do something else
end end
PlaySound("igPlayerInviteDecline") PlaySound("igPlayerInviteDecline")
del(info) del(info)
@@ -722,7 +756,7 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
--call confirm func/method --call confirm func/method
if type(confirm) == "string" then if type(confirm) == "string" then
if handler and handler[confirm] then if handler and handler[confirm] then
success, confirm = safecall(handler[confirm], argc+2, handler, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) success, confirm = safecall(handler[confirm], handler, info, unpack(arg))
if success and type(confirm) == "string" then if success and type(confirm) == "string" then
confirmText = confirm confirmText = confirm
confirm = true confirm = true
@@ -733,7 +767,7 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
error(format("Method %s doesn't exist in handler for type confirm", confirm)) error(format("Method %s doesn't exist in handler for type confirm", confirm))
end end
elseif type(confirm) == "function" then elseif type(confirm) == "function" then
success, confirm = safecall(confirm, argc+1, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) success, confirm = safecall(confirm, info, unpack(arg))
if success and type(confirm) == "string" then if success and type(confirm) == "string" then
confirmText = confirm confirmText = confirm
confirm = true confirm = true
@@ -768,12 +802,12 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
local basepath = user.rootframe:GetUserData("basepath") local basepath = user.rootframe:GetUserData("basepath")
if type(func) == "string" then if type(func) == "string" then
if handler and handler[func] then if handler and handler[func] then
confirmPopup(user.appName, rootframe, basepath, info, confirmText, handler[func], argc+2, handler, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) confirmPopup(user.appName, rootframe, basepath, info, confirmText, handler[func], handler, info, unpack(arg))
else else
error(format("Method %s doesn't exist in handler for type func", func)) error(format("Method %s doesn't exist in handler for type func", func))
end end
elseif type(func) == "function" then elseif type(func) == "function" then
confirmPopup(user.appName, rootframe, basepath, info, confirmText, func, argc+1, info,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) confirmPopup(user.appName, rootframe, basepath, info, confirmText, func, info, unpack(arg))
end end
--func will be called and info deleted when the confirm dialog is responded to --func will be called and info deleted when the confirm dialog is responded to
return return
@@ -783,14 +817,16 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
--call the function --call the function
if type(func) == "string" then if type(func) == "string" then
if handler and handler[func] then if handler and handler[func] then
safecall(handler[func], argc+2, handler, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) safecall(handler[func],handler, info, unpack(arg))
else else
error(format("Method %s doesn't exist in handler for type func", func)) error(format("Method %s doesn't exist in handler for type func", func))
end end
elseif type(func) == "function" then elseif type(func) == "function" then
safecall(func, argc+1, info, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) safecall(func,info, unpack(arg))
end end
local iscustom = user.rootframe:GetUserData("iscustom") local iscustom = user.rootframe:GetUserData("iscustom")
local basepath = user.rootframe:GetUserData("basepath") or emptyTbl local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
--full refresh of the frame, some controls dont cause this on all events --full refresh of the frame, some controls dont cause this on all events
@@ -826,7 +862,7 @@ local function ActivateControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a
del(info) del(info)
end end
local function ActivateSlider(widget, event, _, value) local function ActivateSlider(widget, event, value)
local option = widget:GetUserData("option") local option = widget:GetUserData("option")
local min, max, step = option.min or (not option.softMin and 0 or nil), option.max or (not option.softMax and 100 or nil), option.step local min, max, step = option.min or (not option.softMin and 0 or nil), option.max or (not option.softMax and 100 or nil), option.step
if min then if min then
@@ -838,13 +874,13 @@ local function ActivateSlider(widget, event, _, value)
if max then if max then
value = math_min(value, max) value = math_min(value, max)
end end
ActivateControl(widget,event,1,value) ActivateControl(widget,event,value)
end end
--called from a checkbox that is part of an internally created multiselect group --called from a checkbox that is part of an internally created multiselect group
--this type is safe to refresh on activation of one control --this type is safe to refresh on activation of one control
local function ActivateMultiControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) local function ActivateMultiControl(widget, event, ...)
ActivateControl(widget, event, argc+1, widget:GetUserData("value"), a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) ActivateControl(widget, event, widget:GetUserData("value"), unpack(arg))
local user = widget:GetUserDataTable() local user = widget:GetUserDataTable()
local iscustom = user.rootframe:GetUserData("iscustom") local iscustom = user.rootframe:GetUserData("iscustom")
local basepath = user.rootframe:GetUserData("basepath") or emptyTbl local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
@@ -855,7 +891,7 @@ local function ActivateMultiControl(widget, event, argc, a1,a2,a3,a4,a5,a6,a7,a8
end end
end end
local function MultiControlOnClosed(widget, event) local function MultiControlOnClosed(widget, event, ...)
local user = widget:GetUserDataTable() local user = widget:GetUserDataTable()
if user.valuechanged then if user.valuechanged then
local iscustom = user.rootframe:GetUserData("iscustom") local iscustom = user.rootframe:GetUserData("iscustom")
@@ -876,7 +912,7 @@ end
local function CheckOptionHidden(option, options, path, appName) local function CheckOptionHidden(option, options, path, appName)
--check for a specific boolean option --check for a specific boolean option
local hidden = pickfirstset(2,option.dialogHidden,option.guiHidden) local hidden = pickfirstset(option.dialogHidden,option.guiHidden)
if hidden ~= nil then if hidden ~= nil then
return hidden return hidden
end end
@@ -886,7 +922,7 @@ end
local function CheckOptionDisabled(option, options, path, appName) local function CheckOptionDisabled(option, options, path, appName)
--check for a specific boolean option --check for a specific boolean option
local disabled = pickfirstset(2,option.dialogDisabled,option.guiDisabled) local disabled = pickfirstset(option.dialogDisabled,option.guiDisabled)
if disabled ~= nil then if disabled ~= nil then
return disabled return disabled
end end
@@ -907,7 +943,7 @@ local function BuildTabs(group, options, path, appName)
local v = opts[k] local v = opts[k]
if v.type == "group" then if v.type == "group" then
path[#path+1] = k path[#path+1] = k
local inline = pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false) local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName) local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then if not inline and not hidden then
tinsert(tabs, k) tinsert(tabs, k)
@@ -931,12 +967,12 @@ local function BuildSelect(group, options, path, appName)
BuildSortedOptionsTable(group, keySort, opts, options, path, appName) BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
for i = 1, tgetn(keySort) do for i = 1, getn(keySort) do
local k = keySort[i] local k = keySort[i]
local v = opts[k] local v = opts[k]
if v.type == "group" then if v.type == "group" then
tinsert(path, k) tinsert(path, k)
local inline = pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false) local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName) local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then if not inline and not hidden then
groups[k] = GetOptionsMemberValue("name", v, options, path, appName) groups[k] = GetOptionsMemberValue("name", v, options, path, appName)
@@ -958,12 +994,12 @@ local function BuildSubGroups(group, tree, options, path, appName)
BuildSortedOptionsTable(group, keySort, opts, options, path, appName) BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
for i = 1, tgetn(keySort) do for i = 1, getn(keySort) do
local k = keySort[i] local k = keySort[i]
local v = opts[k] local v = opts[k]
if v.type == "group" then if v.type == "group" then
tinsert(path, k) tinsert(path, k)
local inline = pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false) local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName) local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then if not inline and not hidden then
local entry = new() local entry = new()
@@ -993,18 +1029,19 @@ local function BuildGroups(group, options, path, appName, recurse)
BuildSortedOptionsTable(group, keySort, opts, options, path, appName) BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
for i = 1, tgetn(keySort) do for i = 1, getn(keySort) do
local k = keySort[i] local k = keySort[i]
local v = opts[k] local v = opts[k]
if v.type == "group" then if v.type == "group" then
tinsert(path,k) tinsert(path,k)
local inline = pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false) local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName) local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then if not inline and not hidden then
local entry = new() local entry = new()
entry.value = k entry.value = k
entry.text = GetOptionsMemberValue("name", v, options, path, appName) entry.text = GetOptionsMemberValue("name", v, options, path, appName)
entry.icon = GetOptionsMemberValue("icon", v, options, path, appName) entry.icon = GetOptionsMemberValue("icon", v, options, path, appName)
entry.iconCoords = GetOptionsMemberValue("iconCoords", v, options, path, appName)
entry.disabled = CheckOptionDisabled(v, options, path, appName) entry.disabled = CheckOptionDisabled(v, options, path, appName)
tinsert(tree,entry) tinsert(tree,entry)
if recurse and (v.childGroups or "tree") == "tree" then if recurse and (v.childGroups or "tree") == "tree" then
@@ -1021,12 +1058,11 @@ end
local function InjectInfo(control, options, option, path, rootframe, appName) local function InjectInfo(control, options, option, path, rootframe, appName)
local user = control:GetUserDataTable() local user = control:GetUserDataTable()
local l = tgetn(path) local x = getn(path)
for i = 1, l do for i = 1, x do
user[i] = path[i] user[i] = path[i]
end end
tsetn(user,l) setn(user, x)
user.rootframe = rootframe user.rootframe = rootframe
user.option = option user.option = option
user.options = options user.options = options
@@ -1051,7 +1087,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
BuildSortedOptionsTable(group, keySort, opts, options, path, appName) BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
for i = 1, tgetn(keySort) do for i = 1, getn(keySort) do
local k = keySort[i] local k = keySort[i]
local v = opts[k] local v = opts[k]
tinsert(path, k) tinsert(path, k)
@@ -1059,7 +1095,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
local name = GetOptionsMemberValue("name", v, options, path, appName) local name = GetOptionsMemberValue("name", v, options, path, appName)
if not hidden then if not hidden then
if v.type == "group" then if v.type == "group" then
if inline or pickfirstset(4, v.dialogInline,v.guiInline,v.inline, false) then if inline or pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then
--Inline group --Inline group
local GroupContainer local GroupContainer
if name and name ~= "" then if name and name ~= "" then
@@ -1085,7 +1121,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName) local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName) local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
if type(image) == "string" or type(image) == "number" then if type(image) == "string" then
control = gui:Create("Icon") control = gui:Create("Icon")
if not width then if not width then
width = GetOptionsMemberValue("imageWidth",v, options, path, appName) width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
@@ -1148,7 +1184,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
local image = GetOptionsMemberValue("image", v, options, path, appName) local image = GetOptionsMemberValue("image", v, options, path, appName)
local imageCoords = GetOptionsMemberValue("imageCoords", v, options, path, appName) local imageCoords = GetOptionsMemberValue("imageCoords", v, options, path, appName)
if type(image) == "string" or type(image) == "number" then if type(image) == "string" then
if type(imageCoords) == "table" then if type(imageCoords) == "table" then
control:SetImage(image, unpack(imageCoords)) control:SetImage(image, unpack(imageCoords))
else else
@@ -1215,7 +1251,6 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
if not control then if not control then
geterrorhandler()(format("Invalid Custom Control Type - %s", tostring(controlType))) geterrorhandler()(format("Invalid Custom Control Type - %s", tostring(controlType)))
control = gui:Create("Dropdown") control = gui:Create("Dropdown")
end end
local itemType = v.itemControl local itemType = v.itemControl
if itemType and not gui:GetWidgetVersion(itemType) then if itemType and not gui:GetWidgetVersion(itemType) then
@@ -1234,7 +1269,6 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
elseif v.type == "multiselect" then elseif v.type == "multiselect" then
local values = GetOptionsMemberValue("values", v, options, path, appName) local values = GetOptionsMemberValue("values", v, options, path, appName)
local disabled = CheckOptionDisabled(v, options, path, appName) local disabled = CheckOptionDisabled(v, options, path, appName)
local controlType = v.dialogControl or v.control local controlType = v.dialogControl or v.control
@@ -1271,9 +1305,9 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
control:SetWidth(width_multiplier) control:SetWidth(width_multiplier)
end end
--check:SetTriState(v.tristate) --check:SetTriState(v.tristate)
for i = 1, tgetn(valuesort) do for i = 1, getn(valuesort) do
local key = valuesort[i] local key = valuesort[i]
local value = GetOptionsMemberValue("get", v, options, path, appName, 1, key) local value = GetOptionsMemberValue("get",v, options, path, appName, key)
control:SetItemValue(key,value) control:SetItemValue(key,value)
end end
else else
@@ -1284,7 +1318,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
control:PauseLayout() control:PauseLayout()
local width = GetOptionsMemberValue("width",v,options,path,appName) local width = GetOptionsMemberValue("width",v,options,path,appName)
for i = 1, tgetn(valuesort) do for i = 1, getn(valuesort) do
local value = valuesort[i] local value = valuesort[i]
local text = values[value] local text = values[value]
local check = gui:Create("CheckBox") local check = gui:Create("CheckBox")
@@ -1293,7 +1327,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
check:SetUserData("text", text) check:SetUserData("text", text)
check:SetDisabled(disabled) check:SetDisabled(disabled)
check:SetTriState(v.tristate) check:SetTriState(v.tristate)
check:SetValue(GetOptionsMemberValue("get",v, options, path, appName, 1, value)) check:SetValue(GetOptionsMemberValue("get",v, options, path, appName, value))
check:SetCallback("OnValueChanged",ActivateMultiControl) check:SetCallback("OnValueChanged",ActivateMultiControl)
InjectInfo(check, options, v, path, rootframe, appName) InjectInfo(check, options, v, path, rootframe, appName)
control:AddChild(check) control:AddChild(check)
@@ -1350,7 +1384,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName) local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName) local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
if type(image) == "string" or type(image) == "number" then if type(image) == "string" then
if not width then if not width then
width = GetOptionsMemberValue("imageWidth",v, options, path, appName) width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
end end
@@ -1407,15 +1441,14 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin
del(opts) del(opts)
end end
-- Ace3v: recursive local function BuildPath(path, ...)
local function BuildPath(path, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) for i = 1, arg.n do
if a1 then tinsert(path, arg[i])
tinsert(path,a1)
BuildPath(path,a2,a3,a4,a5,a6,a7,a8,a9,a10)
end end
end end
local function TreeOnButtonEnter(widget, event, _, uniquevalue, button)
local function TreeOnButtonEnter(widget, event, uniquevalue, button)
local user = widget:GetUserDataTable() local user = widget:GetUserDataTable()
if not user then return end if not user then return end
local options = user.options local options = user.options
@@ -1424,13 +1457,15 @@ local function TreeOnButtonEnter(widget, event, _, uniquevalue, button)
local appName = user.appName local appName = user.appName
local feedpath = new() local feedpath = new()
for i = 1, tgetn(path) do local x = getn(path)
for i = 1, x do
feedpath[i] = path[i] feedpath[i] = path[i]
end end
setn(feedpath, x)
BuildPath(feedpath, strsplit("\001", uniquevalue)) BuildPath(feedpath, strsplit("\001", uniquevalue))
local group = options local group = options
for i = 1, tgetn(feedpath) do for i = 1, getn(feedpath) do
if not group then return end if not group then return end
group = GetSubOption(group, feedpath[i]) group = GetSubOption(group, feedpath[i])
end end
@@ -1439,43 +1474,41 @@ local function TreeOnButtonEnter(widget, event, _, uniquevalue, button)
local desc = GetOptionsMemberValue("desc", group, options, feedpath, appName) local desc = GetOptionsMemberValue("desc", group, options, feedpath, appName)
GameTooltip:SetOwner(button, "ANCHOR_NONE") GameTooltip:SetOwner(button, "ANCHOR_NONE")
if widget.type == "TabGroup-ElvUI" then if widget.type == "TabGroup" then
GameTooltip:SetPoint("BOTTOM",button,"TOP") GameTooltip:SetPoint("BOTTOM",button,"TOP")
else else
GameTooltip:SetPoint("LEFT",button,"RIGHT") GameTooltip:SetPoint("LEFT",button,"RIGHT")
end end
if name then GameTooltip:SetText(name, 1, .82, 0, 1)
GameTooltip:SetText(name, 1, .82, 0, true)
end
if type(desc) == "string" then if type(desc) == "string" then
GameTooltip:AddLine(desc, 1, 1, 1, true) GameTooltip:AddLine(desc, 1, 1, 1, 1)
end end
GameTooltip:Show() GameTooltip:Show()
end end
local function TreeOnButtonLeave(widget, event, _, value, button) local function TreeOnButtonLeave(widget, event, value, button)
GameTooltip:Hide() GameTooltip:Hide()
end end
local function GroupExists(appName, options, path, uniquevalue) local function GroupExists(appName, options, path, uniquevalue)
if not uniquevalue then return false end if not uniquevalue then return false end
local feedpath = new() local feedpath = new()
local temppath = new() local temppath = new()
local l = tgetn(path) local x = getn(path)
for i = 1, l do for i = 1, x do
feedpath[i] = path[i] feedpath[i] = path[i]
end end
tsetn(feedpath,l) setn(feedpath, x)
BuildPath(feedpath, strsplit("\001", uniquevalue)) BuildPath(feedpath, strsplit("\001", uniquevalue))
local group = options local group = options
for i = 1, tgetn(feedpath) do for i = 1, getn(feedpath) do
local v = feedpath[i] local v = feedpath[i]
temppath[i] = v temppath[i] = v
group = GetSubOption(group, v) group = GetSubOption(group, v)
@@ -1491,8 +1524,7 @@ local function GroupExists(appName, options, path, uniquevalue)
return true return true
end end
local function GroupSelected(widget, event, _, uniquevalue) local function GroupSelected(widget, event, uniquevalue)
if not uniquevalue then widget:ReleaseChildren() return end
local user = widget:GetUserDataTable() local user = widget:GetUserDataTable()
@@ -1502,19 +1534,18 @@ local function GroupSelected(widget, event, _, uniquevalue)
local rootframe = user.rootframe local rootframe = user.rootframe
local feedpath = new() local feedpath = new()
local l = tgetn(path) local x = getn(path)
for i = 1, l do for i = 1, x do
feedpath[i] = path[i] feedpath[i] = path[i]
end end
tsetn(feedpath,l) setn(feedpath, x)
BuildPath(feedpath, strsplit("\001", uniquevalue)) BuildPath(feedpath, strsplit("\001", uniquevalue))
local group = options local group = options
for i = 1, tgetn(feedpath) do for i = 1, getn(feedpath) do
group = GetSubOption(group, feedpath[i]) group = GetSubOption(group, feedpath[i])
end end
widget:ReleaseChildren() widget:ReleaseChildren()
AceConfigDialog:FeedGroup(user.appName,options,widget,rootframe,feedpath) AceConfigDialog:FeedGroup(user.appName,options,widget,rootframe,feedpath)
del(feedpath) del(feedpath)
@@ -1539,16 +1570,16 @@ Rules:
--]] --]]
function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isRoot) function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isRoot)
local group = options local group = options
--follow the path to get to the curent group --follow the path to get to the curent group
local inline local inline
local grouptype, parenttype = options.childGroups, "none" local grouptype, parenttype = options.childGroups, "none"
for i = 1, tgetn(path) do
for i = 1, getn(path) do
local v = path[i] local v = path[i]
group = GetSubOption(group, v) group = GetSubOption(group, v)
inline = inline or pickfirstset(4,group.dialogInline,group.guiInline,group.inline, false) inline = inline or pickfirstset(group.dialogInline,group.guiInline,group.inline, false)
parenttype = grouptype parenttype = grouptype
grouptype = group.childGroups grouptype = group.childGroups
end end
@@ -1560,14 +1591,14 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR
--check if the group has child groups --check if the group has child groups
local hasChildGroups local hasChildGroups
for k, v in pairs(group.args) do for k, v in pairs(group.args) do
if v.type == "group" and not pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then
hasChildGroups = true hasChildGroups = true
end end
end end
if group.plugins then if group.plugins then
for plugin, t in pairs(group.plugins) do for plugin, t in pairs(group.plugins) do
for k, v in pairs(t) do for k, v in pairs(t) do
if v.type == "group" and not pickfirstset(4,v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then
hasChildGroups = true hasChildGroups = true
end end
end end
@@ -1605,7 +1636,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR
local name = GetOptionsMemberValue("name", group, options, path, appName) local name = GetOptionsMemberValue("name", group, options, path, appName)
if grouptype == "tab" then if grouptype == "tab" then
local tab = gui:Create("TabGroup-ElvUI") local tab = gui:Create("TabGroup")
InjectInfo(tab, options, group, path, rootframe, appName) InjectInfo(tab, options, group, path, rootframe, appName)
tab:SetCallback("OnGroupSelected", GroupSelected) tab:SetCallback("OnGroupSelected", GroupSelected)
tab:SetCallback("OnTabEnter", TreeOnButtonEnter) tab:SetCallback("OnTabEnter", TreeOnButtonEnter)
@@ -1623,7 +1654,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR
tab:SetTabs(tabs) tab:SetTabs(tabs)
tab:SetUserData("tablist", tabs) tab:SetUserData("tablist", tabs)
for i = 1, tgetn(tabs) do for i = 1, getn(tabs) do
local entry = tabs[i] local entry = tabs[i]
if not entry.disabled then if not entry.disabled then
tab:SelectTab((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value) tab:SelectTab((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
@@ -1683,7 +1714,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR
tree:SetTree(treedefinition) tree:SetTree(treedefinition)
tree:SetUserData("tree",treedefinition) tree:SetUserData("tree",treedefinition)
for i = 1, tgetn(treedefinition) do for i = 1, getn(treedefinition) do
local entry = treedefinition[i] local entry = treedefinition[i]
if not entry.disabled then if not entry.disabled then
tree:SelectByValue((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value) tree:SelectByValue((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
@@ -1696,7 +1727,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR
end end
end end
local old_CloseSpecialWindows local old_CloseWindows
local function RefreshOnUpdate() local function RefreshOnUpdate()
@@ -1793,11 +1824,11 @@ end
-- @param appName The application name as given to `:RegisterOptionsTable()` -- @param appName The application name as given to `:RegisterOptionsTable()`
-- @param container An optional container frame to feed the options into -- @param container An optional container frame to feed the options into
-- @param ... The path to open after creating the options window (see `:SelectGroup` for details) -- @param ... The path to open after creating the options window (see `:SelectGroup` for details)
function AceConfigDialog:Open(appName, container, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) function AceConfigDialog:Open(appName, container, ...)
if not old_CloseSpecialWindows then if not old_CloseWindows then
old_CloseSpecialWindows = CloseSpecialWindows old_CloseWindows = CloseWindows
CloseSpecialWindows = function() CloseWindows = function(ignoreCenter)
local found = old_CloseSpecialWindows() local found = old_CloseWindows(ignoreCenter)
return self:CloseAll() or found return self:CloseAll() or found
end end
end end
@@ -1818,11 +1849,13 @@ function AceConfigDialog:Open(appName, container, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10
tinsert(path, container) tinsert(path, container)
container = nil container = nil
end end
BuildPath(path, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) for n = 1, arg.n do
tinsert(path, arg[n])
end
local option = options local option = options
if type(container) == "table" and container.type == "BlizOptionsGroup" and tgetn(path) > 0 then if type(container) == "table" and container.type == "BlizOptionsGroup" and getn(path) > 0 then
for i = 1, tgetn(path) do for i = 1, getn(path) do
option = options.args[path[i]] option = options.args[path[i]]
end end
name = format("%s - %s", name, GetOptionsMemberValue("name", option, options, path, appName)) name = format("%s - %s", name, GetOptionsMemberValue("name", option, options, path, appName))
@@ -1834,7 +1867,7 @@ function AceConfigDialog:Open(appName, container, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10
f:ReleaseChildren() f:ReleaseChildren()
f:SetUserData("appName", appName) f:SetUserData("appName", appName)
f:SetUserData("iscustom", true) f:SetUserData("iscustom", true)
if tgetn(path) > 0 then if getn(path) > 0 then
f:SetUserData("basepath", copy(path)) f:SetUserData("basepath", copy(path))
end end
local status = AceConfigDialog:GetStatusTable(appName) local status = AceConfigDialog:GetStatusTable(appName)
@@ -1860,7 +1893,7 @@ function AceConfigDialog:Open(appName, container, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10
f:ReleaseChildren() f:ReleaseChildren()
f:SetCallback("OnClose", FrameOnClose) f:SetCallback("OnClose", FrameOnClose)
f:SetUserData("appName", appName) f:SetUserData("appName", appName)
if tgetn(path) > 0 then if getn(path) > 0 then
f:SetUserData("basepath", copy(path)) f:SetUserData("basepath", copy(path))
end end
f:SetTitle(name or "") f:SetTitle(name or "")
@@ -1926,8 +1959,7 @@ function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...)
local BlizOptions = AceConfigDialog.BlizOptions local BlizOptions = AceConfigDialog.BlizOptions
local key = appName local key = appName
local l = tgetn(arg) for n = 1, arg.n do
for n = 1, l do
key = key.."\001"..arg[n] key = key.."\001"..arg[n]
end end
@@ -1942,10 +1974,10 @@ function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...)
group:SetTitle(name or appName) group:SetTitle(name or appName)
group:SetUserData("appName", appName) group:SetUserData("appName", appName)
if l > 0 then if arg.n > 0 then
local path = {} local path = {}
for n = 1, l do for n = 1, arg.n do
tinsert(path, args[n]) tinsert(path, arg[n])
end end
group:SetUserData("path", path) group:SetUserData("path", path)
end end
@@ -8,24 +8,24 @@
-- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName". -- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName".
-- @class file -- @class file
-- @name AceConfigRegistry-3.0 -- @name AceConfigRegistry-3.0
-- @release $Id: AceConfigRegistry-3.0.lua 1139 2016-07-03 07:43:51Z nevcairiel $ -- @release $Id: AceConfigRegistry-3.0.lua 1105 2013-12-08 22:11:58Z nevcairiel $
local MAJOR, MINOR = "AceConfigRegistry-3.0", 16 local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
local MAJOR, MINOR = "AceConfigRegistry-3.0", 17
local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR) local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR)
if not AceConfigRegistry then return end if not AceConfigRegistry then return end
AceConfigRegistry.tables = AceConfigRegistry.tables or {} AceConfigRegistry.tables = AceConfigRegistry.tables or {}
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
if not AceConfigRegistry.callbacks then if not AceConfigRegistry.callbacks then
AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry) AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry)
end end
-- Lua APIs -- Lua APIs
local tinsert, tconcat, tgetn = table.insert, table.concat, table.getn local tinsert, tconcat = table.insert, table.concat
local strfind = string.find local strfind, strmatch = string.find, string.match
local type, tostring, pairs = type, tostring, pairs local type, tostring, pairs, unpack = type, tostring, pairs, unpack
local error, assert = error, assert local error, assert = error, assert
----------------------------------------------------------------------- -----------------------------------------------------------------------
@@ -40,24 +40,23 @@ AceConfigRegistry.validated = {
dialog = {}, dialog = {},
} }
local function err(msg, errlvl, ...) local function err(msg, errlvl, ...)
local l = tgetn(arg) local t = {}
local i,j = 1,l for i=arg.n,1,-1 do
while i < j do tinsert(t, arg[i])
arg[i], arg[j] = arg[j], arg[i]
i = i+1
j = j-1
end end
error(MAJOR..":ValidateOptionsTable(): "..tconcat(arg,".")..msg, errlvl+2) error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2)
end end
local isstring={["string"]=true, _="string"} local isstring={["string"]=true, _="string"}
local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"} local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
local istable={["table"]=true, _="table"} local istable={["table"]=true, _="table"}
local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"} local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
local optstring={["nil"]=true,["string"]=true, _="string"} local optstring={["nil"]=true,["string"]=true, _="string"}
local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"} local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
local optstringnumberfunc={["nil"]=true,["string"]=true,["number"]=true,["function"]=true, _="string, number or funcref"}
local optnumber={["nil"]=true,["number"]=true, _="number"} local optnumber={["nil"]=true,["number"]=true, _="number"}
local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"} local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"} local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
@@ -83,7 +82,7 @@ local basekeys={
dialogHidden=optmethodbool, dialogHidden=optmethodbool,
dropdownHidden=optmethodbool, dropdownHidden=optmethodbool,
cmdHidden=optmethodbool, cmdHidden=optmethodbool,
icon=optstringnumberfunc, icon=optstringfunc,
iconCoords=optmethodtable, iconCoords=optmethodtable,
handler=opttable, handler=opttable,
get=optmethodfalse, get=optmethodfalse,
@@ -98,7 +97,7 @@ local basekeys={
local typedkeys={ local typedkeys={
header={}, header={},
description={ description={
image=optstringnumberfunc, image=optstringfunc,
imageCoords=optmethodtable, imageCoords=optmethodtable,
imageHeight=optnumber, imageHeight=optnumber,
imageWidth=optnumber, imageWidth=optnumber,
@@ -115,7 +114,7 @@ local typedkeys={
childGroups=optstring, childGroups=optstring,
}, },
execute={ execute={
image=optstringnumberfunc, image=optstringfunc,
imageCoords=optmethodtable, imageCoords=optmethodtable,
imageHeight=optnumber, imageHeight=optnumber,
imageWidth=optnumber, imageWidth=optnumber,
@@ -127,11 +126,10 @@ local typedkeys={
dialogControl=optstring, dialogControl=optstring,
dropdownControl=optstring, dropdownControl=optstring,
multiline=optboolnumber, multiline=optboolnumber,
nullable=optbool,
}, },
toggle={ toggle={
tristate=optbool, tristate=optbool,
image=optstringnumberfunc, image=optstringfunc,
imageCoords=optmethodtable, imageCoords=optmethodtable,
}, },
tristate={ tristate={
@@ -147,7 +145,6 @@ local typedkeys={
}, },
select={ select={
values=ismethodtable, values=ismethodtable,
valuesTableDestroyable=optbool, -- Ace3v: if the values table is generated by AceCore.new
style={ style={
["nil"]=true, ["nil"]=true,
["string"]={dropdown=true,radio=true}, ["string"]={dropdown=true,radio=true},
@@ -160,7 +157,6 @@ local typedkeys={
}, },
multiselect={ multiselect={
values=ismethodtable, values=ismethodtable,
valuesTableDestroyable=optbool, -- Ace3v: if the values table is generated by AceCore.new
style=optstring, style=optstring,
tristate=optbool, tristate=optbool,
control=optstring, control=optstring,
@@ -175,75 +171,75 @@ local typedkeys={
}, },
} }
local function validateKey(k,errlvl,arg) local function validateKey(k,errlvl,...)
errlvl=(errlvl or 0)+1 errlvl=(errlvl or 0)+1
if type(k)~="string" then if type(k)~="string" then
err("["..tostring(k).."] - key is not a string", errlvl, arg) err("["..tostring(k).."] - key is not a string", errlvl,unpack(arg))
end end
if strfind(k, "[%c\127]") then if strfind(k, "[%c\127]") then
err("["..tostring(k).."] - key name contained control characters", errlvl, arg) err("["..tostring(k).."] - key name contained control characters", errlvl,unpack(arg))
end end
end end
local function validateVal(v, oktypes, errlvl, arg) local function validateVal(v, oktypes, errlvl,...)
errlvl=(errlvl or 0)+1 errlvl=(errlvl or 0)+1
local isok=oktypes[type(v)] or oktypes["*"] local isok=oktypes[type(v)] or oktypes["*"]
if not isok then if not isok then
err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl, arg) err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,unpack(arg))
end end
if type(isok)=="table" then -- isok was a table containing specific values to be tested for! if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
if not isok[v] then if not isok[v] then
err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl, arg) err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,unpack(arg))
end end
end end
end end
local function validate(options,errlvl,arg) local function validate(options,errlvl,...)
errlvl=(errlvl or 0)+1 errlvl=(errlvl or 0)+1
-- basic consistency -- basic consistency
if type(options)~="table" then if type(options)~="table" then
err(": expected a table, got a "..type(options), errlvl, arg) err(": expected a table, got a "..type(options), errlvl,unpack(arg))
end end
if type(options.type)~="string" then if type(options.type)~="string" then
err(".type: expected a string, got a "..type(options.type), errlvl, arg) err(".type: expected a string, got a "..type(options.type), errlvl,unpack(arg))
end end
-- get type and 'typedkeys' member -- get type and 'typedkeys' member
local tk = typedkeys[options.type] local tk = typedkeys[options.type]
if not tk then if not tk then
err(".type: unknown type '"..options.type.."'", errlvl, arg) err(".type: unknown type '"..options.type.."'", errlvl,unpack(arg))
end end
-- make sure that all options[] are known parameters -- make sure that all options[] are known parameters
for k,v in pairs(options) do for k,v in pairs(options) do
if not (tk[k] or basekeys[k]) then if not (tk[k] or basekeys[k]) then
err(": unknown parameter", errlvl,tostring(k), arg) err(": unknown parameter", errlvl,tostring(k),unpack(arg))
end end
end end
-- verify that required params are there, and that everything is the right type -- verify that required params are there, and that everything is the right type
for k,oktypes in pairs(basekeys) do for k,oktypes in pairs(basekeys) do
validateVal(options[k], oktypes, errlvl, k, arg) validateVal(options[k], oktypes, errlvl,k,unpack(arg))
end end
for k,oktypes in pairs(tk) do for k,oktypes in pairs(tk) do
validateVal(options[k], oktypes, errlvl, k, arg) validateVal(options[k], oktypes, errlvl,k,unpack(arg))
end end
-- extra logic for groups -- extra logic for groups
if options.type=="group" then if options.type=="group" then
for k,v in pairs(options.args) do for k,v in pairs(options.args) do
validateKey(k,errlvl,"args", arg) validateKey(k,errlvl,"args",unpack(arg))
validate(v, errlvl,k,"args", arg) validate(v, errlvl,k,"args",unpack(arg))
end end
if options.plugins then if options.plugins then
for plugname,plugin in pairs(options.plugins) do for plugname,plugin in pairs(options.plugins) do
if type(plugin)~="table" then if type(plugin)~="table" then
err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname), "plugins", arg) err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",unpack(arg))
end end
for k,v in pairs(plugin) do for k,v in pairs(plugin) do
validateKey(k,errlvl,tostring(plugname),"plugins",arg) validateKey(k,errlvl,tostring(plugname),"plugins",unpack(arg))
validate(v, errlvl,k,tostring(plugname),"plugins",arg) validate(v, errlvl,k,tostring(plugname),"plugins",unpack(arg))
end end
end end
end end
@@ -271,7 +267,7 @@ end
-- @param appName The application name as given to `:RegisterOptionsTable()` -- @param appName The application name as given to `:RegisterOptionsTable()`
function AceConfigRegistry:NotifyChange(appName) function AceConfigRegistry:NotifyChange(appName)
if not AceConfigRegistry.tables[appName] then return end if not AceConfigRegistry.tables[appName] then return end
AceConfigRegistry.callbacks:Fire("ConfigTableChange", 1, appName) AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName)
end end
-- ------------------------------------------------------------------- -- -------------------------------------------------------------------
@@ -285,7 +281,7 @@ local function validateGetterArgs(uiType, uiName, errlvl)
if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl) error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
end end
if not strfind(uiName, "[A-Za-z]+-[0-9]") then -- Expecting e.g. "MyLib-1.2" if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2"
error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl) error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
end end
end end
@@ -7,9 +7,6 @@ local AceDBOptions, oldminor = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR)
if not AceDBOptions then return end -- No upgrade needed if not AceDBOptions then return end -- No upgrade needed
local AceCore = LibStub("AceCore-3.0")
local new, del = AceCore.new, AceCore.del
-- Lua APIs -- Lua APIs
local pairs, next = pairs, next local pairs, next = pairs, next
@@ -233,6 +230,7 @@ elseif LOCALE == "ptBR" then
end end
local defaultProfiles local defaultProfiles
local tmpprofiles = {}
-- Get a list of available profiles for the specified database. -- Get a list of available profiles for the specified database.
-- You can specify which profiles to include/exclude in the list using the two boolean parameters listed below. -- You can specify which profiles to include/exclude in the list using the two boolean parameters listed below.
@@ -241,8 +239,8 @@ local defaultProfiles
-- @param nocurrent If true, then getProfileList will not display the current profile in the list -- @param nocurrent If true, then getProfileList will not display the current profile in the list
-- @return Hashtable of all profiles with the internal name as keys and the display name as value. -- @return Hashtable of all profiles with the internal name as keys and the display name as value.
local function getProfileList(db, common, nocurrent) local function getProfileList(db, common, nocurrent)
local profiles = new() local profiles = {}
local tmpprofiles = new()
-- copy existing profiles into the table -- copy existing profiles into the table
local currentProfile = db:GetCurrentProfile() local currentProfile = db:GetCurrentProfile()
for i,v in pairs(db:GetProfiles(tmpprofiles)) do for i,v in pairs(db:GetProfiles(tmpprofiles)) do
@@ -250,7 +248,6 @@ local function getProfileList(db, common, nocurrent)
profiles[v] = v profiles[v] = v
end end
end end
del(tmpprofiles)
-- add our default profiles to choose from ( or rename existing profiles) -- add our default profiles to choose from ( or rename existing profiles)
for k,v in pairs(defaultProfiles) do for k,v in pairs(defaultProfiles) do
@@ -293,8 +290,6 @@ end
"common" - returns all avaialble profiles + some commonly used profiles ("char - realm", "realm", "class", "Default") "common" - returns all avaialble profiles + some commonly used profiles ("char - realm", "realm", "class", "Default")
"both" - common except the active profile "both" - common except the active profile
]] ]]
-- Ace3v: It is recommanded to destroy the returned table by AceCore.del
-- if it is no longer needed
function OptionsHandlerPrototype:ListProfiles(info) function OptionsHandlerPrototype:ListProfiles(info)
local arg = info.arg local arg = info.arg
local profiles local profiles
@@ -313,9 +308,7 @@ end
function OptionsHandlerPrototype:HasNoProfiles(info) function OptionsHandlerPrototype:HasNoProfiles(info)
local profiles = self:ListProfiles(info) local profiles = self:ListProfiles(info)
local r = (not next(profiles)) and true or false return ((not next(profiles)) and true or false)
del(profiles)
return r
end end
--[[ Copy a profile ]] --[[ Copy a profile ]]
@@ -393,7 +386,6 @@ local optionsTable = {
order = 30, order = 30,
get = false, get = false,
set = "SetProfile", set = "SetProfile",
nullable = false, -- Ace3v: we do not want a null or empty value
}, },
choose = { choose = {
name = L["choose"], name = L["choose"],
@@ -403,7 +395,6 @@ local optionsTable = {
get = "GetCurrentProfile", get = "GetCurrentProfile",
set = "SetProfile", set = "SetProfile",
values = "ListProfiles", values = "ListProfiles",
valuesTableDestroyable = true,
arg = "common", arg = "common",
}, },
copydesc = { copydesc = {
@@ -419,7 +410,6 @@ local optionsTable = {
get = false, get = false,
set = "CopyProfile", set = "CopyProfile",
values = "ListProfiles", values = "ListProfiles",
valuesTableDestroyable = true,
disabled = "HasNoProfiles", disabled = "HasNoProfiles",
arg = "nocurrent", arg = "nocurrent",
}, },
@@ -436,7 +426,6 @@ local optionsTable = {
get = false, get = false,
set = "DeleteProfile", set = "DeleteProfile",
values = "ListProfiles", values = "ListProfiles",
valuesTableDestroyable = true,
disabled = "HasNoProfiles", disabled = "HasNoProfiles",
arg = "nocurrent", arg = "nocurrent",
confirm = true, confirm = true,
@@ -8,7 +8,7 @@ local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
local next, ipairs, pairs = next, ipairs, pairs local next, ipairs, pairs = next, ipairs, pairs
local upper = string.upper local upper = string.upper
local tinsert, sort, tremove = table.insert, table.sort, table.remove local tinsert, tremove, sort = table.insert, table.remove, table.sort
do do
local widgetType = "LSM30_Background" local widgetType = "LSM30_Background"
@@ -22,15 +22,15 @@ do
tinsert(contentFrameCache, self) tinsert(contentFrameCache, self)
end end
local function ContentOnClick(this, button) local function ContentOnClick()
local self = this.obj local self = this.obj
self:Fire("OnValueChanged", 1, this.text:GetText()) self:Fire("OnValueChanged", this.text:GetText())
if self.dropdown then if self.dropdown then
self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
end end
end end
local function ContentOnEnter(this, button) local function ContentOnEnter()
local self = this.obj local self = this.obj
local text = this.text:GetText() local text = this.text:GetText()
local background = self.list[text] ~= text and self.list[text] or Media:Fetch('background',text) local background = self.list[text] ~= text and self.list[text] or Media:Fetch('background',text)
@@ -45,7 +45,7 @@ do
frame = CreateFrame("Button", nil, UIParent) frame = CreateFrame("Button", nil, UIParent)
--frame:SetWidth(200) --frame:SetWidth(200)
frame:SetHeight(18) frame:SetHeight(18)
frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD") frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD")
frame:SetScript("OnClick", ContentOnClick) frame:SetScript("OnClick", ContentOnClick)
frame:SetScript("OnEnter", ContentOnEnter) frame:SetScript("OnEnter", ContentOnEnter)
@@ -166,12 +166,13 @@ do
for i, k in ipairs(sortedlist) do for i, k in ipairs(sortedlist) do
local f = GetContentLine() local f = GetContentLine()
f.text:SetText(k) f.text:SetText(k)
--print(k)
if k == self.value then if k == self.value then
f.check:Show() f.check:Show()
end end
f.obj = self f.obj = self
f.dropdown = self.dropdown f.dropdown = self.dropdown
self.dropdown:AddFrame(f, i) self.dropdown:AddFrame(f)
end end
wipe(sortedlist) wipe(sortedlist)
end end
@@ -183,18 +184,18 @@ do
end end
end end
local function OnHide(this) local function OnHide()
local self = this.obj local self = this.obj
if self.dropdown then if self.dropdown then
self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
end end
end end
local function Drop_OnEnter(this) local function Drop_OnEnter()
this.obj:Fire("OnEnter") this.obj:Fire("OnEnter")
end end
local function Drop_OnLeave(this) local function Drop_OnLeave()
this.obj:Fire("OnLeave") this.obj:Fire("OnLeave")
end end
@@ -8,7 +8,7 @@ local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
local next, ipairs, pairs = next, ipairs, pairs local next, ipairs, pairs = next, ipairs, pairs
local upper = string.upper local upper = string.upper
local tinsert, sort, tremove = table.insert, table.sort, table.remove local tinsert, tremove, sort = table.insert, table.remove, table.sort
do do
local widgetType = "LSM30_Border" local widgetType = "LSM30_Border"
@@ -24,7 +24,7 @@ do
local function ContentOnClick(this, button) local function ContentOnClick(this, button)
local self = this.obj local self = this.obj
self:Fire("OnValueChanged", 1, this.text:GetText()) self:Fire("OnValueChanged", this.text:GetText())
if self.dropdown then if self.dropdown then
self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
end end
@@ -35,7 +35,7 @@ do
local text = this.text:GetText() local text = this.text:GetText()
local border = self.list[text] ~= text and self.list[text] or Media:Fetch('border',text) local border = self.list[text] ~= text and self.list[text] or Media:Fetch('border',text)
this.dropdown:SetBackdrop({edgeFile = border, this.dropdown:SetBackdrop({edgeFile = border,
bgFile="Interface\\DialogFrame\\UI-DialogBox-Background-Dark", bgFile=[[Interface\DialogFrame\UI-DialogBox-Background-Dark]],
tile = true, tileSize = 16, edgeSize = 16, tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 4, right = 4, top = 4, bottom = 4 }}) insets = { left = 4, right = 4, top = 4, bottom = 4 }})
end end
@@ -48,7 +48,7 @@ do
frame = CreateFrame("Button", nil, UIParent) frame = CreateFrame("Button", nil, UIParent)
--frame:SetWidth(200) --frame:SetWidth(200)
frame:SetHeight(18) frame:SetHeight(18)
frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD") frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD")
frame:SetScript("OnClick", ContentOnClick) frame:SetScript("OnClick", ContentOnClick)
frame:SetScript("OnEnter", ContentOnEnter) frame:SetScript("OnEnter", ContentOnEnter)
local check = frame:CreateTexture("OVERLAY") local check = frame:CreateTexture("OVERLAY")
@@ -110,7 +110,7 @@ do
local border = self.list[text] ~= text and self.list[text] or Media:Fetch('border',text) local border = self.list[text] ~= text and self.list[text] or Media:Fetch('border',text)
self.frame.displayButton:SetBackdrop({edgeFile = border, self.frame.displayButton:SetBackdrop({edgeFile = border,
bgFile="Interface\\DialogFrame\\UI-DialogBox-Background-Dark", bgFile=[[Interface\DialogFrame\UI-DialogBox-Background-Dark]],
tile = true, tileSize = 16, edgeSize = 16, tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 4, right = 4, top = 4, bottom = 4 }}) insets = { left = 4, right = 4, top = 4, bottom = 4 }})
end end
@@ -161,12 +161,13 @@ do
for i, k in ipairs(sortedlist) do for i, k in ipairs(sortedlist) do
local f = GetContentLine() local f = GetContentLine()
f.text:SetText(k) f.text:SetText(k)
--print(k)
if k == self.value then if k == self.value then
f.check:Show() f.check:Show()
end end
f.obj = self f.obj = self
f.dropdown = self.dropdown f.dropdown = self.dropdown
self.dropdown:AddFrame(f, i) self.dropdown:AddFrame(f)
end end
wipe(sortedlist) wipe(sortedlist)
end end
@@ -8,7 +8,7 @@ local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
local next, ipairs, pairs = next, ipairs, pairs local next, ipairs, pairs = next, ipairs, pairs
local upper = string.upper local upper = string.upper
local tinsert, sort, tremove = table.insert, table.sort, table.remove local tinsert, tremove, sort = table.insert, table.remove, table.sort
do do
local widgetType = "LSM30_Font" local widgetType = "LSM30_Font"
@@ -24,7 +24,7 @@ do
local function ContentOnClick() local function ContentOnClick()
local self = this.obj local self = this.obj
self:Fire("OnValueChanged", 1, this.text:GetText()) self:Fire("OnValueChanged", this.text:GetText())
if self.dropdown then if self.dropdown then
self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
end end
@@ -38,7 +38,7 @@ do
frame = CreateFrame("Button", nil, UIParent) frame = CreateFrame("Button", nil, UIParent)
--frame:SetWidth(200) --frame:SetWidth(200)
frame:SetHeight(18) frame:SetHeight(18)
frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD") frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD")
frame:SetScript("OnClick", ContentOnClick) frame:SetScript("OnClick", ContentOnClick)
local check = frame:CreateTexture("OVERLAY") local check = frame:CreateTexture("OVERLAY")
check:SetWidth(16) check:SetWidth(16)
@@ -153,7 +153,7 @@ do
f.check:Show() f.check:Show()
end end
f.obj = self f.obj = self
self.dropdown:AddFrame(f, i) self.dropdown:AddFrame(f)
end end
wipe(sortedlist) wipe(sortedlist)
end end
@@ -8,7 +8,7 @@ local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
local next, ipairs, pairs = next, ipairs, pairs local next, ipairs, pairs = next, ipairs, pairs
local upper = string.upper local upper = string.upper
local tinsert, sort, tremove = table.insert, table.sort, table.remove local tinsert, tremove, sort = table.insert, table.remove, table.sort
do do
local widgetType = "LSM30_Sound" local widgetType = "LSM30_Sound"
@@ -24,7 +24,7 @@ do
local function ContentOnClick() local function ContentOnClick()
local self = this.obj local self = this.obj
self:Fire("OnValueChanged", 1, this.text:GetText()) self:Fire("OnValueChanged", this.text:GetText())
if self.dropdown then if self.dropdown then
self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
end end
@@ -44,7 +44,7 @@ do
frame = CreateFrame("Button", nil, UIParent) frame = CreateFrame("Button", nil, UIParent)
--frame:SetWidth(200) --frame:SetWidth(200)
frame:SetHeight(18) frame:SetHeight(18)
frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD") frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD")
frame:SetScript("OnClick", ContentOnClick) frame:SetScript("OnClick", ContentOnClick)
local check = frame:CreateTexture("OVERLAY") local check = frame:CreateTexture("OVERLAY")
check:SetWidth(16) check:SetWidth(16)
@@ -175,7 +175,7 @@ do
f.check:Show() f.check:Show()
end end
f.obj = self f.obj = self
self.dropdown:AddFrame(f, i) self.dropdown:AddFrame(f)
end end
wipe(sortedlist) wipe(sortedlist)
end end
@@ -8,7 +8,7 @@ local AGSMW = LibStub("AceGUISharedMediaWidgets-1.0")
local next, ipairs, pairs = next, ipairs, pairs local next, ipairs, pairs = next, ipairs, pairs
local upper = string.upper local upper = string.upper
local tinsert, sort, tremove = table.insert, table.sort, table.remove local tinsert, tremove, sort = table.insert, table.remove, table.sort
do do
local widgetType = "LSM30_Statusbar" local widgetType = "LSM30_Statusbar"
@@ -24,7 +24,7 @@ do
local function ContentOnClick() local function ContentOnClick()
local self = this.obj local self = this.obj
self:Fire("OnValueChanged", 1, this.text:GetText()) self:Fire("OnValueChanged", this.text:GetText())
if self.dropdown then if self.dropdown then
self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown) self.dropdown = AGSMW:ReturnDropDownFrame(self.dropdown)
end end
@@ -38,7 +38,7 @@ do
frame = CreateFrame("Button", nil, UIParent) frame = CreateFrame("Button", nil, UIParent)
--frame:SetWidth(200) --frame:SetWidth(200)
frame:SetHeight(18) frame:SetHeight(18)
frame:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight", "ADD") frame:SetHighlightTexture([[Interface\QuestFrame\UI-QuestTitleHighlight]], "ADD")
frame:SetScript("OnClick", ContentOnClick) frame:SetScript("OnClick", ContentOnClick)
local check = frame:CreateTexture("OVERLAY") local check = frame:CreateTexture("OVERLAY")
check:SetWidth(16) check:SetWidth(16)
@@ -155,6 +155,7 @@ do
for i, k in ipairs(sortedlist) do for i, k in ipairs(sortedlist) do
local f = GetContentLine() local f = GetContentLine()
f.text:SetText(k) f.text:SetText(k)
--print(k)
if k == self.value then if k == self.value then
f.check:Show() f.check:Show()
end end
@@ -163,7 +164,7 @@ do
f.bar:SetTexture(statusbar) f.bar:SetTexture(statusbar)
f.obj = self f.obj = self
f.dropdown = self.dropdown f.dropdown = self.dropdown
self.dropdown:AddFrame(f, i) self.dropdown:AddFrame(f)
end end
wipe(sortedlist) wipe(sortedlist)
end end
@@ -19,6 +19,8 @@ AGSMW = AGSMW or {}
local next, ipairs = next, ipairs local next, ipairs = next, ipairs
local tinsert, tremove = table.insert, table.remove local tinsert, tremove = table.insert, table.remove
local GetScreenHeight = GetScreenHeight
AceGUIWidgetLSMlists = { AceGUIWidgetLSMlists = {
['font'] = Media:HashTable("font"), ['font'] = Media:HashTable("font"),
['sound'] = Media:HashTable("sound"), ['sound'] = Media:HashTable("sound"),
@@ -140,8 +142,8 @@ end
do do
local sliderBackdrop = { local sliderBackdrop = {
["bgFile"] = "Interface\\Buttons\\UI-SliderBar-Background", ["bgFile"] = [[Interface\Buttons\UI-SliderBar-Background]],
["edgeFile"] = "Interface\\Buttons\\UI-SliderBar-Border", ["edgeFile"] = [[Interface\Buttons\UI-SliderBar-Border]],
["tile"] = true, ["tile"] = true,
["edgeSize"] = 8, ["edgeSize"] = 8,
["tileSize"] = 8, ["tileSize"] = 8,
@@ -153,38 +155,42 @@ do
}, },
} }
local frameBackdrop = { local frameBackdrop = {
bgFile="Interface\\DialogFrame\\UI-DialogBox-Background-Dark", bgFile=[[Interface\DialogFrame\UI-DialogBox-Background-Dark]],
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]],
tile = true, tileSize = 32, edgeSize = 32, tile = true, tileSize = 32, edgeSize = 32,
insets = { left = 11, right = 12, top = 12, bottom = 9 }, insets = { left = 11, right = 12, top = 12, bottom = 9 },
} }
local function OnMouseWheel(self, dir) local function OnMouseWheel()
self.slider:SetValue(self.slider:GetValue()+(15*dir*-1)) this.slider:SetValue(this.slider:GetValue()+(15*arg1*-1))
end end
local function AddFrame(self, frame, i) local function AddFrame(self, frame)
frame:SetParent(self.contentframe) frame:SetParent(self.contentframe)
frame:SetFrameStrata(self:GetFrameStrata()) frame:SetFrameStrata(self:GetFrameStrata())
frame:SetFrameLevel(self:GetFrameLevel() + 100) frame:SetFrameLevel(self:GetFrameLevel() + 100)
if next(self.contentRepo) then if next(self.contentRepo) then
frame:SetPoint("TOPLEFT", self.contentRepo[i-1], "BOTTOMLEFT", 0, 0) frame:SetPoint("TOPLEFT", self.contentRepo[getn(self.contentRepo)], "BOTTOMLEFT", 0, 0)
-- frame:SetPoint("RIGHT", self.contentframe, "RIGHT", 0, 0)
self.contentframe:SetHeight(self.contentframe:GetHeight() + frame:GetHeight()) self.contentframe:SetHeight(self.contentframe:GetHeight() + frame:GetHeight())
else else
self.contentframe:SetHeight(frame:GetHeight()) self.contentframe:SetHeight(frame:GetHeight())
frame:SetPoint("TOPLEFT", self.contentframe, 0, 0) frame:SetPoint("TOPLEFT", self.contentframe, "TOPLEFT", 0, 0)
-- frame:SetPoint("RIGHT", self.contentframe, "RIGHT", 0, 0)
end end
self.contentRepo[i] = frame tinsert(self.contentRepo, frame)
if self.contentframe:GetHeight() > GetScreenHeight()*2/5 - 20 then if self.contentframe:GetHeight() > GetScreenHeight()*2/5 - 20 then
-- self.scrollframe:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -28, 12)
self.scrollframe:SetWidth(128) self.scrollframe:SetWidth(128)
self:SetHeight(GetScreenHeight()*2/5) self:SetHeight(GetScreenHeight()*2/5)
self.slider:Show() self.slider:Show()
self:SetScript("OnMouseWheel", function() OnMouseWheel(this, arg1) end) self:SetScript("OnMouseWheel", OnMouseWheel)
self.scrollframe:UpdateScrollChildRect() self.scrollframe:UpdateScrollChildRect()
self.slider:SetMinMaxValues(0, self.contentframe:GetHeight()-self.scrollframe:GetHeight()) self.slider:SetMinMaxValues(0, self.contentframe:GetHeight()-self.scrollframe:GetHeight())
else else
-- self.scrollframe:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -14, 12)
self.scrollframe:SetWidth(142) self.scrollframe:SetWidth(142)
self:SetHeight(self.contentframe:GetHeight()+25) self:SetHeight(self.contentframe:GetHeight()+25)
self.slider:Hide() self.slider:Hide()
@@ -229,10 +235,12 @@ do
scrollframe:SetWidth(128) scrollframe:SetWidth(128)
scrollframe:SetHeight((GetScreenHeight()*2/5) - 24) scrollframe:SetHeight((GetScreenHeight()*2/5) - 24)
scrollframe:SetPoint("TOPLEFT", frame, "TOPLEFT", 14, -13) scrollframe:SetPoint("TOPLEFT", frame, "TOPLEFT", 14, -13)
-- scrollframe:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -14, 12)
scrollframe:SetScrollChild(contentframe) scrollframe:SetScrollChild(contentframe)
frame.scrollframe = scrollframe frame.scrollframe = scrollframe
contentframe:SetPoint("TOPLEFT", scrollframe) contentframe:SetPoint("TOPLEFT", scrollframe)
-- contentframe:SetPoint("TOPRIGHT", scrollframe)
local bgTex = frame:CreateTexture(nil, "ARTWORK") local bgTex = frame:CreateTexture(nil, "ARTWORK")
bgTex:SetAllPoints(scrollframe) bgTex:SetAllPoints(scrollframe)
@@ -247,7 +255,7 @@ do
slider:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -14, -10) slider:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -14, -10)
slider:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -14, 10) slider:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -14, 10)
slider:SetBackdrop(sliderBackdrop) slider:SetBackdrop(sliderBackdrop)
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") slider:SetThumbTexture([[Interface\Buttons\UI-SliderBar-Button-Vertical]])
slider:SetMinMaxValues(0, 1) slider:SetMinMaxValues(0, 1)
--slider:SetValueStep(1) --slider:SetValueStep(1)
slider:SetWidth(12) slider:SetWidth(12)
+122 -73
View File
@@ -30,17 +30,13 @@ local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR)
if not AceGUI then return end -- No upgrade needed if not AceGUI then return end -- No upgrade needed
local AceCore = LibStub("AceCore-3.0")
local hooksecurefunc = AceCore.hooksecurefunc
local safecall = AceCore.safecall
-- Lua APIs -- Lua APIs
local tconcat, tremove, tinsert, tgetn, tsetn = table.concat, table.remove, table.insert, table.getn, table.setn local tconcat, tremove, tinsert, getn = table.concat, table.remove, table.insert, table.getn
local pairs, next, type = pairs, next, type local format, gsub, upper = string.format, string.gsub, string.upper
local pairs, next, type, unpack = pairs, next, type, unpack
local error, assert, loadstring = error, assert, loadstring local error, assert, loadstring = error, assert, loadstring
local setmetatable, rawget, rawset = setmetatable, rawget, rawset local setmetatable, rawget, rawset = setmetatable, rawget, rawset
local math_max = math.max local math_max = math.max
local strupper, strfmt = string.upper, string.format
-- WoW APIs -- WoW APIs
local UIParent = UIParent local UIParent = UIParent
@@ -56,17 +52,74 @@ AceGUI.LayoutRegistry = AceGUI.LayoutRegistry or {}
AceGUI.WidgetBase = AceGUI.WidgetBase or {} AceGUI.WidgetBase = AceGUI.WidgetBase or {}
AceGUI.WidgetContainerBase = AceGUI.WidgetContainerBase or {} AceGUI.WidgetContainerBase = AceGUI.WidgetContainerBase or {}
AceGUI.WidgetVersions = AceGUI.WidgetVersions or {} AceGUI.WidgetVersions = AceGUI.WidgetVersions or {}
AceGUI.HookedFunctions = AceGUI.HookedFunctions or {}
-- local upvalues -- local upvalues
local WidgetRegistry = AceGUI.WidgetRegistry local WidgetRegistry = AceGUI.WidgetRegistry
local LayoutRegistry = AceGUI.LayoutRegistry local LayoutRegistry = AceGUI.LayoutRegistry
local WidgetVersions = AceGUI.WidgetVersions local WidgetVersions = AceGUI.WidgetVersions
local HookedFunctions = AceGUI.HookedFunctions
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
local function errorhandler(err)
return geterrorhandler()(err)
end
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = xpcall, function(err) return geterrorhandler()(err) end
local method, ARGS
local function call() return method(ARGS) end
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = unpack(arg)
return xpcall(call, eh)
end
return dispatch
]]
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = gsub(code, "ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
local function safecall(func, ...)
return Dispatchers[arg.n](func, unpack(arg))
end
-- Recycling functions -- Recycling functions
local newWidget, delWidget local newWidget, delWidget
do do
-- Version Upgrade in Minor 29
-- Internal Storage of the objects changed, from an array table
-- to a hash table, and additionally we introduced versioning on
-- the widgets which would discard all widgets from a pre-29 version
-- anyway, so we just clear the storage now, and don't try to
-- convert the storage tables to the new format.
-- This should generally not cause *many* widgets to end up in trash,
-- since once dialogs are opened, all addons should be loaded already
-- and AceGUI should be on the latest version available on the users
-- setup.
-- -- nevcairiel - Nov 2nd, 2009
if oldminor and oldminor < 29 and AceGUI.objPools then
AceGUI.objPools = nil
end
AceGUI.objPools = AceGUI.objPools or {} AceGUI.objPools = AceGUI.objPools or {}
local objPools = AceGUI.objPools local objPools = AceGUI.objPools
--Returns a new instance, if none are available either returns a new table or calls the given contructor --Returns a new instance, if none are available either returns a new table or calls the given contructor
@@ -105,16 +158,19 @@ do
end end
end end
local function fixlevels(parent,...)
local i = 1 local function fixlevels(parent)
local child = arg[i] local child
while child do local childList = {parent:GetChildren()}
child:SetFrameLevel(parent:GetFrameLevel() + (parent.backdrop and -1 or 2)) local level = parent:GetFrameLevel() + 1
fixlevels(child, child:GetChildren())
i = i + 1 for i = 1, getn(childList) do
child = arg[i] child = childList[i]
child:SetFrameLevel(level)
fixlevels(child)
end end
end end
------------------- -------------------
-- API Functions -- -- API Functions --
------------------- -------------------
@@ -130,15 +186,27 @@ function AceGUI:Create(type)
if WidgetRegistry[type] then if WidgetRegistry[type] then
local widget = newWidget(type) local widget = newWidget(type)
if rawget(widget, "Acquire") then
widget.OnAcquire = widget.Acquire
widget.Acquire = nil
elseif rawget(widget, "Aquire") then
widget.OnAcquire = widget.Aquire
widget.Aquire = nil
end
if rawget(widget, "Release") then
widget.OnRelease = rawget(widget, "Release")
widget.Release = nil
end
if widget.OnAcquire then if widget.OnAcquire then
widget:OnAcquire() widget:OnAcquire()
else else
error(strfmt("Widget type %s doesn't supply an OnAcquire Function", type)) error(format("Widget type %s doesn't supply an OnAcquire Function", type))
end end
-- Set the default Layout ("List") -- Set the default Layout ("List")
safecall(widget.SetLayout, 2, widget, "List") safecall(widget.SetLayout, widget, "List")
safecall(widget.ResumeLayout, 1, widget) safecall(widget.ResumeLayout, widget)
return widget return widget
end end
end end
@@ -149,14 +217,14 @@ end
-- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well. -- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well.
-- @param widget The widget to release -- @param widget The widget to release
function AceGUI:Release(widget) function AceGUI:Release(widget)
safecall(widget.PauseLayout, 1, widget) safecall(widget.PauseLayout, widget)
widget:Fire("OnRelease") widget:Fire("OnRelease")
safecall(widget.ReleaseChildren, 1, widget) safecall(widget.ReleaseChildren, widget)
if widget.OnRelease then if widget.OnRelease then
widget:OnRelease() widget:OnRelease()
-- else -- else
-- error(strfmt("Widget type %s doesn't supply an OnRelease Function", widget.type)) -- error(format("Widget type %s doesn't supply an OnRelease Function", widget.type))
end end
for k in pairs(widget.userdata) do for k in pairs(widget.userdata) do
widget.userdata[k] = nil widget.userdata[k] = nil
@@ -191,7 +259,7 @@ end
-- @param widget The widget that should be focused -- @param widget The widget that should be focused
function AceGUI:SetFocus(widget) function AceGUI:SetFocus(widget)
if self.FocusedWidget and self.FocusedWidget ~= widget then if self.FocusedWidget and self.FocusedWidget ~= widget then
safecall(self.FocusedWidget.ClearFocus, 1, self.FocusedWidget) safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
end end
self.FocusedWidget = widget self.FocusedWidget = widget
end end
@@ -201,7 +269,7 @@ end
-- e.g. titlebar of a frame being clicked -- e.g. titlebar of a frame being clicked
function AceGUI:ClearFocus() function AceGUI:ClearFocus()
if self.FocusedWidget then if self.FocusedWidget then
safecall(self.FocusedWidget.ClearFocus, 1, self.FocusedWidget) safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
self.FocusedWidget = nil self.FocusedWidget = nil
end end
end end
@@ -246,7 +314,7 @@ do
frame:SetParent(nil) frame:SetParent(nil)
frame:SetParent(parent.content) frame:SetParent(parent.content)
self.parent = parent self.parent = parent
fixlevels(frame, frame:GetChildren()) fixlevels(frame)
end end
WidgetBase.SetCallback = function(self, name, func) WidgetBase.SetCallback = function(self, name, func)
@@ -255,11 +323,9 @@ do
end end
end end
WidgetBase.Fire = function(self, name, argc, ...) WidgetBase.Fire = function(self, name, ...)
argc = arg.n if self.events[name] then
local func = self.events[name] local success, ret = safecall(self.events[name], self, name, unpack(arg))
if func then
local success, ret = safecall(func, argc+3, self, name, argc, unpack(arg))
if success then if success then
return ret return ret
end end
@@ -310,8 +376,8 @@ do
AceGUI:Release(self) AceGUI:Release(self)
end end
WidgetBase.SetPoint = function(self, a1,a2,a3,a4,a5) WidgetBase.SetPoint = function(self, ...)
return self.frame:SetPoint(a1,a2,a3,a4,a5) return self.frame:SetPoint(unpack(arg))
end end
WidgetBase.ClearAllPoints = function(self) WidgetBase.ClearAllPoints = function(self)
@@ -322,8 +388,8 @@ do
return self.frame:GetNumPoints() return self.frame:GetNumPoints()
end end
WidgetBase.GetPoint = function(self, a1,a2,a3,a4,a5) WidgetBase.GetPoint = function(self, ...)
return self.frame:GetPoint(a1,a2,a3,a4,a5) return self.frame:GetPoint(unpack(arg))
end end
WidgetBase.GetUserDataTable = function(self) WidgetBase.GetUserDataTable = function(self)
@@ -381,7 +447,7 @@ do
if self.LayoutPaused then if self.LayoutPaused then
return return
end end
safecall(self.LayoutFunc, 2, self.content, self.children) safecall(self.LayoutFunc, self.content, self.children)
end end
--call this function to layout, makes sure layed out objects get a frame to get sizes etc --call this function to layout, makes sure layed out objects get a frame to get sizes etc
@@ -410,50 +476,34 @@ do
self:DoLayout() self:DoLayout()
end end
do WidgetContainerBase.AddChildren = function(self, ...)
local args = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil} for i = 1, arg.n do
WidgetContainerBase.AddChildren = function(self,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) local child = arg[i]
args[1] = a1
args[2] = a2
args[3] = a3
args[4] = a4
args[5] = a5
args[6] = a6
args[7] = a7
args[8] = a8
args[9] = a9
args[10] = a10
for i = 1,10 do
local child = args[i]
arg[i] = nil
if not child then break end
tinsert(self.children, child) tinsert(self.children, child)
child:SetParent(self) child:SetParent(self)
child.frame:Show() child.frame:Show()
end end
self:DoLayout() self:DoLayout()
end end
end -- WidgetContainerBase.AddChildren
WidgetContainerBase.ReleaseChildren = function(self) WidgetContainerBase.ReleaseChildren = function(self)
local children = self.children local children = self.children
for i = 1,tgetn(children) do for i = 1,getn(children) do
AceGUI:Release(tremove(children)) AceGUI:Release(tremove(children))
end end
end end
--[[WidgetContainerBase.SetParent = function(self, parent) WidgetContainerBase.SetParent = function(self, parent)
--WidgetBase.SetParent(self, parent) WidgetBase.SetParent(self, parent)
local lv = self.frame:GetFrameLevel() local level = self.frame:GetFrameLevel()
self.content:SetFrameLevel(lv+1) self.content:SetFrameLevel(level + 1)
local children = self.children local children = self.children
for i = 1,tgetn(children) do for i = 1,getn(children) do
local child = children[i] local child = children[i]
child:SetParent(self) child:SetParent(self)
end end
end]] end
WidgetContainerBase.SetLayout = function(self, Layout) WidgetContainerBase.SetLayout = function(self, Layout)
self.LayoutFunc = AceGUI:GetLayout(Layout) self.LayoutFunc = AceGUI:GetLayout(Layout)
@@ -548,7 +598,7 @@ end
function AceGUI:RegisterLayout(Name, LayoutFunc) function AceGUI:RegisterLayout(Name, LayoutFunc)
assert(type(LayoutFunc) == "function") assert(type(LayoutFunc) == "function")
if type(Name) == "string" then if type(Name) == "string" then
Name = string.upper(Name) Name = upper(Name)
end end
LayoutRegistry[Name] = LayoutFunc LayoutRegistry[Name] = LayoutFunc
end end
@@ -557,7 +607,7 @@ end
-- @param Name The name of the layout -- @param Name The name of the layout
function AceGUI:GetLayout(Name) function AceGUI:GetLayout(Name)
if type(Name) == "string" then if type(Name) == "string" then
Name = strupper(Name) Name = upper(Name)
end end
return LayoutRegistry[Name] return LayoutRegistry[Name]
end end
@@ -604,7 +654,7 @@ AceGUI:RegisterLayout("List",
function(content, children) function(content, children)
local height = 0 local height = 0
local width = content.width or content:GetWidth() or 0 local width = content.width or content:GetWidth() or 0
for i = 1, tgetn(children) do for i = 1, getn(children) do
local child = children[i] local child = children[i]
local frame = child.frame local frame = child.frame
@@ -633,7 +683,7 @@ AceGUI:RegisterLayout("List",
height = height + (frame.height or frame:GetHeight() or 0) height = height + (frame.height or frame:GetHeight() or 0)
end end
safecall(content.obj.LayoutFinished, 3, content.obj, nil, height) safecall(content.obj.LayoutFinished, content.obj, nil, height)
end) end)
-- A single control fills the whole content area -- A single control fills the whole content area
@@ -644,15 +694,14 @@ AceGUI:RegisterLayout("Fill",
children[1]:SetHeight(content:GetHeight() or 0) children[1]:SetHeight(content:GetHeight() or 0)
children[1].frame:SetAllPoints(content) children[1].frame:SetAllPoints(content)
children[1].frame:Show() children[1].frame:Show()
safecall(content.obj.LayoutFinished, 3, content.obj, nil, children[1].frame:GetHeight()) safecall(content.obj.LayoutFinished, content.obj, nil, children[1].frame:GetHeight())
end end
end) end)
-- Ace3v: currently only a1 used
local layoutrecursionblock = nil local layoutrecursionblock = nil
local function safelayoutcall(object, func, a1) local function safelayoutcall(object, func, ...)
layoutrecursionblock = true layoutrecursionblock = true
object[func](object, a1) object[func](object, unpack(arg))
layoutrecursionblock = nil layoutrecursionblock = nil
end end
@@ -679,7 +728,7 @@ AceGUI:RegisterLayout("Flow",
local frameoffset local frameoffset
local lastframeoffset local lastframeoffset
local oversize local oversize
for i = 1, tgetn(children) do for i = 1, getn(children) do
local child = children[i] local child = children[i]
oversize = nil oversize = nil
local frame = child.frame local frame = child.frame
@@ -785,5 +834,5 @@ AceGUI:RegisterLayout("Flow",
end end
height = height + rowheight + 3 height = height + rowheight + 3
safecall(content.obj.LayoutFinished, 3, content.obj, nil, height) safecall(content.obj.LayoutFinished, content.obj, nil, height)
end) end)
@@ -15,11 +15,11 @@ local CreateFrame = CreateFrame
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
Scripts Scripts
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
local function SelectedGroup(self, event, _, value) local function SelectedGroup(self, event, value)
local group = self.parentgroup local group = self.parentgroup
local status = group.status or group.localstatus local status = group.status or group.localstatus
status.selected = value status.selected = value
self.parentgroup:Fire("OnGroupSelected", 1, value) self.parentgroup:Fire("OnGroupSelected", value)
end end
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
@@ -63,7 +63,7 @@ local methods = {
self.dropdown:SetValue(group) self.dropdown:SetValue(group)
local status = self.status or self.localstatus local status = self.status or self.localstatus
status.selected = group status.selected = group
self:Fire("OnGroupSelected", 1, group) self:Fire("OnGroupSelected", group)
end, end,
["OnWidthSet"] = function(self, width) ["OnWidthSet"] = function(self, width)
@@ -1,15 +1,13 @@
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
Frame Container Frame Container
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
local Type, Version = "Frame", 24 local Type, Version = "Frame", 25
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
local AceCore = LibStub("AceCore-3.0")
local wipe = AceCore.wipe
-- Lua APIs -- Lua APIs
local pairs, assert, type = pairs, assert, type local pairs, assert, type = pairs, assert, type
local wipe = table.wipe
-- WoW APIs -- WoW APIs
local PlaySound = PlaySound local PlaySound = PlaySound
@@ -27,6 +25,10 @@ local function Button_OnClick()
this.obj:Hide() this.obj:Hide()
end end
local function Frame_OnShow()
this.obj:Fire("OnShow")
end
local function Frame_OnClose() local function Frame_OnClose()
this.obj:Fire("OnClose") this.obj:Fire("OnClose")
end end
@@ -154,7 +156,7 @@ local methods = {
frame:SetPoint("TOP", UIParent, "BOTTOM", 0, status.top) frame:SetPoint("TOP", UIParent, "BOTTOM", 0, status.top)
frame:SetPoint("LEFT", UIParent, "LEFT", status.left, 0) frame:SetPoint("LEFT", UIParent, "LEFT", status.left, 0)
else else
frame:SetPoint("CENTER", UIParent) frame:SetPoint("CENTER", 0, 0)
end end
end end
} }
@@ -188,6 +190,7 @@ local function Constructor()
frame:SetBackdropColor(0, 0, 0, 1) frame:SetBackdropColor(0, 0, 0, 1)
frame:SetMinResize(400, 200) frame:SetMinResize(400, 200)
frame:SetToplevel(true) frame:SetToplevel(true)
frame:SetScript("OnShow", Frame_OnShow)
frame:SetScript("OnHide", Frame_OnClose) frame:SetScript("OnHide", Frame_OnClose)
frame:SetScript("OnMouseDown", Frame_OnMouseDown) frame:SetScript("OnMouseDown", Frame_OnMouseDown)
@@ -245,7 +248,6 @@ local function Constructor()
titlebg_r:SetWidth(30) titlebg_r:SetWidth(30)
titlebg_r:SetHeight(40) titlebg_r:SetHeight(40)
-- bottom right sizer
local sizer_se = CreateFrame("Frame", nil, frame) local sizer_se = CreateFrame("Frame", nil, frame)
sizer_se:SetPoint("BOTTOMRIGHT", 0, 0) sizer_se:SetPoint("BOTTOMRIGHT", 0, 0)
sizer_se:SetWidth(25) sizer_se:SetWidth(25)
@@ -255,9 +257,20 @@ local function Constructor()
sizer_se:SetScript("OnMouseUp", MoverSizer_OnMouseUp) sizer_se:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
local line1 = sizer_se:CreateTexture(nil, "BACKGROUND") local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
line1:SetPoint("BOTTOMRIGHT", -10, 10) line1:SetWidth(14)
line1:SetTexture("Interface\\Cursor\\Item") line1:SetHeight(14)
line1:SetTexCoord(1, 0, 1, 0) line1:SetPoint("BOTTOMRIGHT", -8, 8)
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 14/17
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
line2:SetWidth(8)
line2:SetHeight(8)
line2:SetPoint("BOTTOMRIGHT", -8, 8)
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
local x = 0.1 * 8/17
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
local sizer_s = CreateFrame("Frame", nil, frame) local sizer_s = CreateFrame("Frame", nil, frame)
sizer_s:SetPoint("BOTTOMRIGHT", -25, 0) sizer_s:SetPoint("BOTTOMRIGHT", -25, 0)
@@ -278,7 +291,6 @@ local function Constructor()
--Container Support --Container Support
local content = CreateFrame("Frame", nil, frame) local content = CreateFrame("Frame", nil, frame)
content:SetPoint("TOPLEFT", 17, -27) content:SetPoint("TOPLEFT", 17, -27)
--content:SetPoint("BOTTOMRIGHT", -17, 40)
local widget = { local widget = {
localstatus = {}, localstatus = {},
@@ -2,7 +2,7 @@
ScrollFrame Container ScrollFrame Container
Plain container that scrolls its content and doesn't grow in height. Plain container that scrolls its content and doesn't grow in height.
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
local Type, Version = "ScrollFrame", 24 local Type, Version = "ScrollFrame", 23
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
@@ -90,7 +90,6 @@ local methods = {
end, end,
["FixScroll"] = function(self) ["FixScroll"] = function(self)
if self.updateLock then return end if self.updateLock then return end
self.updateLock = true self.updateLock = true
local status = self.status or self.localstatus local status = self.status or self.localstatus
@@ -153,6 +152,13 @@ local methods = {
end, end,
["OnHeightSet"] = function(self, height) ["OnHeightSet"] = function(self, height)
local parent = self.parent
if parent and height then
height = (parent.content.height or 0) or height
self.frame.height = parent.content.height or 0
end
self.scrollframe:SetHeight(height)
local content = self.content local content = self.content
content.height = height content.height = height
end end
@@ -169,7 +175,7 @@ local function Constructor()
scrollframe:SetPoint("BOTTOMRIGHT", 0, 0) scrollframe:SetPoint("BOTTOMRIGHT", 0, 0)
scrollframe:EnableMouseWheel(true) scrollframe:EnableMouseWheel(true)
scrollframe:SetScript("OnMouseWheel", ScrollFrame_OnMouseWheel) scrollframe:SetScript("OnMouseWheel", ScrollFrame_OnMouseWheel)
-- scrollframe:SetScript("OnSizeChanged", ScrollFrame_OnSizeChanged) scrollframe:SetScript("OnSizeChanged", ScrollFrame_OnSizeChanged)
local scrollbar = CreateFrame("Slider", format("AceConfigDialogScrollFrame%dScrollBar", num), scrollframe, "UIPanelScrollBarTemplate") local scrollbar = CreateFrame("Slider", format("AceConfigDialogScrollFrame%dScrollBar", num), scrollframe, "UIPanelScrollBarTemplate")
scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16) scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16)
@@ -2,14 +2,14 @@
TabGroup Container TabGroup Container
Container that uses tabs on top to switch between groups. Container that uses tabs on top to switch between groups.
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
local Type, Version = "TabGroup-ElvUI", 31 local Type, Version = "TabGroup", 31
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs -- Lua APIs
local pairs, ipairs, assert, type, wipe = pairs, ipairs, assert, type, wipe local pairs, ipairs, assert, type, wipe = pairs, ipairs, assert, type, wipe
local getn = table.getn
local format = string.format local format = string.format
local getn = table.getn
-- WoW APIs -- WoW APIs
local PlaySound = PlaySound local PlaySound = PlaySound
@@ -72,12 +72,12 @@ end
local function Tab_OnEnter() local function Tab_OnEnter()
local self = this.obj local self = this.obj
self:Fire("OnTabEnter", 2, self.tabs[this.id].value, this) self:Fire("OnTabEnter", self.tabs[this.id].value, this)
end end
local function Tab_OnLeave() local function Tab_OnLeave()
local self = this.obj local self = this.obj
self:Fire("OnTabLeave", 2, self.tabs[this.id].value, this) self:Fire("OnTabLeave", self.tabs[this.id].value, this)
end end
local function Tab_OnShow() local function Tab_OnShow()
@@ -110,6 +110,21 @@ local methods = {
tab.id = id tab.id = id
tab:SetHeight(24) tab:SetHeight(24)
-- Normal texture
local texture = _G[tabname.."Left"]
texture:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
texture = _G[tabname.."Middle"]
texture:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
texture = _G[tabname.."Right"]
texture:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
-- Disabled texture
texture = _G[tabname.."LeftDisabled"]
texture:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
texture = _G[tabname.."MiddleDisabled"]
texture:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
texture = _G[tabname.."RightDisabled"]
texture:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
tab.text = _G[tabname .. "Text"] tab.text = _G[tabname .. "Text"]
tab.text:ClearAllPoints() tab.text:ClearAllPoints()
tab.text:SetPoint("LEFT", 14, -3) tab.text:SetPoint("LEFT", 14, -3)
@@ -156,7 +171,7 @@ local methods = {
end end
status.selected = value status.selected = value
if found then if found then
self:Fire("OnGroupSelected",1,value) self:Fire("OnGroupSelected",value)
end end
end, end,
@@ -189,19 +204,24 @@ local methods = {
end end
tab:Show() tab:Show()
if type(v) == "table" then
tab:SetText(v.text) tab:SetText(v.text)
tab:SetDisabled(v.disabled) tab:SetDisabled(v.disabled)
tab.value = v.value tab.value = v.value
elseif type(v) == "string" then
tab:SetText(v)
tab.value = v
end
widths[i] = tab:GetWidth() - 6 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing, but add a fixed 4px padding for the text widths[i] = tab:GetWidth() - 6 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing, but add a fixed 4px padding for the text
end end
local numtabs = getn(tablist) for i = getn(tablist)+1, getn(tabs), 1 do
for i = numtabs+1, numtabs, 1 do
tabs[i]:Hide() tabs[i]:Hide()
end end
--First pass, find the minimum number of rows needed to hold all tabs and the initial tab layout --First pass, find the minimum number of rows needed to hold all tabs and the initial tab layout
local numtabs = getn(tablist)
local numrows = 1 local numrows = 1
local usedwidth = 0 local usedwidth = 0
@@ -281,6 +301,14 @@ local methods = {
end, end,
["OnHeightSet"] = function(self, height) ["OnHeightSet"] = function(self, height)
local parent = self.parent
if parent and height then
local _, _, _, _, offset = self:GetPoint()
height = (parent.content.height or 0) + (offset or 0) or height
self.frame.height = (parent.content.height or 0) + (offset or 0)
end
--self.frame:SetHeight(height)
local content = self.content local content = self.content
local contentheight = height - (self.borderoffset + 23) local contentheight = height - (self.borderoffset + 23)
if contentheight < 0 then if contentheight < 0 then
@@ -9,9 +9,8 @@ if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs -- Lua APIs
local next, pairs, ipairs, assert, type = next, pairs, ipairs, assert, type local next, pairs, ipairs, assert, type = next, pairs, ipairs, assert, type
local math_min, math_max, floor = math.min, math.max, floor local math_min, math_max, floor = math.min, math.max, floor
local select, tremove, unpack, tconcat = select, table.remove, unpack, table.concat local tremove, unpack, tconcat, getn = table.remove, unpack, table.concat, getn
local tgetn = table.getn local format, split = string.format, string.split
local strfmt = string.format
-- WoW APIs -- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent local CreateFrame, UIParent = CreateFrame, UIParent
@@ -168,12 +167,7 @@ local function FirstFrameUpdate()
end end
local function BuildUniqueValue(...) local function BuildUniqueValue(...)
local n = tgetn(arg) return tconcat(arg, "\001", 1, arg.n)
if n == 1 then
return arg[1]
else
return (unpack(arg)).."\001"..BuildUniqueValue(select(2, unpack(arg)))
end
end end
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
@@ -189,7 +183,7 @@ end
local function Button_OnClick() local function Button_OnClick()
local self = this.obj local self = this.obj
self:Fire("OnClick", 2, this.uniquevalue, this.selected) self:Fire("OnClick", this.uniquevalue, this.selected)
if not this.selected then if not this.selected then
self:SetSelected(this.uniquevalue) self:SetSelected(this.uniquevalue)
this.selected = true this.selected = true
@@ -209,12 +203,12 @@ end
local function Button_OnEnter() local function Button_OnEnter()
local self = this.obj local self = this.obj
self:Fire("OnButtonEnter", 2, this.uniquevalue, this) self:Fire("OnButtonEnter", this.uniquevalue, this)
if self.enabletooltips then if self.enabletooltips then
GameTooltip:SetOwner(this, "ANCHOR_NONE") GameTooltip:SetOwner(this, "ANCHOR_NONE")
GameTooltip:SetPoint("LEFT",this,"RIGHT") GameTooltip:SetPoint("LEFT",this,"RIGHT")
GameTooltip:SetText(this.text:GetText() or "", 1, .82, 0, true) GameTooltip:SetText(this.text:GetText() or "", 1, .82, 0, 1)
GameTooltip:Show() GameTooltip:Show()
end end
@@ -222,7 +216,7 @@ end
local function Button_OnLeave() local function Button_OnLeave()
local self = this.obj local self = this.obj
self:Fire("OnButtonLeave", 2, this.uniquevalue, this) self:Fire("OnButtonLeave", this.uniquevalue, this)
if self.enabletooltips then if self.enabletooltips then
GameTooltip:Hide() GameTooltip:Hide()
@@ -233,7 +227,7 @@ local function OnScrollValueChanged()
if this.obj.noupdate then return end if this.obj.noupdate then return end
local self = this.obj local self = this.obj
local status = self.status or self.localstatus local status = self.status or self.localstatus
status.scrollvalue = floor(arg1 + 0.5) status.scrollvalue = arg1
self:RefreshTree() self:RefreshTree()
AceGUI:ClearFocus() AceGUI:ClearFocus()
end end
@@ -271,19 +265,19 @@ end
local function Dragger_OnMouseUp() local function Dragger_OnMouseUp()
local treeframe = this:GetParent() local treeframe = this:GetParent()
local self = treeframe.obj local self = treeframe.obj
local this = treeframe:GetParent() local frame = treeframe:GetParent()
treeframe:StopMovingOrSizing() treeframe:StopMovingOrSizing()
--treeframe:SetScript("OnUpdate", nil) --treeframe:SetScript("OnUpdate", nil)
treeframe:SetUserPlaced(false) treeframe:SetUserPlaced(false)
--Without this :GetHeight will get stuck on the current height, causing the tree contents to not resize --Without this :GetHeight will get stuck on the current height, causing the tree contents to not resize
treeframe:SetHeight(0) treeframe:SetHeight(0)
treeframe:SetPoint("TOPLEFT", this, "TOPLEFT",0,0) treeframe:SetPoint("TOPLEFT", frame, "TOPLEFT",0,0)
treeframe:SetPoint("BOTTOMLEFT", this, "BOTTOMLEFT",0,0) treeframe:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT",0,0)
local status = self.status or self.localstatus local status = self.status or self.localstatus
status.treewidth = treeframe:GetWidth() status.treewidth = treeframe:GetWidth()
treeframe.obj:Fire("OnTreeResize", 1, treeframe:GetWidth()) treeframe.obj:Fire("OnTreeResize",treeframe:GetWidth())
-- recalculate the content width -- recalculate the content width
treeframe.obj:OnWidthSet(status.fullwidth) treeframe.obj:OnWidthSet(status.fullwidth)
-- update the layout of the content -- update the layout of the content
@@ -297,7 +291,6 @@ local methods = {
["OnAcquire"] = function(self) ["OnAcquire"] = function(self)
self:SetTreeWidth(DEFAULT_TREE_WIDTH, DEFAULT_TREE_SIZABLE) self:SetTreeWidth(DEFAULT_TREE_WIDTH, DEFAULT_TREE_SIZABLE)
self:EnableButtonTooltips(true) self:EnableButtonTooltips(true)
self.frame:SetScript("OnUpdate", FirstFrameUpdate)
end, end,
["OnRelease"] = function(self) ["OnRelease"] = function(self)
@@ -322,36 +315,38 @@ local methods = {
["CreateButton"] = function(self) ["CreateButton"] = function(self)
local num = AceGUI:GetNextWidgetNum("TreeGroupButton") local num = AceGUI:GetNextWidgetNum("TreeGroupButton")
local button = CreateFrame("Button", format("AceGUI30TreeButton%d", num), self.treeframe)
local button = CreateFrame("Button", strfmt("AceGUI30TreeButton%d", num), self.treeframe)
button.obj = self button.obj = self
button:SetWidth(DEFAULT_TREE_WIDTH)
button:SetWidth(175)
button:SetHeight(18) button:SetHeight(18)
local toggle = CreateFrame("Button", "$parentToggle", button) local toggle = CreateFrame("Button", nil, button)
toggle:SetWidth(14) toggle:SetWidth(14)
toggle:SetHeight(14) toggle:SetHeight(14)
toggle:ClearAllPoints()
toggle:SetPoint("TOPRIGHT", button, "TOPRIGHT", -6, -1) toggle:SetPoint("TOPRIGHT", button, "TOPRIGHT", -6, -1)
toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP") toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP")
toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN") toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN")
toggle:SetHighlightTexture("Interface\Buttons\UI-PlusButton-Hilight", "ADD") toggle:SetHighlightTexture("Interface\Buttons\UI-PlusButton-Hilight", "ADD")
toggle:SetScript("OnClick", Button_OnClick)
button.toggle = toggle button.toggle = toggle
toggle.obj = button
local text = button:CreateFontString() local text = button:CreateFontString()
button.text = text
text:SetFontObject(GameFontNormal) text:SetFontObject(GameFontNormal)
button:SetHighlightFontObject(GameFontHighlight) text:SetPoint("RIGHT", toggle, "LEFT", -2, 0)
text:SetPoint("RIGHT", toggle, "LEFT", -2, 0);
text:SetJustifyH("LEFT") text:SetJustifyH("LEFT")
button:SetHighlightFontObject(GameFontHighlight)
button.text = text
local highlight = button:CreateTexture(nil, "HIGHLIGHT"); local highlight = button:CreateTexture(nil, "HIGHLIGHT")
button.highlight = highlight
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight")
highlight:SetBlendMode("ADD")
highlight:SetVertexColor(.196, .388, .8);
highlight:ClearAllPoints()
highlight:SetPoint("TOPLEFT", 0, 1) highlight:SetPoint("TOPLEFT", 0, 1)
highlight:SetPoint("BOTTOMRIGHT", 0, 1) highlight:SetPoint("BOTTOMRIGHT", 0, 1)
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestLogTitleHighlight")
highlight:SetBlendMode("ADD")
highlight:SetVertexColor(.196, .388, .8)
button.highlight = highlight
local icon = button:CreateTexture(nil, "OVERLAY") local icon = button:CreateTexture(nil, "OVERLAY")
icon:SetWidth(14) icon:SetWidth(14)
@@ -445,7 +440,7 @@ local methods = {
self:BuildLevel(tree, 1) self:BuildLevel(tree, 1)
local numlines = tgetn(lines) local numlines = getn(lines)
local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18)) local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18))
if maxlines <= 0 then return end if maxlines <= 0 then return end
@@ -529,13 +524,14 @@ local methods = {
button:Show() button:Show()
buttonnum = buttonnum + 1 buttonnum = buttonnum + 1
end end
end, end,
["SetSelected"] = function(self, value) ["SetSelected"] = function(self, value)
local status = self.status or self.localstatus local status = self.status or self.localstatus
if status.selected ~= value then if status.selected ~= value then
status.selected = value status.selected = value
self:Fire("OnGroupSelected", 1, value) self:Fire("OnGroupSelected", value)
end end
end, end,
@@ -548,7 +544,7 @@ local methods = {
end end
status.selected = uniquevalue status.selected = uniquevalue
self:RefreshTree(true) self:RefreshTree(true)
self:Fire("OnGroupSelected", 1, uniquevalue) self:Fire("OnGroupSelected", uniquevalue)
end, end,
["SelectByPath"] = function(self, ...) ["SelectByPath"] = function(self, ...)
@@ -556,7 +552,7 @@ local methods = {
end, end,
["SelectByValue"] = function(self, uniquevalue) ["SelectByValue"] = function(self, uniquevalue)
self:Select(uniquevalue, strsplit("\001", uniquevalue)) self:Select(uniquevalue, split("\001", uniquevalue))
end, end,
["ShowScroll"] = function(self, show) ["ShowScroll"] = function(self, show)
@@ -598,6 +594,14 @@ local methods = {
end, end,
["OnHeightSet"] = function(self, height) ["OnHeightSet"] = function(self, height)
local parent = self.parent
if parent and height then
local _, _, _, _, offset = self:GetPoint()
height = (parent.content.height or 0) + (offset or 0) or height
self.frame.height = (parent.content.height or 0) + (offset or 0)
end
self.treeframe:SetHeight(height)
local content = self.content local content = self.content
local contentheight = height - 20 local contentheight = height - 20
if contentheight < 0 then if contentheight < 0 then
@@ -666,7 +670,6 @@ local function Constructor()
local treeframe = CreateFrame("Frame", nil, frame) local treeframe = CreateFrame("Frame", nil, frame)
treeframe:SetPoint("TOPLEFT", 0, 0) treeframe:SetPoint("TOPLEFT", 0, 0)
treeframe:SetPoint("BOTTOMLEFT", 0, 0)
treeframe:SetWidth(DEFAULT_TREE_WIDTH) treeframe:SetWidth(DEFAULT_TREE_WIDTH)
treeframe:EnableMouseWheel(true) treeframe:EnableMouseWheel(true)
treeframe:SetBackdrop(PaneBackdrop) treeframe:SetBackdrop(PaneBackdrop)
@@ -690,7 +693,7 @@ local function Constructor()
dragger:SetScript("OnMouseDown", Dragger_OnMouseDown) dragger:SetScript("OnMouseDown", Dragger_OnMouseDown)
dragger:SetScript("OnMouseUp", Dragger_OnMouseUp) dragger:SetScript("OnMouseUp", Dragger_OnMouseUp)
local scrollbar = CreateFrame("Slider", strfmt("AceConfigDialogTreeGroup%dScrollBar", num), treeframe, "UIPanelScrollBarTemplate") local scrollbar = CreateFrame("Slider", format("AceConfigDialogTreeGroup%dScrollBar", num), treeframe, "UIPanelScrollBarTemplate")
scrollbar:SetScript("OnValueChanged", nil) scrollbar:SetScript("OnValueChanged", nil)
scrollbar:SetPoint("TOPRIGHT", -10, -26) scrollbar:SetPoint("TOPRIGHT", -10, -26)
scrollbar:SetPoint("BOTTOMRIGHT", -10, 26) scrollbar:SetPoint("BOTTOMRIGHT", -10, 26)
@@ -714,7 +717,7 @@ local function Constructor()
--Container Support --Container Support
local content = CreateFrame("Frame", nil, border) local content = CreateFrame("Frame", nil, border)
content:SetPoint("TOPLEFT", 10, -10) content:SetPoint("TOPLEFT", 10, -10)
content:SetPoint("BOTTOMRIGHT", -10, 10) --content:SetPoint("BOTTOMRIGHT", -10, 10)
local widget = { local widget = {
frame = frame, frame = frame,
@@ -21,7 +21,11 @@ local CreateFrame, UIParent = CreateFrame, UIParent
]] ]]
do do
local Type = "Window" local Type = "Window"
local Version = 4 local Version = 5
local function frameOnShow()
this.obj:Fire("OnShow")
end
local function frameOnClose() local function frameOnClose()
this.obj:Fire("OnClose") this.obj:Fire("OnClose")
@@ -180,6 +184,7 @@ do
frame:SetFrameStrata("FULLSCREEN_DIALOG") frame:SetFrameStrata("FULLSCREEN_DIALOG")
frame:SetScript("OnMouseDown", frameOnMouseDown) frame:SetScript("OnMouseDown", frameOnMouseDown)
frame:SetScript("OnShow",frameOnShow)
frame:SetScript("OnHide",frameOnClose) frame:SetScript("OnHide",frameOnClose)
frame:SetMinResize(240,240) frame:SetMinResize(240,240)
frame:SetToplevel(true) frame:SetToplevel(true)
@@ -6,23 +6,20 @@ local Type, Version = "Button", 23
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
local AceCore = LibStub("AceCore-3.0")
-- Lua APIs -- Lua APIs
local pairs = pairs local pairs = pairs
-- WoW APIs -- WoW APIs
local _G = AceCore._G local _G = _G
local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
Scripts Scripts
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
-- arg1 is the button for OnClick event
local function Button_OnClick() local function Button_OnClick()
AceGUI:ClearFocus() AceGUI:ClearFocus()
PlaySound("igMainMenuOption") PlaySound("igMainMenuOption")
this.obj:Fire("OnClick", 1, arg1) this.obj:Fire("OnClick", arg1)
end end
local function Control_OnEnter() local function Control_OnEnter()
@@ -7,6 +7,7 @@ if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs -- Lua APIs
local pairs = pairs local pairs = pairs
local unpack = unpack
-- WoW APIs -- WoW APIs
local PlaySound = PlaySound local PlaySound = PlaySound
@@ -55,7 +56,6 @@ local function CheckBox_OnMouseDown()
end end
local function CheckBox_OnMouseUp() local function CheckBox_OnMouseUp()
local self = this.obj local self = this.obj
if not self.disabled then if not self.disabled then
self:ToggleChecked() self:ToggleChecked()
@@ -66,7 +66,7 @@ local function CheckBox_OnMouseUp()
PlaySound("igMainMenuOptionCheckBoxOff") PlaySound("igMainMenuOptionCheckBoxOff")
end end
self:Fire("OnValueChanged", 1, self.checked) self:Fire("OnValueChanged", self.checked)
AlignImage(self) AlignImage(self)
end end
end end
@@ -173,7 +173,6 @@ local methods = {
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight") highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
highlight:SetTexCoord(0, 1, 0, 1) highlight:SetTexCoord(0, 1, 0, 1)
end end
checkbg:SetHeight(size) checkbg:SetHeight(size)
checkbg:SetWidth(size) checkbg:SetWidth(size)
end, end,
@@ -223,13 +222,14 @@ local methods = {
end end
end, end,
["SetImage"] = function(self, path, a1,a2,a3,a4,a5,a6,a7,a8) ["SetImage"] = function(self, path, ...)
local image = self.image local image = self.image
image:SetTexture(path) image:SetTexture(path)
if image:GetTexture() then if image:GetTexture() then
if a4 or a8 then local n = arg.n
image:SetTexCoord(a1,a2,a3,a4,a5,a6,a7,a8) if n == 4 or n == 8 then
image:SetTexCoord(unpack(arg))
else else
image:SetTexCoord(0, 1, 0, 1) image:SetTexCoord(0, 1, 0, 1)
end end
@@ -1,7 +1,7 @@
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
ColorPicker Widget ColorPicker Widget
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
local Type, Version = "ColorPicker", 23 local Type, Version = "ColorPicker", 22
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
@@ -25,12 +25,12 @@ local function ColorCallback(self, r, g, b, a, isAlpha)
self:SetColor(r, g, b, a) self:SetColor(r, g, b, a)
if ColorPickerFrame:IsVisible() then if ColorPickerFrame:IsVisible() then
--colorpicker is still open --colorpicker is still open
self:Fire("OnValueChanged", 4, r, g, b, a) self:Fire("OnValueChanged", r, g, b, a)
else else
--colorpicker is closed, color callback is first, ignore it, --colorpicker is closed, color callback is first, ignore it,
--alpha callback is the final call after it closes so confirm now --alpha callback is the final call after it closes so confirm now
if isAlpha then if isAlpha then
self:Fire("OnValueConfirmed", 4, r, g, b, a) self:Fire("OnValueConfirmed", r, g, b, a)
end end
end end
end end
@@ -51,6 +51,7 @@ local function ColorSwatch_OnClick()
local self = this.obj local self = this.obj
if not self.disabled then if not self.disabled then
ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG") ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG")
ColorPickerFrame:SetFrameLevel(this:GetFrameLevel() + 10)
ColorPickerFrame:SetClampedToScreen(true) ColorPickerFrame:SetClampedToScreen(true)
ColorPickerFrame.func = function() ColorPickerFrame.func = function()
@@ -1,25 +1,32 @@
--[[ $Id: AceGUIWidget-DropDown-Items.lua 1137 2016-05-15 10:57:36Z nevcairiel $ ]]-- --[[ $Id: AceGUIWidget-DropDown-Items.lua 996 2010-12-01 18:34:17Z nevcairiel $ ]]--
local AceGUI = LibStub("AceGUI-3.0") local AceGUI = LibStub("AceGUI-3.0")
local IsLegion = false
-- Lua APIs -- Lua APIs
local assert = assert local assert, unpack = assert, unpack
local tgetn = table.getn
-- WoW APIs -- WoW APIs
local PlaySound = PlaySound local PlaySound = PlaySound
local CreateFrame = CreateFrame local CreateFrame = CreateFrame
local function fixlevels(parent, ...) local function fixlevels(parent, ...)
local i = 1 local child
local child = arg[i] local level = parent:GetFrameLevel() + 1
while child do
child:SetFrameLevel(parent:GetFrameLevel()+1) for i = 1, arg.n do
fixlevels(child, child:GetChildren())
i = i + 1
child = arg[i] child = arg[i]
child:SetFrameLevel(level)
fixlevels(child)
end
end
local function fixstrata(strata, parent, ...)
local child
parent:SetFrameStrata(strata)
for i = 1, arg.n do
child = arg[i]
fixstrata(strata, child)
end end
end end
@@ -83,9 +90,8 @@ function ItemBase.SetPullout(self, pullout)
self.pullout = pullout self.pullout = pullout
self.frame:SetParent(nil) self.frame:SetParent(nil)
local itemFrame = pullout.itemFrame self.frame:SetParent(pullout.itemFrame)
self.frame:SetParent(itemFrame) self.parent = pullout.itemFrame
self.parent = itemFrame
fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren()) fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren())
end end
@@ -100,8 +106,8 @@ function ItemBase.GetText(self)
end end
-- exported -- exported
function ItemBase.SetPoint(self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) function ItemBase.SetPoint(self, ...)
self.frame:SetPoint(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) self.frame:SetPoint(unpack(arg))
end end
-- exported -- exported
@@ -241,7 +247,7 @@ do
local widgetType = "Dropdown-Item-Header" local widgetType = "Dropdown-Item-Header"
local widgetVersion = 1 local widgetVersion = 1
local function OnEnter(this) local function OnEnter()
local self = this.obj local self = this.obj
self:Fire("OnEnter") self:Fire("OnEnter")
@@ -290,7 +296,7 @@ do
local widgetType = "Dropdown-Item-Execute" local widgetType = "Dropdown-Item-Execute"
local widgetVersion = 1 local widgetVersion = 1
local function Frame_OnClick(this, button) local function Frame_OnClick()
local self = this.obj local self = this.obj
if self.disabled then return end if self.disabled then return end
self:Fire("OnClick") self:Fire("OnClick")
@@ -341,7 +347,7 @@ do
PlaySound("igMainMenuOptionCheckBoxOff") PlaySound("igMainMenuOptionCheckBoxOff")
end end
UpdateToggle(self) UpdateToggle(self)
self:Fire("OnValueChanged", 1, self.value) self:Fire("OnValueChanged", self.value)
end end
-- exported -- exported
@@ -433,7 +439,7 @@ end
-- A single line to separate items -- A single line to separate items
do do
local widgetType = "Dropdown-Item-Separator" local widgetType = "Dropdown-Item-Separator"
local widgetVersion = 2 local widgetVersion = 1
-- exported, override -- exported, override
local function SetDisabled(self, disabled) local function SetDisabled(self, disabled)
@@ -449,7 +455,6 @@ do
local line = self.frame:CreateTexture(nil, "OVERLAY") local line = self.frame:CreateTexture(nil, "OVERLAY")
line:SetHeight(1) line:SetHeight(1)
line:SetTexture(.5, .5, .5) line:SetTexture(.5, .5, .5)
line:SetPoint("LEFT", self.frame, "LEFT", 10, 0) line:SetPoint("LEFT", self.frame, "LEFT", 10, 0)
line:SetPoint("RIGHT", self.frame, "RIGHT", -10, 0) line:SetPoint("RIGHT", self.frame, "RIGHT", -10, 0)
@@ -1,42 +1,39 @@
--[[ $Id: AceGUIWidget-DropDown.lua 1116 2014-10-12 08:15:46Z nevcairiel $ ]]-- --[[ $Id: AceGUIWidget-DropDown.lua 1116 2014-10-12 08:15:46Z nevcairiel $ ]]--
local AceGUI = LibStub("AceGUI-3.0") local AceGUI = LibStub("AceGUI-3.0")
local AceCore = LibStub("AceCore-3.0")
-- Lua APIs -- Lua APIs
local min, max, floor = math.min, math.max, math.floor local min, max, floor = math.min, math.max, math.floor
local pairs, ipairs, type = pairs, ipairs, type local pairs, ipairs, type = pairs, ipairs, type
local tsort, tinsert, tgetn, tsetn = table.sort, table.insert, table.getn, table.setn local tsort, tinsert, getn, setn = table.sort, table.insert, table.getn, table.setn
local format = string.format local format = string.format
-- WoW APIs -- WoW APIs
local PlaySound = PlaySound local PlaySound = PlaySound
local UIParent, CreateFrame = UIParent, CreateFrame local UIParent, CreateFrame = UIParent, CreateFrame
local _G = AceCore._G local _G = _G
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script -- List them here for Mikk's FindGlobals script
-- GLOBALS: CLOSE -- GLOBALS: CLOSE
local function fixlevels(parent, ...) local function fixlevels(parent, ...)
local i = 1 local child
local child = arg[i] local level = parent:GetFrameLevel() + 1
while child do
child:SetFrameLevel(parent:GetFrameLevel()+1) for i = 1, arg.n do
fixlevels(child, child:GetChildren())
i = i + 1
child = arg[i] child = arg[i]
child:SetFrameLevel(level)
fixlevels(child)
end end
end end
local function fixstrata(strata, parent, ...) local function fixstrata(strata, parent, ...)
local i = 1 local child
local child = arg[i]
parent:SetFrameStrata(strata) parent:SetFrameStrata(strata)
while child do
fixstrata(strata, child, child:GetChildren()) for i = 1, arg.n do
i = i + 1
child = arg[i] child = arg[i]
fixstrata(strata, child)
end end
end end
@@ -107,6 +104,7 @@ do
end end
child:ClearAllPoints() child:ClearAllPoints()
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset) child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
-- child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset)
status.offset = offset status.offset = offset
status.scrollvalue = value status.scrollvalue = value
end end
@@ -150,6 +148,7 @@ do
if value < 1000 then if value < 1000 then
child:ClearAllPoints() child:ClearAllPoints()
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset) child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
-- child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset)
status.offset = offset status.offset = offset
end end
end end
@@ -172,7 +171,7 @@ do
local function AddItem(self, item) local function AddItem(self, item)
tinsert(self.items, item) tinsert(self.items, item)
local h = tgetn(self.items) * 16 local h = getn(self.items) * 16
self.itemFrame:SetHeight(h) self.itemFrame:SetHeight(h)
self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement
@@ -223,7 +222,7 @@ do
AceGUI:Release(item) AceGUI:Release(item)
items[i] = nil items[i] = nil
end end
tsetn(items,0) setn(items, 0)
end end
-- exported -- exported
@@ -325,6 +324,7 @@ do
scrollFrame:SetWidth(defaultWidth - 12) scrollFrame:SetWidth(defaultWidth - 12)
scrollFrame:SetHeight(self.maxHeight - 24) scrollFrame:SetHeight(self.maxHeight - 24)
scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12) scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12)
-- scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12)
scrollFrame:EnableMouseWheel(true) scrollFrame:EnableMouseWheel(true)
scrollFrame:SetScript("OnMouseWheel", OnMouseWheel) scrollFrame:SetScript("OnMouseWheel", OnMouseWheel)
scrollFrame:SetScript("OnSizeChanged", OnSizeChanged) scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
@@ -333,6 +333,7 @@ do
itemFrame:SetWidth(defaultWidth - 12) itemFrame:SetWidth(defaultWidth - 12)
itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0) itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
-- itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0)
itemFrame:SetHeight(400) itemFrame:SetHeight(400)
itemFrame:SetToplevel(true) itemFrame:SetToplevel(true)
itemFrame:SetFrameStrata("FULLSCREEN_DIALOG") itemFrame:SetFrameStrata("FULLSCREEN_DIALOG")
@@ -436,20 +437,17 @@ do
self:SetText(text) self:SetText(text)
end end
local function OnItemValueChanged(this, event, _, checked) local function OnItemValueChanged(this, event, checked)
local self = this.userdata.obj local self = this.userdata.obj
if self.multiselect then if self.multiselect then
self:Fire("OnValueChanged", 2, this.userdata.value, checked) self:Fire("OnValueChanged", this.userdata.value, checked)
ShowMultiText(self) ShowMultiText(self)
else else
if checked then if checked then
self:SetValue(this.userdata.value) self:SetValue(this.userdata.value)
self:Fire("OnValueChanged", 1, this.userdata.value) self:Fire("OnValueChanged", this.userdata.value)
this:SetValue(false)
else else
self:SetValue(nil)
self:Fire("OnValueChanged", 1, nil)
this:SetValue(true) this:SetValue(true)
end end
if self.open then if self.open then
@@ -468,7 +466,6 @@ do
pullout:SetCallback("OnClose", OnPulloutClose) pullout:SetCallback("OnClose", OnPulloutClose)
pullout:SetCallback("OnOpen", OnPulloutOpen) pullout:SetCallback("OnOpen", OnPulloutOpen)
self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1) self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
local frame = self.pullout.frame
fixlevels(self.pullout.frame, self.pullout.frame:GetChildren()) fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())
self:SetHeight(44) self:SetHeight(44)
@@ -618,7 +615,7 @@ do
AddListItem(self, key, list[key], itemType) AddListItem(self, key, list[key], itemType)
sortlist[i] = nil sortlist[i] = nil
end end
tsetn(sortlist,0) setn(sortlist, 0)
else else
for i, key in ipairs(order) do for i, key in ipairs(order) do
AddListItem(self, key, list[key], itemType) AddListItem(self, key, list[key], itemType)
@@ -5,19 +5,29 @@ local Type, Version = "EditBox", 26
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
local AceCore = LibStub("AceCore-3.0")
local hooksecurefunc = AceCore.hooksecurefunc
local _G = AceCore._G
local GetCursorInfo = _G.GetCursorInfo
-- Lua APIs -- Lua APIs
local tostring, pairs = tostring, pairs local tostring, pairs = tostring, pairs
local gsub, sub = string.gsub, string.sub
-- WoW APIs -- WoW APIs
local PlaySound = PlaySound local PlaySound = PlaySound
local GetCursorInfo, ClearCursor, GetSpellInfo = GetCursorInfo, ClearCursor, GetSpellInfo local GetCursorInfo, ClearCursor, GetSpellName = GetCursorInfo, ClearCursor, GetSpellName
local CreateFrame, UIParent = CreateFrame, UIParent local CreateFrame, UIParent = CreateFrame, UIParent
local strlen = string.len local _G = _G
local GetContainerItemLink = GetContainerItemLink
local GetInventoryItemLink = GetInventoryItemLink
local GetLootSlotLink = GetLootSlotLink
local GetMerchantItemLink = GetMerchantItemLink
local GetQuestItemLink = GetQuestItemLink
local GetQuestLogItemLink = GetQuestLogItemLink
local GetSpellName = GetSpellName
local IsShiftKeyDown = IsShiftKeyDown
local IsSpellPassive = IsSpellPassive
local SpellBook_GetSpellID = SpellBook_GetSpellID
local BANK_CONTAINER = BANK_CONTAINER
local KEYRING_CONTAINER = KEYRING_CONTAINER
local MAX_SPELLS = MAX_SPELLS
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script -- List them here for Mikk's FindGlobals script
@@ -28,94 +38,104 @@ Support functions
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
if not AceGUIEditBoxInsertLink then if not AceGUIEditBoxInsertLink then
-- upgradeable hook -- upgradeable hook
hooksecurefunc("BankFrameItemButtonGeneric_OnClick", local orig_BankFrameItemButtonGeneric_OnClick = BankFrameItemButtonGeneric_OnClick
function(button) function BankFrameItemButtonGeneric_OnClick(button)
if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then
return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(BANK_CONTAINER, this:GetID())) return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(BANK_CONTAINER, this:GetID()))
end end
end) end
hooksecurefunc("ContainerFrameItemButton_OnClick",
function(button, ignoreModifiers) local orig_ContainerFrameItemButton_OnClick = ContainerFrameItemButton_OnClick
function ContainerFrameItemButton_OnClick(button, ignoreModifiers)
if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(this:GetParent():GetID(), this:GetID())) return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(this:GetParent():GetID(), this:GetID()))
end end
end) end
hooksecurefunc("KeyRingItemButton_OnClick", local orig_KeyRingItemButton_OnClick = KeyRingItemButton_OnClick
function(button) function KeyRingItemButton_OnClick(button)
if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then
return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(KEYRING_CONTAINER, this:GetID())) return _G.AceGUIEditBoxInsertLink(GetContainerItemLink(KEYRING_CONTAINER, this:GetID()))
end end
end) end
hooksecurefunc("LootFrameItem_OnClick",
function(button) local orig_LootFrameItem_OnClick = LootFrameItem_OnClick
function LootFrameItem_OnClick(button)
if button == "LeftButton" and IsShiftKeyDown() then if button == "LeftButton" and IsShiftKeyDown() then
return _G.AceGUIEditBoxInsertLink(GetLootSlotLink(this.slot)) return _G.AceGUIEditBoxInsertLink(GetLootSlotLink(this.slot))
end end
end) end
hooksecurefunc("SetItemRef",
function(link, text, button) local orig_SetItemRef = SetItemRef
function SetItemRef(link, text, button)
if IsShiftKeyDown() then if IsShiftKeyDown() then
if strsub(link,1,6) == "player" then if sub(link, 1, 6) == "player" then
local name = strsub(link,8) local name = sub(link, 8)
if name and (strlen(name) > 0) then if name and name ~= "" then
return _G.AceGUIEditBoxInsertLink(name) return _G.AceGUIEditBoxInsertLink(name)
end end
else else
return _G.AceGUIEditBoxInsertLink(text) return _G.AceGUIEditBoxInsertLink(text)
end end
end end
end) end
hooksecurefunc("MerchantItemButton_OnClick",
function(button, ignoreModifiers) local orig_MerchantItemButton_OnClick = MerchantItemButton_OnClick
function MerchantItemButton_OnClick(button, ignoreModifiers)
if MerchantFrame.selectedTab == 1 and button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then if MerchantFrame.selectedTab == 1 and button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
return _G.AceGUIEditBoxInsertLink(GetMerchantItemLink(this:GetID())) return _G.AceGUIEditBoxInsertLink(GetMerchantItemLink(this:GetID()))
end end
end) end
hooksecurefunc("PaperDollItemSlotButton_OnClick",
function(button, ignoreModifiers) local orig_PaperDollItemSlotButton_OnClick = PaperDollItemSlotButton_OnClick
function PaperDollItemSlotButton_OnClick(button, ignoreModifiers)
if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
return _G.AceGUIEditBoxInsertLink(GetInventoryItemLink("player", this:GetID())) return _G.AceGUIEditBoxInsertLink(GetInventoryItemLink("player", this:GetID()))
end end
end) end
hooksecurefunc("QuestItem_OnClick",
function() local orig_QuestItem_OnClick = QuestItem_OnClick
function QuestItem_OnClick()
if IsShiftKeyDown() and this.rewardType ~= "spell" then if IsShiftKeyDown() and this.rewardType ~= "spell" then
return _G.AceGUIEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID())) return _G.AceGUIEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID()))
end end
end) end
hooksecurefunc("QuestRewardItem_OnClick",
function() local orig_QuestRewardItem_OnClick = QuestRewardItem_OnClick
function QuestRewardItem_OnClick()
if IsShiftKeyDown() and this.rewardType ~= "spell" then if IsShiftKeyDown() and this.rewardType ~= "spell" then
return _G.AceGUIEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID())) return _G.AceGUIEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID()))
end end
end) end
hooksecurefunc("QuestLogTitleButton_OnClick",
function(button) local orig_QuestLogTitleButton_OnClick = QuestLogTitleButton_OnClick
function QuestLogTitleButton_OnClick(button)
if IsShiftKeyDown() and (not this.isHeader) then if IsShiftKeyDown() and (not this.isHeader) then
return _G.AceGUIEditBoxInsertLink(gsub(this:GetText(), " *(.*)", "%1")) return _G.AceGUIEditBoxInsertLink(gsub(this:GetText(), " *(.*)", "%1"))
end end
end) end
hooksecurefunc("QuestLogRewardItem_OnClick",
function() local orig_QuestLogRewardItem_OnClick = QuestLogRewardItem_OnClick
function QuestLogRewardItem_OnClick()
if IsShiftKeyDown() and this.rewardType ~= "spell" then if IsShiftKeyDown() and this.rewardType ~= "spell" then
return _G.AceGUIEditBoxInsertLink(GetQuestLogItemLink(this.type, this:GetID())) return _G.AceGUIEditBoxInsertLink(GetQuestLogItemLink(this.type, this:GetID()))
end end
end) end
hooksecurefunc("SpellButton_OnClick",
function(drag) local orig_SpellButton_OnClick = SpellButton_OnClick
function SpellButton_OnClick(drag)
local id = SpellBook_GetSpellID(this:GetID()) local id = SpellBook_GetSpellID(this:GetID())
if id <= MAX_SPELLS and (not drag) and IsShiftKeyDown() then if id <= MAX_SPELLS and (not drag) and IsShiftKeyDown() then
local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType) local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType)
if spellName and not IsSpellPassive(id, SpellBookFrame.bookType) then if spellName and not IsSpellPassive(id, SpellBookFrame.bookType) then
if subSpellName and (strlen(subSpellName) > 0) then if subSpellName and subSpellName ~= "" then
_G.AceGUIEditBoxInsertLink(spellName.."("..subSpellName..")"); _G.AceGUIEditBoxInsertLink(spellName.."("..subSpellName..")")
else else
_G.AceGUIEditBoxInsertLink(spellName); _G.AceGUIEditBoxInsertLink(spellName)
end
end end
end end
end end
end)
end end
function _G.AceGUIEditBoxInsertLink(text) function _G.AceGUIEditBoxInsertLink(text)
@@ -163,7 +183,7 @@ end
local function EditBox_OnEnterPressed() local function EditBox_OnEnterPressed()
local self = this.obj local self = this.obj
local value = this:GetText() local value = this:GetText()
local cancel = self:Fire("OnEnterPressed", 1, value) local cancel = self:Fire("OnEnterPressed", value)
if not cancel then if not cancel then
PlaySound("igMainMenuOptionCheckBoxOn") PlaySound("igMainMenuOptionCheckBoxOn")
HideButton(self) HideButton(self)
@@ -172,34 +192,36 @@ end
local function EditBox_OnReceiveDrag() local function EditBox_OnReceiveDrag()
if not GetCursorInfo then return end if not GetCursorInfo then return end
local self = this.obj local self = this.obj
local type, id, info = GetCursorInfo() local type, id, info = GetCursorInfo()
if type == "item" then if type == "item" then
self:SetText(info) self:SetText(info)
self:Fire("OnEnterPressed", 1, info) self:Fire("OnEnterPressed", info)
ClearCursor() ClearCursor()
elseif type == "spell" then elseif type == "spell" then
local spell, rank = GetSpellName(id, info) local name, rank = GetSpellName(id, info)
if rank ~= "" then spell = spell.."("..rank..")" end if rank ~= "" then
self:SetText(spell) name = name.."("..rank..")"
self:Fire("OnEnterPressed", 1, spell) end
self:SetText(name)
self:Fire("OnEnterPressed", name)
ClearCursor() ClearCursor()
elseif type == "macro" then elseif type == "macro" then
local name = GetMacroInfo(id) local name = GetMacroInfo(id)
self:SetText(name) self:SetText(name)
self:Fire("OnEnterPressed", 1, name) self:Fire("OnEnterPressed", name)
ClearCursor() ClearCursor()
end end
HideButton(self) HideButton(self)
AceGUI:ClearFocus() AceGUI:ClearFocus()
end end
local function EditBox_OnTextChanged() local function EditBox_OnTextChanged()
local self = this.obj local self = this.obj
local value = this:GetText() local value = this:GetText()
if tostring(value) ~= tostring(self.lasttext) then if tostring(value) ~= tostring(self.lasttext) then
self:Fire("OnTextChanged", 1, value) self:Fire("OnTextChanged", value)
self.lasttext = value self.lasttext = value
ShowButton(self) ShowButton(self)
end end
@@ -217,7 +239,7 @@ end
local function Button_OnClick() local function Button_OnClick()
local editbox = this.obj.editbox local editbox = this.obj.editbox
editbox:ClearFocus() editbox:ClearFocus()
this = editbox -- Ace3v: this is kinda hack here this = editbox
EditBox_OnEnterPressed() EditBox_OnEnterPressed()
end end
@@ -256,7 +278,7 @@ local methods = {
["SetText"] = function(self, text) ["SetText"] = function(self, text)
self.lasttext = text or "" self.lasttext = text or ""
self.editbox:SetText(text or "") self.editbox:SetText(text or "")
self.editbox:HighlightText(0) EditBoxSetCursorPosition(self.editbox, 0)
HideButton(self) HideButton(self)
end, end,
@@ -6,7 +6,7 @@ local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs -- Lua APIs
local pairs, print = pairs, print local pairs, print, unpack = pairs, print, unpack
-- WoW APIs -- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent local CreateFrame, UIParent = CreateFrame, UIParent
@@ -23,7 +23,7 @@ local function Control_OnLeave()
end end
local function Button_OnClick() local function Button_OnClick()
this.obj:Fire("OnClick", 1, arg1) this.obj:Fire("OnClick", arg1)
AceGUI:ClearFocus() AceGUI:ClearFocus()
end end
@@ -53,13 +53,14 @@ local methods = {
end end
end, end,
["SetImage"] = function(self, path, a1,a2,a3,a4,a5,a6,a7,a8) ["SetImage"] = function(self, path, ...)
local image = self.image local image = self.image
image:SetTexture(path) image:SetTexture(path)
if image:GetTexture() then if image:GetTexture() then
if a4 or a8 then local n = arg.n
image:SetTexCoord(a1,a2,a3,a4,a5,a6,a7,a8) if n == 4 or n == 8 then
image:SetTexCoord(unpack(arg))
else else
image:SetTexCoord(0, 1, 0, 1) image:SetTexCoord(0, 1, 0, 1)
end end
@@ -131,7 +132,7 @@ local function Constructor()
widget[method] = func widget[method] = func
end end
widget.SetText = function(self,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) print("AceGUI-3.0-Icon: SetText is deprecated! Use SetLabel instead!"); self:SetLabel(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) end widget.SetText = widget.SetLabel
return AceGUI:RegisterAsWidget(widget) return AceGUI:RegisterAsWidget(widget)
end end
@@ -1,12 +1,12 @@
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
InteractiveLabel Widget InteractiveLabel Widget
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
local Type, Version = "InteractiveLabel", 20 local Type, Version = "InteractiveLabel", 21
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs -- Lua APIs
local pairs = pairs local pairs, unpack = pairs, unpack
-- WoW APIs -- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent local CreateFrame, UIParent = CreateFrame, UIParent
@@ -27,7 +27,7 @@ local function Control_OnLeave()
end end
local function Label_OnClick() local function Label_OnClick()
this.obj:Fire("OnClick", 1, arg1) this.obj:Fire("OnClick", arg1)
AceGUI:ClearFocus() AceGUI:ClearFocus()
end end
@@ -44,13 +44,14 @@ local methods = {
-- ["OnRelease"] = nil, -- ["OnRelease"] = nil,
["SetHighlight"] = function(self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) ["SetHighlight"] = function(self, ...)
self.highlight:SetTexture(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) self.highlight:SetTexture(unpack(arg))
end, end,
["SetHighlightTexCoord"] = function(self, a1,a2,a3,a4,a5,a6,a7,a8) ["SetHighlightTexCoord"] = function(self, ...)
if a4 or a8 then local c = arg.n
self.highlight:SetTexCoord(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) if c == 4 or c == 8 then
self.highlight:SetTexCoord(unpack(arg))
else else
self.highlight:SetTexCoord(0, 1, 0, 1) self.highlight:SetTexCoord(0, 1, 0, 1)
end end
@@ -38,10 +38,31 @@ local function Keybinding_OnHide()
self.waitingForKey = nil self.waitingForKey = nil
end end
local function Keybinding_OnClick()
if arg1 == "LeftButton" or arg1 == "RightButton" then
local self = this.obj
if self.waitingForKey then
this:EnableKeyboard(false)
this:EnableMouseWheel(false)
self.msgframe:Hide()
this:UnlockHighlight()
self.waitingForKey = nil
else
this:EnableKeyboard(true)
this:EnableMouseWheel(true)
self.msgframe:Show()
this:LockHighlight()
self.waitingForKey = true
end
end
AceGUI:ClearFocus()
end
local ignoreKeys = { local ignoreKeys = {
["BUTTON1"] = true, ["BUTTON2"] = true, ["BUTTON1"] = true, ["BUTTON2"] = true,
["UNKNOWN"] = true, ["UNKNOWN"] = true,
["SHIFT"] = true, ["CTRL"] = true, ["ALT"] = true, ["LSHIFT"] = true, ["LCTRL"] = true, ["LALT"] = true,
["RSHIFT"] = true, ["RCTRL"] = true, ["RALT"] = true,
} }
local function Keybinding_OnKeyDown() local function Keybinding_OnKeyDown()
local self = this.obj local self = this.obj
@@ -70,23 +91,14 @@ local function Keybinding_OnKeyDown()
if not self.disabled then if not self.disabled then
self:SetKey(keyPressed) self:SetKey(keyPressed)
self:Fire("OnKeyChanged", 1, keyPressed) self:Fire("OnKeyChanged", keyPressed)
end end
end end
end end
local function Keybinding_OnMouseDown()
getglobal(this:GetName().."Left"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
getglobal(this:GetName().."Middle"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
getglobal(this:GetName().."Right"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
end
local function Keybinding_OnMouseUp() local function Keybinding_OnMouseUp()
getglobal(this:GetName().."Left"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
getglobal(this:GetName().."Middle"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
getglobal(this:GetName().."Right"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
local self = this.obj
if MouseIsOver(this) and not self.disabled then if MouseIsOver(this) and not self.disabled then
local self = this.obj
if self.waitingForKey then if self.waitingForKey then
if arg1 ~= "LeftButton" and arg1 ~= "RightButton" then if arg1 ~= "LeftButton" and arg1 ~= "RightButton" then
Keybinding_OnKeyDown() Keybinding_OnKeyDown()
@@ -107,6 +119,19 @@ local function Keybinding_OnMouseUp()
AceGUI:ClearFocus() AceGUI:ClearFocus()
end end
local function Keybinding_OnMouseDown()
if arg1 == "LeftButton" or arg1 == "RightButton" then
return
elseif arg1 == "MiddleButton" then
arg1 = "BUTTON3"
elseif arg1 == "Button4" then
arg1 = "BUTTON4"
elseif arg1 == "Button5" then
arg1 = "BUTTON5"
end
Keybinding_OnKeyDown()
end
local function Keybinding_OnMouseWheel() local function Keybinding_OnMouseWheel()
if arg1 >= 0 then if arg1 >= 0 then
arg1 = "MOUSEWHEELUP" arg1 = "MOUSEWHEELUP"
@@ -198,14 +223,13 @@ local function Constructor()
button:EnableMouse(true) button:EnableMouse(true)
button:EnableMouseWheel(false) button:EnableMouseWheel(false)
button:RegisterForClicks("AnyDown")
button:SetScript("OnEnter", Control_OnEnter) button:SetScript("OnEnter", Control_OnEnter)
button:SetScript("OnLeave", Control_OnLeave) button:SetScript("OnLeave", Control_OnLeave)
-- button:SetScript("OnClick", Keybinding_OnClick)
button:SetScript("OnKeyDown", Keybinding_OnKeyDown)
button:RegisterForClicks("AnyDown","AnyUp")
-- Ace3v: RegisterForClicks means OnClick will not be triggered, so use OnKeyDown and OnKeyUp
button:SetScript("OnMouseDown", Keybinding_OnMouseDown)
button:SetScript("OnMouseUp", Keybinding_OnMouseUp) button:SetScript("OnMouseUp", Keybinding_OnMouseUp)
button:SetScript("OnKeyDown", Keybinding_OnKeyDown)
button:SetScript("OnMouseDown", Keybinding_OnMouseDown)
button:SetScript("OnMouseWheel", Keybinding_OnMouseWheel) button:SetScript("OnMouseWheel", Keybinding_OnMouseWheel)
button:SetScript("OnHide", Keybinding_OnHide) button:SetScript("OnHide", Keybinding_OnHide)
button:SetPoint("BOTTOMLEFT", 0, 0) button:SetPoint("BOTTOMLEFT", 0, 0)
@@ -2,12 +2,12 @@
Label Widget Label Widget
Displays text and optionally an icon. Displays text and optionally an icon.
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
local Type, Version = "Label", 23 local Type, Version = "Label", 24
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs -- Lua APIs
local max, pairs = math.max, pairs local max, pairs, unpack = math.max, pairs, unpack
-- WoW APIs -- WoW APIs
local CreateFrame, UIParent = CreateFrame, UIParent local CreateFrame, UIParent = CreateFrame, UIParent
@@ -78,6 +78,8 @@ local methods = {
self:SetImageSize(16, 16) self:SetImageSize(16, 16)
self:SetColor() self:SetColor()
self:SetFontObject() self:SetFontObject()
self:SetJustifyH("LEFT")
self:SetJustifyV("TOP")
-- reset the flag -- reset the flag
self.resizing = nil self.resizing = nil
@@ -103,14 +105,15 @@ local methods = {
self.label:SetVertexColor(r, g, b) self.label:SetVertexColor(r, g, b)
end, end,
["SetImage"] = function(self, path, a1,a2,a3,a4,a5,a6,a7,a8) ["SetImage"] = function(self, path, ...)
local image = self.image local image = self.image
image:SetTexture(path) image:SetTexture(path)
if image:GetTexture() then if image:GetTexture() then
self.imageshown = true self.imageshown = true
if a4 or a8 then local n = arg.n
image:SetTexCoord(a1,a2,a3,a4,a5,a6,a7,a8) if n == 4 or n == 8 then
image:SetTexCoord(unpack(arg))
else else
image:SetTexCoord(0, 1, 0, 1) image:SetTexCoord(0, 1, 0, 1)
end end
@@ -133,6 +136,14 @@ local methods = {
self.image:SetHeight(height) self.image:SetHeight(height)
UpdateImageAnchor(self) UpdateImageAnchor(self)
end, end,
["SetJustifyH"] = function(self, justifyH)
self.label:SetJustifyH(justifyH)
end,
["SetJustifyV"] = function(self, justifyV)
self.label:SetJustifyV(justifyV)
end,
} }
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
@@ -143,9 +154,6 @@ local function Constructor()
frame:Hide() frame:Hide()
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall") local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall")
label:SetJustifyH("LEFT")
label:SetJustifyV("TOP")
local image = frame:CreateTexture(nil, "BACKGROUND") local image = frame:CreateTexture(nil, "BACKGROUND")
-- create widget -- create widget
@@ -2,17 +2,28 @@ local Type, Version = "MultiLineEditBox", 28
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
local AceCore = LibStub("AceCore-3.0")
local hooksecurefunc = AceCore.hooksecurefunc
-- Lua APIs -- Lua APIs
local strfmt = string.format
local pairs = pairs local pairs = pairs
local format, gsub, sub = string.format, string.gsub, string.sub
-- WoW APIs -- WoW APIs
local CursorHasItem, ClearCursor = CursorHasItem, ClearCursor local GetCursorInfo, GetSpellName, ClearCursor = GetCursorInfo, GetSpellName, ClearCursor
local CreateFrame, UIParent = CreateFrame, UIParent local CreateFrame, UIParent = CreateFrame, UIParent
local _G = AceCore._G local _G = _G
local GetContainerItemLink = GetContainerItemLink
local GetInventoryItemLink = GetInventoryItemLink
local GetLootSlotLink = GetLootSlotLink
local GetMerchantItemLink = GetMerchantItemLink
local GetQuestItemLink = GetQuestItemLink
local GetQuestLogItemLink = GetQuestLogItemLink
local GetSpellName = GetSpellName
local IsShiftKeyDown = IsShiftKeyDown
local IsSpellPassive = IsSpellPassive
local SpellBook_GetSpellID = SpellBook_GetSpellID
local BANK_CONTAINER = BANK_CONTAINER
local KEYRING_CONTAINER = KEYRING_CONTAINER
local MAX_SPELLS = MAX_SPELLS
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script -- List them here for Mikk's FindGlobals script
@@ -21,101 +32,112 @@ local _G = AceCore._G
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
Support functions Support functions
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
if not AceGUIMultiLineEditBoxInsertLink then if not AceGUIMultiLineEditBoxInsertLink then
-- upgradeable hook -- upgradeable hook
hooksecurefunc("BankFrameItemButtonGeneric_OnClick", local orig_BankFrameItemButtonGeneric_OnClick = BankFrameItemButtonGeneric_OnClick
function(button) function BankFrameItemButtonGeneric_OnClick(button)
if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then
return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(BANK_CONTAINER, this:GetID())) return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(BANK_CONTAINER, this:GetID()))
end end
end) end
hooksecurefunc("ContainerFrameItemButton_OnClick",
function(button, ignoreModifiers) local orig_ContainerFrameItemButton_OnClick = ContainerFrameItemButton_OnClick
function ContainerFrameItemButton_OnClick(button, ignoreModifiers)
if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(this:GetParent():GetID(), this:GetID())) return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(this:GetParent():GetID(), this:GetID()))
end end
end) end
hooksecurefunc("KeyRingItemButton_OnClick", local orig_KeyRingItemButton_OnClick = KeyRingItemButton_OnClick
function(button) function KeyRingItemButton_OnClick(button)
if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then if button == "LeftButton" and IsShiftKeyDown() and not this.isBag then
return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(KEYRING_CONTAINER, this:GetID())) return _G.AceGUIMultiLineEditBoxInsertLink(GetContainerItemLink(KEYRING_CONTAINER, this:GetID()))
end end
end) end
hooksecurefunc("LootFrameItem_OnClick",
function(button) local orig_LootFrameItem_OnClick = LootFrameItem_OnClick
function LootFrameItem_OnClick(button)
if button == "LeftButton" and IsShiftKeyDown() then if button == "LeftButton" and IsShiftKeyDown() then
return _G.AceGUIMultiLineEditBoxInsertLink(GetLootSlotLink(this.slot)) return _G.AceGUIMultiLineEditBoxInsertLink(GetLootSlotLink(this.slot))
end end
end) end
hooksecurefunc("SetItemRef",
function(link, text, button) local orig_SetItemRef = SetItemRef
function SetItemRef(link, text, button)
if IsShiftKeyDown() then if IsShiftKeyDown() then
if strsub(link,1,6) == "player" then if sub(link, 1, 6) == "player" then
local name = strsub(link,8) local name = sub(link, 8)
if name and (strlen(name) > 0) then if name and name ~= "" then
return _G.AceGUIMultiLineEditBoxInsertLink(name) return _G.AceGUIMultiLineEditBoxInsertLink(name)
end end
else else
return _G.AceGUIMultiLineEditBoxInsertLink(text) return _G.AceGUIMultiLineEditBoxInsertLink(text)
end end
end end
end) end
hooksecurefunc("MerchantItemButton_OnClick",
function(button, ignoreModifiers) local orig_MerchantItemButton_OnClick = MerchantItemButton_OnClick
function MerchantItemButton_OnClick(button, ignoreModifiers)
if MerchantFrame.selectedTab == 1 and button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then if MerchantFrame.selectedTab == 1 and button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
return _G.AceGUIMultiLineEditBoxInsertLink(GetMerchantItemLink(this:GetID())) return _G.AceGUIMultiLineEditBoxInsertLink(GetMerchantItemLink(this:GetID()))
end end
end) end
hooksecurefunc("PaperDollItemSlotButton_OnClick",
function(button, ignoreModifiers) local orig_PaperDollItemSlotButton_OnClick = PaperDollItemSlotButton_OnClick
function PaperDollItemSlotButton_OnClick(button, ignoreModifiers)
if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then if button == "LeftButton" and IsShiftKeyDown() and not ignoreModifiers then
return _G.AceGUIMultiLineEditBoxInsertLink(GetInventoryItemLink("player", this:GetID())) return _G.AceGUIMultiLineEditBoxInsertLink(GetInventoryItemLink("player", this:GetID()))
end end
end) end
hooksecurefunc("QuestItem_OnClick",
function() local orig_QuestItem_OnClick = QuestItem_OnClick
function QuestItem_OnClick()
if IsShiftKeyDown() and this.rewardType ~= "spell" then if IsShiftKeyDown() and this.rewardType ~= "spell" then
return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID())) return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID()))
end end
end) end
hooksecurefunc("QuestRewardItem_OnClick",
function() local orig_QuestRewardItem_OnClick = QuestRewardItem_OnClick
function QuestRewardItem_OnClick()
if IsShiftKeyDown() and this.rewardType ~= "spell" then if IsShiftKeyDown() and this.rewardType ~= "spell" then
return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID())) return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestItemLink(this.type, this:GetID()))
end end
end) end
hooksecurefunc("QuestLogTitleButton_OnClick",
function(button) local orig_QuestLogTitleButton_OnClick = QuestLogTitleButton_OnClick
function QuestLogTitleButton_OnClick(button)
if IsShiftKeyDown() and (not this.isHeader) then if IsShiftKeyDown() and (not this.isHeader) then
return _G.AceGUIMultiLineEditBoxInsertLink(gsub(this:GetText(), " *(.*)", "%1")) return _G.AceGUIMultiLineEditBoxInsertLink(gsub(this:GetText(), " *(.*)", "%1"))
end end
end) end
hooksecurefunc("QuestLogRewardItem_OnClick",
function() local orig_QuestLogRewardItem_OnClick = QuestLogRewardItem_OnClick
function QuestLogRewardItem_OnClick()
if IsShiftKeyDown() and this.rewardType ~= "spell" then if IsShiftKeyDown() and this.rewardType ~= "spell" then
return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestLogItemLink(this.type, this:GetID())) return _G.AceGUIMultiLineEditBoxInsertLink(GetQuestLogItemLink(this.type, this:GetID()))
end end
end) end
hooksecurefunc("SpellButton_OnClick",
function(drag) local orig_SpellButton_OnClick = SpellButton_OnClick
function SpellButton_OnClick(drag)
local id = SpellBook_GetSpellID(this:GetID()) local id = SpellBook_GetSpellID(this:GetID())
if id <= MAX_SPELLS and (not drag) and IsShiftKeyDown() then if id <= MAX_SPELLS and (not drag) and IsShiftKeyDown() then
local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType) local spellName, subSpellName = GetSpellName(id, SpellBookFrame.bookType)
if spellName and not IsSpellPassive(id, SpellBookFrame.bookType) then if spellName and not IsSpellPassive(id, SpellBookFrame.bookType) then
if subSpellName and (strlen(subSpellName) > 0) then if subSpellName and subSpellName ~= "" then
_G.AceGUIMultiLineEditBoxInsertLink(spellName.."("..subSpellName..")"); _G.AceGUIMultiLineEditBoxInsertLink(spellName.."("..subSpellName..")")
else else
_G.AceGUIMultiLineEditBoxInsertLink(spellName); _G.AceGUIMultiLineEditBoxInsertLink(spellName)
end
end end
end end
end end
end)
end end
function _G.AceGUIMultiLineEditBoxInsertLink(text) function _G.AceGUIMultiLineEditBoxInsertLink(text)
for i = 1, AceGUI:GetWidgetCount(Type) do for i = 1, AceGUI:GetWidgetCount(Type) do
local editbox = _G[strfmt("MultiLineEditBox%uEdit",i)] local editbox = _G[format("MultiLineEditBox%uEdit",i)]
if editbox and editbox:IsVisible() and editbox.hasfocus then if editbox and editbox:IsVisible() and editbox.hasfocus then
editbox:Insert(text) editbox:Insert(text)
return true return true
@@ -123,6 +145,7 @@ function _G.AceGUIMultiLineEditBoxInsertLink(text)
end end
end end
local function Layout(self) local function Layout(self)
self:SetHeight(self.numlines * 14 + (self.disablebutton and 19 or 41) + self.labelHeight) self:SetHeight(self.numlines * 14 + (self.disablebutton and 19 or 41) + self.labelHeight)
@@ -147,13 +170,12 @@ Scripts
local function OnClick() -- Button local function OnClick() -- Button
local self = this.obj local self = this.obj
self.editBox:ClearFocus() self.editBox:ClearFocus()
if not self:Fire("OnEnterPressed", 1, self.editBox:GetText()) then if not self:Fire("OnEnterPressed", self.editBox:GetText()) then
self.button:Disable() self.button:Disable()
end end
end end
local function OnCursorChanged() -- EditBox local function OnCursorChanged() -- EditBox
local self, y = this.obj.scrollFrame, -arg2 local self, y = this.obj.scrollFrame, -arg2
local offset = self:GetVerticalScroll() local offset = self:GetVerticalScroll()
if y < offset then if y < offset then
@@ -191,54 +213,61 @@ end
local function OnMouseUp() -- ScrollFrame local function OnMouseUp() -- ScrollFrame
local self = this.obj.editBox local self = this.obj.editBox
self:SetFocus() self:SetFocus()
local n = self:GetNumLetters() EditBoxSetCursorPosition(self, self:GetNumLetters())
self:HighlightText(n,n)
end end
local function OnReceiveDrag() -- EditBox / ScrollFrame local function OnReceiveDrag() -- EditBox / ScrollFrame
if not CursorHasItem() then return end if not GetCursorInfo then return end
local type, id, info = GetCursorInfo()
if type == "spell" then
local name, rank = GetSpellName(id, info)
if rank ~= "" then
name = name.."("..rank..")"
end
info = name
elseif type ~= "item" then
return
end
ClearCursor() ClearCursor()
local self = this.obj local self = this.obj
local editBox = self.editBox local editBox = self.editBox
if not this.hasfocus then if not this.hasfocus then
this.hasfocus = true this.hasfocus = true
editBox:SetFocus() editBox:SetFocus()
local n = editBox:GetNumLetters() EditBoxSetCursorPosition(editBox, editBox:GetNumLetters())
editBox:HighlightText(n,n)
end end
editBox:Insert(info) editBox:Insert(info)
self.button:Enable() self.button:Enable()
end end
local function OnSizeChanged() -- ScrollFrame local function OnSizeChanged() -- ScrollFrame
this:UpdateScrollChildRect() this.obj.editBox:SetWidth(this.obj.editBox:GetWidth())
this:SetVerticalScroll(this:GetHeight())
this.obj.editBox:SetWidth(arg1)
end end
local function OnTextChanged() -- EditBox local function OnTextChanged() -- EditBox
local self = this.obj local self = this.obj
local value = this:GetText() local value = self.editBox:GetText()
if tostring(value) ~= tostring(self.lasttext) then if not self.lastText or value ~= self.lastText then
self:Fire("OnTextChanged", 1, value) self:Fire("OnTextChanged", value)
self.lasttext = value self.lastText = nil
self.button:Enable() self.button:Enable()
else
self.button:Disable()
self.lastText = value
end end
end end
local function OnTextSet() -- EditBox local function OnTextSet() -- EditBox
this:HighlightText(0, 0) this:HighlightText(0, 0)
EditBoxSetCursorPosition(this, this:GetNumLetters())
EditBoxSetCursorPosition(this, 0)
this.obj.button:Disable() this.obj.button:Disable()
end end
local function OnVerticalScroll() -- ScrollFrame local function OnVerticalScroll() -- ScrollFrame
local self = this.obj local editBox = this.obj.editBox
local editBox = self.editBox
editBox:SetHitRectInsets(0, 0, arg1, editBox:GetHeight() - arg1 - this:GetHeight()) editBox:SetHitRectInsets(0, 0, arg1, editBox:GetHeight() - arg1 - this:GetHeight())
self.scrollFrame:SetScrollChild(self.editBox)
self.editBox:SetPoint("TOPLEFT",0,arg1)
self.editBox:SetPoint("TOPRIGHT",0,arg1)
end end
local function OnShowFocus() local function OnShowFocus()
@@ -252,7 +281,7 @@ local function OnEditFocusGained()
this.obj:Fire("OnEditFocusGained") this.obj:Fire("OnEditFocusGained")
end end
local function OnEscapePressed() -- EditBox local function OnEscapePressed()
AceGUI:ClearFocus() AceGUI:ClearFocus()
end end
@@ -314,10 +343,8 @@ local methods = {
end, end,
["SetText"] = function(self, text) ["SetText"] = function(self, text)
self.lasttext = text or "" self.lastText = text
self.editBox:SetText(text or "") self.editBox:SetText(text)
self.editBox:HighlightText(0)
self.button:Disable()
end, end,
["GetText"] = function(self) ["GetText"] = function(self)
@@ -353,6 +380,22 @@ local methods = {
["HighlightText"] = function(self, from, to) ["HighlightText"] = function(self, from, to)
self.editBox:HighlightText(from, to) self.editBox:HighlightText(from, to)
end, end,
["GetCursorPosition"] = function(self)
return EditBoxGetCursorPosition(self.editBox)
end,
["SetCursorPosition"] = function(self, pos)
return EditBoxSetCursorPosition(self.editBox, pos)
end,
["OnWidthSet"] = function(self, width)
self.scrollFrame:SetWidth(width)
end,
["OnHeightSet"] = function(self, height)
self.scrollFrame:SetHeight(height)
end
} }
--[[----------------------------------------------------------------------------- --[[-----------------------------------------------------------------------------
@@ -377,7 +420,7 @@ local function Constructor()
label:SetText(ACCEPT) label:SetText(ACCEPT)
label:SetHeight(10) label:SetHeight(10)
local button = CreateFrame("Button", strfmt("%s%dButton", Type, widgetNum), frame, "UIPanelButtonTemplate") local button = CreateFrame("Button", format("%s%dButton", Type, widgetNum), frame, "UIPanelButtonTemplate")
button:SetPoint("BOTTOMLEFT", 0, 4) button:SetPoint("BOTTOMLEFT", 0, 4)
button:SetHeight(22) button:SetHeight(22)
button:SetWidth(label:GetStringWidth() + 24) button:SetWidth(label:GetStringWidth() + 24)
@@ -396,7 +439,7 @@ local function Constructor()
scrollBG:SetBackdropColor(0, 0, 0) scrollBG:SetBackdropColor(0, 0, 0)
scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4) scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)
local scrollFrame = CreateFrame("ScrollFrame", strfmt("%s%dScrollFrame", Type, widgetNum), frame, "UIPanelScrollFrameTemplate") local scrollFrame = CreateFrame("ScrollFrame", format("%s%dScrollFrame", Type, widgetNum), frame, "UIPanelScrollFrameTemplate")
local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"] local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
scrollBar:ClearAllPoints() scrollBar:ClearAllPoints()
@@ -414,17 +457,9 @@ local function Constructor()
scrollFrame:SetScript("OnMouseUp", OnMouseUp) scrollFrame:SetScript("OnMouseUp", OnMouseUp)
scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag) scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
scrollFrame:SetScript("OnSizeChanged", OnSizeChanged) scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
local old = scrollFrame:GetScript("OnVerticalScroll"); HookScript(scrollFrame, "OnVerticalScroll", OnVerticalScroll)
if old then
scrollFrame:SetScript("OnVerticalScroll", function()
old()
OnVerticalScroll()
end)
else
scrollFrame:SetScript("OnVerticalScroll", OnVerticalScroll)
end
local editBox = CreateFrame("EditBox", strfmt("%s%dEdit", Type, widgetNum), scrollFrame) local editBox = CreateFrame("EditBox", format("%s%dEdit", Type, widgetNum), scrollFrame)
editBox:SetFontObject(ChatFontNormal) editBox:SetFontObject(ChatFontNormal)
editBox:SetMultiLine(true) editBox:SetMultiLine(true)
editBox:EnableMouse(true) editBox:EnableMouse(true)
@@ -440,10 +475,9 @@ local function Constructor()
editBox:SetScript("OnTextSet", OnTextSet) editBox:SetScript("OnTextSet", OnTextSet)
editBox:SetScript("OnEditFocusGained", OnEditFocusGained) editBox:SetScript("OnEditFocusGained", OnEditFocusGained)
-- Ace3v: the orders are important here
scrollFrame:SetScrollChild(editBox) scrollFrame:SetScrollChild(editBox)
editBox:SetPoint("TOPLEFT",0,0) editBox:SetAllPoints()
editBox:SetPoint("TOPRIGHT",0,0)
local widget = { local widget = {
button = button, button = button,
@@ -2,14 +2,14 @@
Slider Widget Slider Widget
Graphical Slider, like, for Range values. Graphical Slider, like, for Range values.
-------------------------------------------------------------------------------]] -------------------------------------------------------------------------------]]
local Type, Version = "Slider", 21 local Type, Version = "Slider", 20
local AceGUI = LibStub and LibStub("AceGUI-3.0", true) local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
-- Lua APIs -- Lua APIs
local min, max, floor = math.min, math.max, math.floor local min, max, floor = math.min, math.max, math.floor
local format, gsub = string.format, string.gsub
local tonumber, pairs = tonumber, pairs local tonumber, pairs = tonumber, pairs
local format, gsub = string.format, string.gsub
-- WoW APIs -- WoW APIs
local PlaySound = PlaySound local PlaySound = PlaySound
@@ -62,13 +62,9 @@ local function Slider_OnValueChanged()
local self = this.obj local self = this.obj
if not this.setup then if not this.setup then
local newvalue = this:GetValue() local newvalue = this:GetValue()
if self.step and self.step > 0 then
local min_value = self.min or 0
newvalue = floor((newvalue - min_value) / self.step + 0.5) * self.step + min_value
end
if newvalue ~= self.value and not self.disabled then if newvalue ~= self.value and not self.disabled then
self.value = newvalue self.value = newvalue
self:Fire("OnValueChanged", 1, newvalue) self:Fire("OnValueChanged", newvalue)
end end
if self.value then if self.value then
UpdateText(self) UpdateText(self)
@@ -78,7 +74,7 @@ end
local function Slider_OnMouseUp() local function Slider_OnMouseUp()
local self = this.obj local self = this.obj
self:Fire("OnMouseUp", 1, self.value) self:Fire("OnMouseUp", self.value)
end end
local function Slider_OnMouseWheel() local function Slider_OnMouseWheel()
@@ -111,7 +107,7 @@ local function EditBox_OnEnterPressed()
if value then if value then
PlaySound("igMainMenuOptionCheckBoxOn") PlaySound("igMainMenuOptionCheckBoxOn")
self.slider:SetValue(value) self.slider:SetValue(value)
self:Fire("OnMouseUp", 1, value) self:Fire("OnMouseUp", value)
end end
end end
@@ -224,7 +220,7 @@ local function Constructor()
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal") local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetPoint("TOPLEFT", 0, 0) label:SetPoint("TOPLEFT", 0, 0)
label:SetPoint("TOPRIGHT", 0, 0) label:SetPoint("TOPRIGHT", 0, 0)
label:SetJustifyH("CENTER",0,0) label:SetJustifyH("CENTER")
label:SetHeight(15) label:SetHeight(15)
local slider = CreateFrame("Slider", nil, frame) local slider = CreateFrame("Slider", nil, frame)