WoWInterface SVN Broker_BubbleToggle

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

Broker_BubbleToggle.lua New file
0,0 → 1,184
local addonName = ...
local L = LibStub("AceLocale-3.0"):GetLocale(addonName, true)
local db
local dataobj
local ShowKeybindFrame -- local function, forward declaration
local frame -- first used for ADDON_LOADED, then can be recycled for keybinding
 
 
-- Print with colored prefix.
local printPrefix = "|cff33ff99"..addonName.."|r:"
local function print(...)
_G.print(printPrefix, ...)
end
 
 
-- Globals for bindings
BINDING_HEADER_BROKER_BUBBLETOGGLE = addonName
BINDING_NAME_BROKER_BUBBLETOGGLE_TOGGLE = L["Toggle Chat Bubbles"]
 
 
-- Global. Used in Bindings.
function Broker_BubbleToggle_Toggle()
SetCVar("ChatBubbles", 1 - GetCVar("ChatBubbles"))
UpdateDataObject()
if GameTooltip:IsShown() then
GameTooltip:Hide()
end
end
 
 
-- Updates aspects of the dataobj that change when we change settings.
function UpdateDataObject()
if db.showText then
dataobj.type = "data source"
else
dataobj.type = "launcher"
end
if GetCVarBool("ChatBubbles") then
dataobj.text = L["Chat Bubbles"]
dataobj.icon = "Interface\\Addons\\Broker_BubbleToggle\\images\\green.tga"
dataobj.modeDescription = "Chat Bubbles"
dataobj.otherModeDescription = L["No Bubbles"]
else
dataobj.text = L["No Bubbles"]
dataobj.icon = "Interface\\Addons\\Broker_BubbleToggle\\images\\red.tga"
dataobj.modeDescription = L["No Bubbles"]
dataobj.otherModeDescription = "Chat Bubbles"
end
end
 
 
-- Init. Use frame to wait for ADDON_LOADED.
frame = CreateFrame("Frame")
frame:SetScript("OnEvent", function(self, event, name)
if name ~= addonName then return end
frame:UnregisterEvent("ADDON_LOADED")
frame:SetScript("OnEvent", nil)
 
Broker_BubbleToggleDB = Broker_BubbleToggleDB or {}
db = Broker_BubbleToggleDB
if db.showText == nil then
db.showText = true
end
 
dataobj = {}
UpdateDataObject()
dataobj = LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject("BubbleToggle", dataobj)
--hooksecurefunc("RestartGx", UpdateDataObject)
 
function dataobj:OnTooltipShow()
self:AddLine(dataobj.modeDescription)
self:AddDoubleLine(L["Left-Click"], dataobj.otherModeDescription)
self:AddDoubleLine(L["Middle-Click"], (db.showText and L["Hide Text"] or L["Show Text"]))
self:AddDoubleLine(L["Right-Click"], KEY_BINDING)
end
 
function dataobj:OnClick(button)
if button == "LeftButton" then
Broker_BubbleToggle_Toggle()
elseif button == "MiddleButton" then
db.showText = not db.showText
UpdateDataObject()
elseif button == "RightButton" then
if not InCombatLockdown() then
ShowKeybindFrame()
else
print(L["Can't keybind in combat."])
end
end
end
end)
frame:RegisterEvent("ADDON_LOADED")
 
 
-----------------------------------
-- Keybind Frame
-----------------------------------
 
-- This can be called many times; it only does extensive init the first time.
function ShowKeybindFrame() -- declared local
frame:SetFrameStrata("DIALOG")
frame:EnableKeyboard(true)
frame:SetClampedToScreen(true)
frame:Hide()
frame:SetPoint("CENTER", 0, UIParent:GetHeight() / 7)
frame:SetBackdrop({
bgFile=[[Interface\Tooltips\UI-Tooltip-Background]],
edgeFile=[[Interface\Tooltips\UI-Tooltip-Border]], tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 4, right = 4, top = 4, bottom = 4 }
})
frame:SetBackdropColor(0, 0, 0)
 
frame.text = frame:CreateFontString(nil, "ARTWORK", "GameFontNormal")
frame.text:SetPoint("TOP", 0, -40)
frame.text:SetText(L[ [=[
Press a key to bind.
 
Or press ESC to cancel.]=] ])
 
frame:SetScript("OnShow", function(self)
local width = self.text:GetWidth() + 80
local height = self.text:GetHeight() + 80
self:SetWidth(width)
self:SetHeight(height)
 
self:RegisterEvent("PLAYER_REGEN_DISABLED") -- so we can hide in combat
end)
 
frame:SetScript("OnHide", function(self)
self:UnregisterEvent("PLAYER_REGEN_DISABLED")
end)
 
frame:SetScript("OnEvent", function(self, event, ...)
if event == "PLAYER_REGEN_DISABLED" then
print(L["Can't keybind in combat."])
self:Hide() -- hide in combat
end
end)
 
-- These generate OnKeyDown events, but aren't bindable and should be discarded.
local unbindableKeys = {
LALT = 1,
LCTRL = 1,
LSHIFT = 1,
RALT = 1,
RCTRL = 1,
RSHIFT = 1,
UNKNOWN = 1,
}
 
frame:SetScript("OnKeyDown", function(self, key)
if unbindableKeys[key] then
return
end
if key == "ESCAPE" then
self:Hide()
return
end
if GetBindingFromClick(key) == "SCREENSHOT" then
TakeScreenshot()
return
end
if IsShiftKeyDown() then
key = "SHIFT-"..key
end
if IsControlKeyDown() then
key = "CTRL-"..key
end
if IsAltKeyDown() then
key = "ALT-"..key
end
 
if SetBinding(key, "BROKER_BUBBLETOGGLE_TOGGLE") then
print(KEY_BOUND..": "..key)
SaveBindings(GetCurrentBindingSet())
else
print(KEY_BINDING..": "..FAILED)
end
self:Hide()
end)
 
ShowKeybindFrame = function() frame:Show() end
frame:Show()
end
Property changes : Added: svn:eol-style + native
.project New file
0,0 → 1,17
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>BubbleToggle</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.keplerproject.ldt.core.luaProjectBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.keplerproject.ldt.core.luaProjectNature</nature>
</natures>
</projectDescription>
Property changes : Added: svn:eol-style + native
Broker_BubbleToggle.toc New file
0,0 → 1,19
## Interface: 30300
## Title: Broker: BubbleToggle
## Notes: Toggle chat bubbles with click or keybind. Totally borrowed the code from ZombiePope
## Author: Monk1nr
## OptionalDeps: Ace3
## SavedVariables: Broker_BubbleToggleDB
 
## LoadManagers: AddonLoader
## X-LoadOn-Always: delayed
 
#@no-lib-strip@
libs\LibStub\LibStub.lua
libs\CallbackHandler-1.0\CallbackHandler-1.0.xml
libs\AceLocale-3.0\AceLocale-3.0.xml
#@end-no-lib-strip@
libs\LibDataBroker-1.1.lua
 
Localization.lua
Broker_BubbleToggle.lua
\ No newline at end of file Property changes : Added: svn:eol-style + native
images/red.tga Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes : Added: svn:mime-type + application/octet-stream
images/green.tga Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes : Added: svn:mime-type + application/octet-stream
images/Credits.txt New file
0,0 → 1,3
The "chat bubble" icons are from GoSquared. They're public domain, and this credit isn't necessary; it's just a courtesy:
 
http://www.gosquared.com/liquidicity/archives/122
Property changes : Added: svn:eol-style + native
Localization.lua New file
0,0 → 1,30
-- Broker_BubbleToggle Localization File
-- THIS CONTENTS OF THIS FILE ARE AUTO-GENERATED BY THE WOWACE PACKAGER
-- Please use the Localization App on WowAce to update this
-- at http://www.wowace.com/projects/broker-windowed-mode/localization/
 
local addonName = ...
local AL3 = LibStub("AceLocale-3.0")
local debug = false
--[===[@debug@
debug = true
--@end-debug@]===]
 
local L = AL3:NewLocale(addonName, "enUS", true, debug)
if L then
L["Can't keybind in combat."] = true
L["Bubbles"] = true
L["Chat Bubbles"] = true
L["Hide Text"] = true
L["Left-Click"] = true
L["Middle-Click"] = true
L[ [=[Press a key to bind.
 
Or press ESC to cancel.]=] ] = true
L["Right-Click"] = true
L["Show Text"] = true
L["Toggle Chat Bubbles"] = true
L["No Bubbles"] = true
 
if GetLocale() == "enUS" or GetLocale() == "enGB" then return end
end
Property changes : Added: svn:eol-style + native
libs/LibDataBroker-1.1.lua New file
0,0 → 1,90
 
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
 
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
if not lib then return end
oldminor = oldminor or 0
 
 
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
 
if oldminor < 2 then
lib.domt = {
__metatable = "access denied",
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
}
end
 
if oldminor < 3 then
lib.domt.__newindex = function(self, key, value)
if not attributestorage[self] then attributestorage[self] = {} end
if attributestorage[self][key] == value then return end
attributestorage[self][key] = value
local name = namestorage[self]
if not name then return end
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
end
end
 
if oldminor < 2 then
function lib:NewDataObject(name, dataobj)
if self.proxystorage[name] then return end
 
if dataobj then
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
self.attributestorage[dataobj] = {}
for i,v in pairs(dataobj) do
self.attributestorage[dataobj][i] = v
dataobj[i] = nil
end
end
dataobj = setmetatable(dataobj or {}, self.domt)
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
return dataobj
end
end
 
if oldminor < 1 then
function lib:DataObjectIterator()
return pairs(self.proxystorage)
end
 
function lib:GetDataObjectByName(dataobjectname)
return self.proxystorage[dataobjectname]
end
 
function lib:GetNameByDataObject(dataobject)
return self.namestorage[dataobject]
end
end
 
if oldminor < 4 then
local next = pairs(attributestorage)
function lib:pairs(dataobject_or_name)
local t = type(dataobject_or_name)
assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
 
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
assert(attributestorage[dataobj], "Data object not found")
 
return next, attributestorage[dataobj], nil
end
 
local ipairs_iter = ipairs(attributestorage)
function lib:ipairs(dataobject_or_name)
local t = type(dataobject_or_name)
assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
 
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
assert(attributestorage[dataobj], "Data object not found")
 
return ipairs_iter, attributestorage[dataobj], 0
end
end
Property changes : Added: svn:eol-style + native
libs/LibStub/LibStub.lua New file
0,0 → 1,30
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
-- 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 = _G[LIBSTUB_MAJOR]
 
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
 
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
 
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
 
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
 
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
Property changes : Added: svn:eol-style + native
libs/LibStub/LibStub.toc New file
0,0 → 1,13
## Interface: 20400
## Title: Lib: LibStub
## Notes: Universal Library Stub
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
## X-Website: http://jira.wowace.com/browse/LS
## X-Category: Library
## X-License: Public Domain
## X-Curse-Packaged-Version: 1.0
## X-Curse-Project-Name: LibStub
## X-Curse-Project-ID: libstub
## X-Curse-Repository-ID: wow/libstub/mainline
 
LibStub.lua
Property changes : Added: svn:eol-style + native
libs/AceLocale-3.0/AceLocale-3.0.xml New file
0,0 → 1,4
<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"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native
libs/AceLocale-3.0/AceLocale-3.0.lua New file
0,0 → 1,136
--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
-- @class file
-- @name AceLocale-3.0
-- @release $Id: AceLocale-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
local MAJOR,MINOR = "AceLocale-3.0", 2
 
local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceLocale then return end -- no upgrade needed
 
-- Lua APIs
local assert, tostring, error = assert, tostring, error
local setmetatable, rawset, rawget = setmetatable, rawset, rawget
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: GAME_LOCALE, geterrorhandler
 
local gameLocale = GetLocale()
if gameLocale == "enGB" then
gameLocale = "enUS"
end
 
AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
 
-- This metatable is used on all tables returned from GetLocale
local readmeta = {
__index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
rawset(self, key, key) -- only need to see the warning once, really
geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
return key
end
}
 
-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
local readmetasilent = {
__index = function(self, key) -- requesting totally unknown entries: return key
rawset(self, key, key) -- only need to invoke this function once
return key
end
}
 
-- Remember the locale table being registered right now (it gets set by :NewLocale())
-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
local registering
 
-- local assert false function
local assertfalse = function() assert(false) end
 
-- This metatable proxy is used when registering nondefault locales
local writeproxy = setmetatable({}, {
__newindex = function(self, key, value)
rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
end,
__index = assertfalse
})
 
-- This metatable proxy is used when registering the default locale.
-- It refuses to overwrite existing values
-- Reason 1: Allows loading locales in any order
-- Reason 2: If 2 modules have the same string, but only the first one to be
-- loaded has a translation for the current locale, the translation
-- doesn't get overwritten.
--
local writedefaultproxy = setmetatable({}, {
__newindex = function(self, key, value)
if not rawget(registering, key) then
rawset(registering, key, value == true and key or value)
end
end,
__index = assertfalse
})
 
--- Register a new locale (or extend an existing one) for the specified application.
-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
-- game locale.
-- @paramsig application, locale[, isDefault[, silent]]
-- @param application Unique name of addon / module
-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
-- @param silent If true, the locale will not issue warnings for missing keys. Can only be set on the default locale.
-- @usage
-- -- enUS.lua
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
-- L["string1"] = true
--
-- -- deDE.lua
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
-- if not L then return end
-- L["string1"] = "Zeichenkette1"
-- @return Locale Table to add localizations to, or nil if the current locale is not required.
function AceLocale:NewLocale(application, locale, isDefault, silent)
 
if silent and not isDefault then
error("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' can only be specified for the default locale", 2)
end
 
-- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
-- Ammo: I still think this is a bad idea, for instance an addon that checks for some ingame string will fail, just because some other addon
-- gives the user the illusion that they can run in a different locale? Ditch this whole thing or allow a setting per 'application'. I'm of the
-- opinion to remove this.
local gameLocale = GAME_LOCALE or gameLocale
 
if locale ~= gameLocale and not isDefault then
return -- nop, we don't need these translations
end
 
local app = AceLocale.apps[application]
 
if not app then
app = setmetatable({}, silent and readmetasilent or readmeta)
AceLocale.apps[application] = app
AceLocale.appnames[app] = application
end
 
registering = app -- remember globally for writeproxy and writedefaultproxy
 
if isDefault then
return writedefaultproxy
end
 
return writeproxy
end
 
--- Returns localizations for the current locale (or default locale if translations are missing).
-- Errors if nothing is registered (spank developer, not just a missing translation)
-- @param application Unique name of addon / module
-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
-- @return The locale table for the current language.
function AceLocale:GetLocale(application, silent)
if not silent and not AceLocale.apps[application] then
error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
end
return AceLocale.apps[application]
end
Property changes : Added: svn:eol-style + native
libs/CallbackHandler-1.0/CallbackHandler-1.0.xml New file
0,0 → 1,4
<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="CallbackHandler-1.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native
libs/CallbackHandler-1.0/CallbackHandler-1.0.lua New file
0,0 → 1,240
--[[ $Id: CallbackHandler-1.0.lua 14 2010-08-09 00:43:38Z mikk $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 6
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
 
if not CallbackHandler then return end -- No upgrade needed
 
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
 
-- Lua APIs
local tconcat = table.concat
local assert, error, loadstring = assert, error, loadstring
local setmetatable, rawset, rawget = setmetatable, rawset, rawget
local next, select, pairs, type, tostring = next, select, pairs, type, tostring
 
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: geterrorhandler
 
local xpcall = xpcall
 
local function errorhandler(err)
return geterrorhandler()(err)
end
 
local function CreateDispatcher(argCount)
local code = [[
local next, xpcall, eh = ...
 
local method, ARGS
local function call() method(ARGS) end
 
local function dispatch(handlers, ...)
local index
index, method = next(handlers)
if not method then return end
local OLD_ARGS = ARGS
ARGS = ...
repeat
xpcall(call, eh)
index, method = next(handlers, index)
until not method
ARGS = OLD_ARGS
end
 
return dispatch
]]
 
local ARGS, OLD_ARGS = {}, {}
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
end
 
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
 
--------------------------------------------------------------------------
-- CallbackHandler:New
--
-- target - target object to embed public APIs in
-- RegisterName - name of the callback registration API, default "RegisterCallback"
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
 
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
-- TODO: Remove this after beta has gone out
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
 
RegisterName = RegisterName or "RegisterCallback"
UnregisterName = UnregisterName or "UnregisterCallback"
if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
UnregisterAllName = "UnregisterAllCallbacks"
end
 
-- we declare all objects and exported APIs inside this closure to quickly gain access
-- to e.g. function names, the "target" parameter, etc
 
 
-- Create the registry object
local events = setmetatable({}, meta)
local registry = { recurse=0, events=events }
 
-- registry:Fire() - fires the given event/message into the registry
function registry:Fire(eventname, ...)
if not rawget(events, eventname) or not next(events[eventname]) then return end
local oldrecurse = registry.recurse
registry.recurse = oldrecurse + 1
 
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
 
registry.recurse = oldrecurse
 
if registry.insertQueue and oldrecurse==0 then
-- Something in one of our callbacks wanted to register more callbacks; they got queued
for eventname,callbacks in pairs(registry.insertQueue) do
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
for self,func in pairs(callbacks) do
events[eventname][self] = func
-- fire OnUsed callback?
if first and registry.OnUsed then
registry.OnUsed(registry, target, eventname)
first = nil
end
end
end
registry.insertQueue = nil
end
end
 
-- Registration of a callback, handles:
-- self["method"], leads to self["method"](self, ...)
-- self with function ref, leads to functionref(...)
-- "addonId" (instead of self) with function ref, leads to functionref(...)
-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
if type(eventname) ~= "string" then
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
end
 
method = method or eventname
 
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
 
if type(method) ~= "string" and type(method) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
end
 
local regfunc
 
if type(method) == "string" then
-- self["method"] calling style
if type(self) ~= "table" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
elseif self==target then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
elseif type(self[method]) ~= "function" then
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
end
 
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) self[method](self,arg,...) end
else
regfunc = function(...) self[method](self,...) end
end
else
-- function ref with self=object or self="addonId" or self=thread
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
end
 
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
local arg=select(1,...)
regfunc = function(...) method(arg,...) end
else
regfunc = method
end
end
 
 
if events[eventname][self] or registry.recurse<1 then
-- if registry.recurse<1 then
-- we're overwriting an existing entry, or not currently recursing. just set it.
events[eventname][self] = regfunc
-- fire OnUsed callback?
if registry.OnUsed and first then
registry.OnUsed(registry, target, eventname)
end
else
-- we're currently processing a callback in this registry, so delay the registration of this new entry!
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
registry.insertQueue = registry.insertQueue or setmetatable({},meta)
registry.insertQueue[eventname][self] = regfunc
end
end
 
-- Unregister a callback
target[UnregisterName] = function(self, eventname)
if not self or self==target then
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
end
if type(eventname) ~= "string" then
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
end
if rawget(events, eventname) and events[eventname][self] then
events[eventname][self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(events[eventname]) then
registry.OnUnused(registry, target, eventname)
end
end
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
registry.insertQueue[eventname][self] = nil
end
end
 
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
if UnregisterAllName then
target[UnregisterAllName] = function(...)
if select("#",...)<1 then
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
end
if select("#",...)==1 and ...==target then
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
end
 
 
for i=1,select("#",...) do
local self = select(i,...)
if registry.insertQueue then
for eventname, callbacks in pairs(registry.insertQueue) do
if callbacks[self] then
callbacks[self] = nil
end
end
end
for eventname, callbacks in pairs(events) do
if callbacks[self] then
callbacks[self] = nil
-- Fire OnUnused callback?
if registry.OnUnused and not next(callbacks) then
registry.OnUnused(registry, target, eventname)
end
end
end
end
end
end
 
return registry
end
 
 
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
-- try to upgrade old implicit embeds since the system is selfcontained and
-- relies on closures to work.
 
Property changes : Added: svn:eol-style + native
Bindings.xml New file
0,0 → 1,5
<Bindings>
<Binding name="BROKER_BUBBLETOGGLE_TOGGLE" header="BROKER_BUBBLETOGGLE">
Broker_BubbleToggle_Toggle()
</Binding>
</Bindings>
Property changes : Added: svn:eol-style + native