/
LanguageCycle v4.2 |
LanguageCycle |
---What this mod does--- |
/lc group |
/lc guild |
/lc toggle |
Any of the above commands will do the same thing. Each is the same as clicking the checkbox in the pop-up panel (or toggling the Titan Panel auto-translate option). |
Any of the above commands will do the same thing. Each is the same as clicking the checkbox in the pop-up panel. |
To hide or show the visual UI, use: |
At this time, there are no other known issues with either the standard WoW UI or any other third-party mods. |
---Version History--- |
-4.2.2 |
Minimap icon should now save its position |
Added slashcommand to hide the minimap button |
LDB libs are now embedded |
-4.2 |
Updated toc version |
Added LDB support |
-4.0.1 |
Fixed depreciated code usage and updated toc |
-3.2 |
Updated toc version for 3.2.2. No code changes, mod still fully functional. |
-3.1.0 |
Updated toc version for patch 3.1, mod still fully functional. |
-3.0.3 |
Updated toc version and various comments/texts including this file. |
-3.0.2d |
After getting some help the default UI button works again. |
-3.0.2c |
Stripped all non-functional code to make the mod functional for Patch 3.0.2. UI functionality disabled. |
-2.03 - Apr. 7, 2008: |
Fixed an issue where Blizzard had corrected a typoed function call so LanguageCycle can find the proper function again. |
-2.02 - Dec. 31, 2006: |
Integrated the Titan panel plugin into the core (LanguageCycle) mod rather than keeping it a seperate one, for people who are directory concious. |
Integrated a new FuBar plugin so LanguageCycle now supports that aswell. Added a few ACE libraries because of this integration. |
Removed old additional TitanPanel plugin as it is no longer needed. |
-2.01 - Dec. 31, 2006: |
Added a few other new channels to the auto-translate feature (battlegrounds for one) |
Fixed and Readded the Titanpanel plugin as it seems to be working now. |
-2.00 - Dec. 26, 2006: |
Updated for WoW client 2.x. |
Changed a few inner works to ensure playing nicely with Blizzard's new protected calls. |
Removed the Titanpanel plugin for now until it can be tested with 2.x. |
-1.1.10900 - Jan. 5, 2006: |
Update TOC number to 10900 for WoW client patch 1.9.0 |
No other changes |
-1.1.1800 - Oct. 16, 2005: |
Update TOC number to 1800 for WoW client patch 1.8.0 |
Added Guild Officer channel to auto-translate feature. |
-1.1.1700 - Sept. 13, 2005: |
Update TOC number to 1700 for WoW client patch 1.7.0 |
No other changes |
-1.1.1600 - July 12, 2005: |
Updated TOC number to 1600 for WoW client patch 1.6.0. |
No other changes. |
-1.1.1500 - June 15, 2005: |
Added MyAddons support. |
Added Titan Panel plugin. |
-1.0.1 - June 7, 2005: |
Updated TOC number to 1500 for WoW client patch 1.5.0. |
Added Raid channel to auto-translation. |
-1.0.0 - April 11, 2005: |
First released version. |
---Contact info--- |
Questions and concerns may be sent to: |
aghokala@gmail.com |
---EOF--- |
-- Language cycle script |
-- Version 5.0.4.a |
local ButtonTexture = "Interface\\Addons\\LanguageCycle\\media\\LanguageCycleIcon" |
local addonName = "LanguageCycle" |
BINDING_HEADER_LANGUAGECYCLE="Language Cycle"; |
local defaults = { |
saved_language = {}; |
translate_group = true; |
panel_visible = true; |
panel_locked = false; |
minimapIcon = { |
hide = false, |
minimapPos = 220, |
radius = 80, |
} |
} |
if not LANGUAGE_CYCLE then |
LANGUAGE_CYCLE = defaults |
else |
for k, v in pairs(defaults) do |
if LANGUAGE_CYCLE[k] == nil or type(LANGUAGE_CYCLE[k]) ~= type(v) then |
LANGUAGE_CYCLE[k] = v |
end |
end |
end |
LC_default_language = ""; |
LC_verbose = true; |
LC_unknown = "Unknown Entity"; |
LC_realm_name = ""; |
LC_player_name = ""; |
LC_player_id = nil; |
LC_panel_height = 0; |
LC_panel_width = 0; |
LC_version = "4.2.2, by Halya, Argent Dawn, EU"; |
LC_Help_Text={}; |
LC_Help_Text[0]="Language Cycle will respond to the following commands:"; |
LC_Help_Text[1]="- /lc : Toggles spoken language between racial/common"; |
LC_Help_Text[2]="- /lc status : Displays current settings"; |
LC_Help_Text[3]="- /lc toggle : Toggles Guild/Party translation on/off"; |
LC_Help_Text[4]="- /lc help : Displays this message"; |
LC_Help_Text[5]="- /lc show : Display the language cycle button"; |
LC_Help_Text[6]="- /lc hide : Hide the language cycle button"; |
LC_Help_Text[7]="- /lc MM : Toggle the language cycle mini-map button"; |
LC_Help_Text[8]="--------------------------------------------------------------"; |
--Save Blizzard's original SendText function |
local LC_Blizzard_SendChatMessage; |
function Language_Cycle_OnLoad( self ) |
-- Hook SendChatMessage |
LC_Blizzard_SendChatMessage = SendChatMessage; |
SendChatMessage = LC_SendChatMessage; |
SlashCmdList["LANGUAGECYCLE"] = Language_Cycle_Slash; |
SLASH_LANGUAGECYCLE1 = "/lc"; |
ShowUIPanel(Language_Cycle_Panel); |
if ( not Language_Cycle_Panel:IsVisible() ) then |
Language_Cycle_Panel:SetOwner(UIParent, "ANCHOR_PRESERVE"); |
end |
Language_Cycle_Panel_Backdrop:SetBackdropBorderColor(1,1,1); |
Language_Cycle_Panel_Backdrop:SetBackdropColor(0.3, 0.3, 0.3); |
Language_Cycle_Backdrop_Hide(); |
LC_panel_height = Language_Cycle_Panel:GetHeight(); |
LC_panel_width = Language_Cycle_Panel:GetWidth(); |
Language_Cycle_Party_Toggle_Text:SetJustifyH("Right"); |
Language_Cycle_Add_Message("LanguageCycle loaded; Type '/lc help' for a list of options; Version " .. LC_version); |
-- self:SetPadding(16); |
self:RegisterForDrag("LeftButton"); |
self:RegisterEvent("VARIABLES_LOADED"); |
self:RegisterEvent("PLAYER_ENTERING_WORLD"); |
end |
function Language_Cycle_Get_Version() |
return LC_version |
end |
-- replace Blizzard's SendChatMessage function instead. -Nhani |
function LC_SendChatMessage(msg, chatType, language, channel) |
if (LC_player_id ~= nil) then |
language = LANGUAGE_CYCLE.saved_language[LC_player_id]; |
end |
-- Small change here. Instead of defining what channels we WANT |
-- in a common language, we define what channels we DON'T want. |
-- Since those are far fewer in number. -Nhani |
if (LANGUAGE_CYCLE.translate_group) then |
if (chatType ~= "SAY" and chatType ~= "YELL") then |
if (language ~= LC_default_language) then |
language = LC_default_language; |
end |
end |
end |
local numLanguages = GetNumLanguages(); |
local i; |
for i = 1, numLanguages, 1 do |
local getlanguage, getlanguageID = GetLanguageByIndex(i); |
if (language == getlanguage) then |
languageID = getlanguageID; |
end |
end |
LC_Blizzard_SendChatMessage(msg, chatType, languageID, channel); |
end |
function Language_Cycle_Panel_Visible() |
if (Language_Cycle_Panel:IsVisible() ) then |
HideUIPanel(Language_Cycle_Panel); |
LANGUAGE_CYCLE.panel_visible = false; |
else |
ShowUIPanel(Language_Cycle_Panel); |
LANGUAGE_CYCLE.panel_visible = true; |
end |
end |
function Language_Cycle_Backdrop_Show(override) |
if (LANGUAGE_CYCLE.panel_locked and not override) then |
else |
Language_Cycle_Panel_Backdrop:Show(); |
end |
end |
function Language_Cycle_Backdrop_Hide(override) |
if (LANGUAGE_CYCLE.panel_locked and not override) then |
else |
Language_Cycle_Panel_Backdrop:Hide(); |
end |
end |
function Language_Cycle_Cycle() |
local numLangs = GetNumLanguages(); |
local currentlang = 0; |
local lang; |
lang = Language_Cycle_Get_Lang(); |
for i=1,numLangs,1 do |
if (lang == GetLanguageByIndex(i)) then |
currentlang = i; |
end |
end |
if (currentlang == numLangs) then |
currentlang = 1; |
else |
currentlang = currentlang + 1; |
end |
Language_Cycle_Set_Lang(GetLanguageByIndex(currentlang)); |
-- if (IsAddOnLoaded("Titan")) then |
-- TitanPanelButton_UpdateButton(TITAN_LANGUAGECYCLE_ID); |
-- end |
-- if (IsAddOnLoaded("FuBar")) then |
-- LanguageCycleFuBar:UpdateText() |
-- end |
-- For debugging |
-- Langauge_Cycle_Debug_Message(); |
end |
function Language_Cycle_Language_Clicked(button) |
if (button == "LeftButton") then |
LC_verbose = false; |
Language_Cycle_Cycle(); |
LC_verbose = true; |
end |
if (button == "RightButton") then |
LANGUAGE_CYCLE.panel_locked = not LANGUAGE_CYCLE.panel_locked; |
Langauge_Cycle_Lock_Backdrop(); |
end |
end |
function Langauge_Cycle_Lock_Backdrop() |
if (LANGUAGE_CYCLE.panel_locked) then |
Language_Cycle_Backdrop_Hide(true); |
Language_Cycle_Panel:SetHeight(Language_Cycle_Button:GetHeight()); |
Language_Cycle_Panel:SetWidth(Language_Cycle_Button:GetWidth()); |
else |
Language_Cycle_Backdrop_Show(true); |
Language_Cycle_Panel:SetHeight(LC_panel_height); |
Language_Cycle_Panel:SetWidth(LC_panel_width); |
end |
end |
function Language_Cycle_Variables_Loaded() |
--Called when variables_loaded event fires, usually on UI reload |
if (LANGUAGE_CYCLE.panel_visible) then |
ShowUIPanel(Language_Cycle_Panel); |
else |
HideUIPanel(Language_Cycle_Panel); |
end |
Langauge_Cycle_Lock_Backdrop(); |
-- For debugging |
-- Language_Cycle_Debug_Message(); |
-- Language_Cycle_Add_Message("Onload done"); |
end |
function Language_Cycle_OnEvent( self, event, ... ) |
if (event == "VARIABLES_LOADED") then |
Language_Cycle_Variables_Loaded(); |
-- Add LanguageCycle to myAddOns addons list |
if(myAddOnsFrame) then |
myAddOnsList.LanguageCycle = { |
name = "LanguageCycle", |
description = "A button to change your spoken language", |
version = Language_Cycle_Get_Version(), |
category = MYADDONS_CATEGORY_CHAT, |
frame = "Language_Cycle_Panel"}; |
end |
---------------------------------------------------------------------------------------- |
-- LDB Button Creation |
---------------------------------------------------------------------------------------- |
local defaults = { |
minimapIcon = { |
hide = false, |
minimapPos = 220, |
radius = 80, |
} |
} |
if not LANGUAGE_CYCLE then |
LANGUAGE_CYCLE = defaults |
else |
for k, v in pairs(defaults) do |
if LANGUAGE_CYCLE[k] == nil or type(LANGUAGE_CYCLE[k]) ~= type(v) then |
LANGUAGE_CYCLE[k] = v |
end |
end |
end |
local ButtonFrameObject = LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject(addonName, { |
type = "launcher", |
label = addonName, |
icon = ButtonTexture, |
OnClick = function(frame, button) |
GameTooltip:Hide() |
if button =="LeftButton" then |
Language_Cycle_Cycle(); |
elseif button =="MiddleButton" then |
local t = 0; |
while LC_Help_Text[t] ~= nil do |
DEFAULT_CHAT_FRAME:AddMessage(LC_Help_Text[t],0.0, 1.0, 0.0); |
t = t + 1; |
end |
elseif button == "RightButton" then |
Language_Cycle_Panel_Visible(); |
end |
end, |
OnTooltipShow = function(tooltip) |
if tooltip and tooltip.AddLine then |
tooltip:SetText("LanguageCycle") |
tooltip:AddLine("Left-Click: Cycle Language|nRight-Click: Show/Hide Built-in Panel|nMiddle-Click: Show Help",.8,.8,.8,1) |
tooltip:Show() |
end |
end, |
}) |
LibStub("LibDBIcon-1.0"):Register(addonName, ButtonFrameObject, LANGUAGE_CYCLE.minimapIcon) |
end |
if (event == "PLAYER_ENTERING_WORLD") then |
Language_Cycle_Init(); |
end |
end |
function Language_Cycle_Init() |
--Called when the Player_Entering_World event fires, usually on character login. |
-- May be called later, if initialization fails |
LC_realm_name = string.gsub(GetCVar("realmName"),"'",""); |
LC_player_name = UnitName("player"); |
LC_default_language = GetDefaultLanguage(); |
LC_verbose = false; |
Language_Cycle_Backdrop_Hide(true); |
Language_Cycle_Set_Text_Color(); |
local lang; |
if (LC_player_name == nil or LC_player_name == LC_unknown or LC_realm_name == nil) then |
else |
LC_player_id = LC_realm_name .. " " .. LC_player_name; |
end |
lang = Language_Cycle_Get_Lang(); |
if (lang == nil) then |
else |
Language_Cycle_Set_Lang(lang) |
end |
if (LC_default_language == nil) then |
else |
Language_Cycle_Party_Toggle_Text:SetText("Speak " .. LC_default_language .. " in Party/Guild chat:"); |
end |
Language_Cycle_Set_Party_Checkbutton(); |
LC_verbose = true; |
-- For debugging |
-- Language_Cycle_Debug_Message(); |
-- Language_Cycle_Add_Message("Entering World Done"); |
end |
function Language_Cycle_OnUpdate( self, elapsed ) |
if (not LC_player_id) then |
Language_Cycle_Init(); |
end |
end |
function Language_Cycle_Set_Lang(lang) |
-- Updates the button text, chat window and returns a chat window message |
Language_Cycle_Button:SetText(lang); |
DEFAULT_CHAT_FRAME.editBox.language = lang; |
if (LC_verbose) then |
Language_Cycle_Add_Message(string.format("Now speaking %s", lang)); |
end |
Language_Cycle_Save_Lang(lang); |
end |
function Language_Cycle_Save_Lang(lang) |
if (LC_player_id == nil) then |
else |
LANGUAGE_CYCLE.saved_language[LC_player_id] = lang; |
end |
end |
function Language_Cycle_Get_Lang() |
local lang, langID; |
if (LC_player_id == nil) then |
else |
lang = DEFAULT_CHAT_FRAME.editBox.language; |
if (LANGUAGE_CYCLE.saved_language[LC_player_id] == nil) then |
if (lang == nil) then |
lang = LC_default_language; |
end |
else |
lang = LANGUAGE_CYCLE.saved_language[LC_player_id]; |
end |
end |
return lang |
end |
function Language_Cycle_Debug_Message() |
local lang; |
lang = LANGUAGE_CYCLE.saved_language[LC_player_id]; |
if (lang == nil) then |
lang = "unknown"; |
end |
if not(LC_player_name == nil) then |
message(LC_player_name .. " speaks " .. lang); |
else |
message("LC_player_name is nil"); |
end |
end |
function Language_Cycle_Toggle_Group(verbose) |
if (LANGUAGE_CYCLE.translate_group) then |
LANGUAGE_CYCLE.translate_group = false; |
if (verbose) then |
Language_Cycle_Add_Message("Guild/Party translation is now off."); |
end |
else |
LANGUAGE_CYCLE.translate_group = true; |
if (verbose) then |
Language_Cycle_Add_Message("Guild/Party translation is now on."); |
end |
end |
Language_Cycle_Set_Text_Color(); |
Language_Cycle_Set_Party_Checkbutton(); |
-- if (IsAddOnLoaded("Titan")) then |
-- TitanPanelButton_UpdateButton(TITAN_LANGUAGECYCLE_ID); |
-- end |
-- if (IsAddOnLoaded("FuBar")) then |
-- LanguageCycleFuBar:UpdateText() |
-- end |
end |
function Language_Cycle_Set_Party_Checkbutton() |
if (LANGUAGE_CYCLE.translate_group) then |
Language_Cycle_Party_Toggle:SetChecked(1); |
else |
Language_Cycle_Party_Toggle:SetChecked(0); |
end |
end |
function Language_Cycle_Set_Text_Color() |
if (LANGUAGE_CYCLE.translate_group) then |
Language_Cycle_Button:GetNormalFontObject():SetTextColor(1, 1, 1); |
else |
Language_Cycle_Button:GetNormalFontObject():SetTextColor(.5, 1, .5); |
end |
end |
function Language_Cycle_Slash(arg) |
if (arg == "" or arg == nil) then |
Language_Cycle_Cycle(); |
elseif (arg == "ver" or arg == "version") then |
Language_Cycle_Add_Message("LanguageCycle version: " .. LC_version); |
elseif (arg == "clear") then |
Language_Cycle_Clear(); |
elseif (arg == "stat" or arg == "status") then |
local msg = "Speaking: " .. LANGUAGE_CYCLE.saved_language[LC_player_id] .. "; Guild/Party translation is "; |
if (LANGUAGE_CYCLE.translate_group) then |
msg = msg .. "on."; |
else |
msg = msg .. "off."; |
end |
Language_Cycle_Add_Message(msg); |
elseif (arg == "party" or arg == "guild" or arg == "group" or arg =="toggle") then |
Language_Cycle_Toggle_Group(true); |
elseif (arg == "show" or arg == "hide") then |
Language_Cycle_Panel_Visible(); |
elseif (arg == "mm" or arg == "MM") then |
if (LANGUAGE_CYCLE.minimapIcon.hide == false) then |
LibStub("LibDBIcon-1.0"):Hide("LanguageCycle") |
LANGUAGE_CYCLE.minimapIcon.hide = true |
else |
LibStub("LibDBIcon-1.0"):Show("LanguageCycle") |
LANGUAGE_CYCLE.minimapIcon.hide = false |
end |
elseif (arg == "help") then |
local t = 0; |
while LC_Help_Text[t] ~= nil do |
DEFAULT_CHAT_FRAME:AddMessage(LC_Help_Text[t],0.0, 1.0, 0.0); |
t = t + 1; |
end |
end |
end |
function Language_Cycle_Clear() |
LANGUAGE_CYCLE.saved_language[LC_player_id] = nil; |
LANGUAGE_CYCLE.translate_group = true; |
Language_Cycle_Add_Message(string.format("Cleared language for %s", LC_player_name)); |
Language_Cycle_Button:SetText("Pref Cleared..."); |
Language_Cycle_Set_Text_Color(); |
end |
function Language_Cycle_Add_Message(msg) |
DEFAULT_CHAT_FRAME:AddMessage(msg,0.0,1.0,0.0); |
end |
-- Language cycle script |
-- Version 5.0.4.a |
local ButtonTexture = "Interface\\Addons\\LanguageCycle\\media\\LanguageCycleIcon" |
local addonName = "LanguageCycle" |
LC_player_id = nil; |
LC_panel_height = 0; |
LC_panel_width = 0; |
LC_version = "4.2.2, by Halya, Argent Dawn, EU"; |
LC_version = "5.3.0c, by Halya, Argent Dawn, EU"; |
LC_Help_Text={}; |
LC_Help_Text[0]="Language Cycle will respond to the following commands:"; |
LC_Help_Text[1]="- /lc : Toggles spoken language between racial/common"; |
externals: |
libs/LibStub: |
url: svn://svn.wowace.com/wow/libstub/mainline/trunk |
tag: latest |
libs/CallbackHandler-1.0: |
url: svn://svn.wowace.com/wow/callbackhandler/mainline/trunk/CallbackHandler-1.0 |
tag: latest |
libs/LibDataBroker-1.1: |
url: git://git.wowace.com/wow/libdatabroker-1-1/mainline.git |
tag: latest |
libs/LibDBIcon-1.0: |
url: svn://svn.wowace.com/wow/libdbicon-1-0/mainline/trunk |
tag: latest |
## X-Maintainers: Halya of Argent Dawn EU, Aenott of Earthen Ring EU. |
## SavedVariables: LANGUAGE_CYCLE |
LanguageCycle.xml |
Libs\LibStub\LibStub.lua |
Libs\CallbackHandler-1.0\CallbackHandler-1.0.lua |
Libs\LibDataBroker-1.1\LibDataBroker-1.1.lua |
Libs\LibDBIcon-1.0\LibDBIcon-1.0.lua |
LanguageCycle.xml |
## Interface: 50300 |
## Title: Lib: DataBrokerIcon-1.0 |
## Notes: Allows addons to register to recieve a lightweight minimap icon as an alternative to more heavy LDB displays. |
## Author: Rabbit |
## X-eMail: rabbit.magtheridon@mail.com |
## X-Category: Library |
## X-License: GPLv2 or later |
## X-Credits: copystring for Barrel. |
## X-Curse-Packaged-Version: r36-release |
## X-Curse-Project-Name: LibDBIcon-1.0 |
## X-Curse-Project-ID: libdbicon-1-0 |
## X-Curse-Repository-ID: wow/libdbicon-1-0/mainline |
libs\LibStub\LibStub.lua |
libs\CallbackHandler-1.0\CallbackHandler-1.0.lua |
libs\LibDataBroker-1.1\LibDataBroker-1.1.lua |
LibDBIcon-1.0\LibDBIcon-1.0.lua |
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 |
-- 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 |
<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> |
--[[ $Id: CallbackHandler-1.0.lua 895 2009-12-06 16:28:55Z nevcairiel $ ]] |
local MAJOR, MINOR = "CallbackHandler-1.0", 5 |
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" |
if type(self)~="table" and type(self)~="string" then |
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string 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. |
--[[ |
Name: DBIcon-1.0 |
Revision: $Rev: 34 $ |
Author(s): Rabbit (rabbit.magtheridon@gmail.com) |
Description: Allows addons to register to recieve a lightweight minimap icon as an alternative to more heavy LDB displays. |
Dependencies: LibStub |
License: GPL v2 or later. |
]] |
--[[ |
Copyright (C) 2008-2011 Rabbit |
This program is free software; you can redistribute it and/or |
modify it under the terms of the GNU General Public License |
as published by the Free Software Foundation; either version 2 |
of the License, or (at your option) any later version. |
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
]] |
----------------------------------------------------------------------- |
-- DBIcon-1.0 |
-- |
-- Disclaimer: Most of this code was ripped from Barrel but fixed, streamlined |
-- and cleaned up a lot so that it no longer sucks. |
-- |
local DBICON10 = "LibDBIcon-1.0" |
local DBICON10_MINOR = tonumber(("$Rev: 34 $"):match("(%d+)")) |
if not LibStub then error(DBICON10 .. " requires LibStub.") end |
local ldb = LibStub("LibDataBroker-1.1", true) |
if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end |
local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR) |
if not lib then return end |
lib.disabled = lib.disabled or nil |
lib.objects = lib.objects or {} |
lib.callbackRegistered = lib.callbackRegistered or nil |
lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib) |
lib.notCreated = lib.notCreated or {} |
function lib:IconCallback(event, name, key, value, dataobj) |
if lib.objects[name] then |
if key == "icon" then |
lib.objects[name].icon:SetTexture(value) |
elseif key == "iconCoords" then |
lib.objects[name].icon:UpdateCoord() |
elseif key == "iconR" then |
local _, g, b = lib.objects[name].icon:GetVertexColor() |
lib.objects[name].icon:SetVertexColor(value, g, b) |
elseif key == "iconG" then |
local r, _, b = lib.objects[name].icon:GetVertexColor() |
lib.objects[name].icon:SetVertexColor(r, value, b) |
elseif key == "iconB" then |
local r, g = lib.objects[name].icon:GetVertexColor() |
lib.objects[name].icon:SetVertexColor(r, g, value) |
end |
end |
end |
if not lib.callbackRegistered then |
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback") |
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback") |
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconR", "IconCallback") |
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconG", "IconCallback") |
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconB", "IconCallback") |
lib.callbackRegistered = true |
end |
-- Tooltip code ripped from StatBlockCore by Funkydude |
local function getAnchors(frame) |
local x, y = frame:GetCenter() |
if not x or not y then return "CENTER" end |
local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or "" |
local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM" |
return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf |
end |
local function onEnter(self) |
if self.isMoving then return end |
local obj = self.dataObject |
if obj.OnTooltipShow then |
GameTooltip:SetOwner(self, "ANCHOR_NONE") |
GameTooltip:SetPoint(getAnchors(self)) |
obj.OnTooltipShow(GameTooltip) |
GameTooltip:Show() |
elseif obj.OnEnter then |
obj.OnEnter(self) |
end |
end |
local function onLeave(self) |
local obj = self.dataObject |
GameTooltip:Hide() |
if obj.OnLeave then obj.OnLeave(self) end |
end |
-------------------------------------------------------------------------------- |
local onClick, onMouseUp, onMouseDown, onDragStart, onDragStop, onDragEnd, updatePosition |
do |
local minimapShapes = { |
["ROUND"] = {true, true, true, true}, |
["SQUARE"] = {false, false, false, false}, |
["CORNER-TOPLEFT"] = {false, false, false, true}, |
["CORNER-TOPRIGHT"] = {false, false, true, false}, |
["CORNER-BOTTOMLEFT"] = {false, true, false, false}, |
["CORNER-BOTTOMRIGHT"] = {true, false, false, false}, |
["SIDE-LEFT"] = {false, true, false, true}, |
["SIDE-RIGHT"] = {true, false, true, false}, |
["SIDE-TOP"] = {false, false, true, true}, |
["SIDE-BOTTOM"] = {true, true, false, false}, |
["TRICORNER-TOPLEFT"] = {false, true, true, true}, |
["TRICORNER-TOPRIGHT"] = {true, false, true, true}, |
["TRICORNER-BOTTOMLEFT"] = {true, true, false, true}, |
["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false}, |
} |
function updatePosition(button) |
local angle = math.rad(button.db and button.db.minimapPos or button.minimapPos or 225) |
local x, y, q = math.cos(angle), math.sin(angle), 1 |
if x < 0 then q = q + 1 end |
if y > 0 then q = q + 2 end |
local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND" |
local quadTable = minimapShapes[minimapShape] |
if quadTable[q] then |
x, y = x*80, y*80 |
else |
local diagRadius = 103.13708498985 --math.sqrt(2*(80)^2)-10 |
x = math.max(-80, math.min(x*diagRadius, 80)) |
y = math.max(-80, math.min(y*diagRadius, 80)) |
end |
button:SetPoint("CENTER", Minimap, "CENTER", x, y) |
end |
end |
function onClick(self, b) if self.dataObject.OnClick then self.dataObject.OnClick(self, b) end end |
function onMouseDown(self) self.isMouseDown = true; self.icon:UpdateCoord() end |
function onMouseUp(self) self.isMouseDown = false; self.icon:UpdateCoord() end |
do |
local function onUpdate(self) |
local mx, my = Minimap:GetCenter() |
local px, py = GetCursorPosition() |
local scale = Minimap:GetEffectiveScale() |
px, py = px / scale, py / scale |
if self.db then |
self.db.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360 |
else |
self.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360 |
end |
updatePosition(self) |
end |
function onDragStart(self) |
self:LockHighlight() |
self.isMouseDown = true |
self.icon:UpdateCoord() |
self:SetScript("OnUpdate", onUpdate) |
self.isMoving = true |
GameTooltip:Hide() |
end |
end |
function onDragStop(self) |
self:SetScript("OnUpdate", nil) |
self.isMouseDown = false |
self.icon:UpdateCoord() |
self:UnlockHighlight() |
self.isMoving = nil |
end |
local defaultCoords = {0, 1, 0, 1} |
local function updateCoord(self) |
local coords = self:GetParent().dataObject.iconCoords or defaultCoords |
local deltaX, deltaY = 0, 0 |
if not self:GetParent().isMouseDown then |
deltaX = (coords[2] - coords[1]) * 0.05 |
deltaY = (coords[4] - coords[3]) * 0.05 |
end |
self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY) |
end |
local function createButton(name, object, db) |
local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap) |
button.dataObject = object |
button.db = db |
button:SetFrameStrata("MEDIUM") |
button:SetSize(31, 31) |
button:SetFrameLevel(8) |
button:RegisterForClicks("anyUp") |
button:RegisterForDrag("LeftButton") |
button:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight") |
local overlay = button:CreateTexture(nil, "OVERLAY") |
overlay:SetSize(53, 53) |
overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder") |
overlay:SetPoint("TOPLEFT") |
local background = button:CreateTexture(nil, "BACKGROUND") |
background:SetSize(20, 20) |
background:SetTexture("Interface\\Minimap\\UI-Minimap-Background") |
background:SetPoint("TOPLEFT", 7, -5) |
local icon = button:CreateTexture(nil, "ARTWORK") |
icon:SetSize(17, 17) |
icon:SetTexture(object.icon) |
icon:SetPoint("TOPLEFT", 7, -6) |
button.icon = icon |
button.isMouseDown = false |
local r, g, b = icon:GetVertexColor() |
icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b) |
icon.UpdateCoord = updateCoord |
icon:UpdateCoord() |
button:SetScript("OnEnter", onEnter) |
button:SetScript("OnLeave", onLeave) |
button:SetScript("OnClick", onClick) |
if not db or not db.lock then |
button:SetScript("OnDragStart", onDragStart) |
button:SetScript("OnDragStop", onDragStop) |
end |
button:SetScript("OnMouseDown", onMouseDown) |
button:SetScript("OnMouseUp", onMouseUp) |
lib.objects[name] = button |
if lib.loggedIn then |
updatePosition(button) |
if not db or not db.hide then button:Show() |
else button:Hide() end |
end |
lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback |
end |
-- We could use a metatable.__index on lib.objects, but then we'd create |
-- the icons when checking things like :IsRegistered, which is not necessary. |
local function check(name) |
if lib.notCreated[name] then |
createButton(name, lib.notCreated[name][1], lib.notCreated[name][2]) |
lib.notCreated[name] = nil |
end |
end |
lib.loggedIn = lib.loggedIn or false |
-- Wait a bit with the initial positioning to let any GetMinimapShape addons |
-- load up. |
if not lib.loggedIn then |
local f = CreateFrame("Frame") |
f:SetScript("OnEvent", function() |
for _, object in pairs(lib.objects) do |
updatePosition(object) |
if not lib.disabled and (not object.db or not object.db.hide) then object:Show() |
else object:Hide() end |
end |
lib.loggedIn = true |
f:SetScript("OnEvent", nil) |
f = nil |
end) |
f:RegisterEvent("PLAYER_LOGIN") |
end |
local function getDatabase(name) |
return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db |
end |
function lib:Register(name, object, db) |
if not object.icon then error("Can't register LDB objects without icons set!") end |
if lib.objects[name] or lib.notCreated[name] then error("Already registered, nubcake.") end |
if not lib.disabled and (not db or not db.hide) then |
createButton(name, object, db) |
else |
lib.notCreated[name] = {object, db} |
end |
end |
function lib:Lock(name) |
if not lib:IsRegistered(name) then return end |
if lib.objects[name] then |
lib.objects[name]:SetScript("OnDragStart", nil) |
lib.objects[name]:SetScript("OnDragStop", nil) |
end |
local db = getDatabase(name) |
if db then db.lock = true end |
end |
function lib:Unlock(name) |
if not lib:IsRegistered(name) then return end |
if lib.objects[name] then |
lib.objects[name]:SetScript("OnDragStart", onDragStart) |
lib.objects[name]:SetScript("OnDragStop", onDragStop) |
end |
local db = getDatabase(name) |
if db then db.lock = nil end |
end |
function lib:Hide(name) |
if not lib.objects[name] then return end |
lib.objects[name]:Hide() |
end |
function lib:Show(name) |
if lib.disabled then return end |
check(name) |
lib.objects[name]:Show() |
updatePosition(lib.objects[name]) |
end |
function lib:IsRegistered(name) |
return (lib.objects[name] or lib.notCreated[name]) and true or false |
end |
function lib:Refresh(name, db) |
if lib.disabled then return end |
check(name) |
local button = lib.objects[name] |
if db then button.db = db end |
updatePosition(button) |
if not button.db or not button.db.hide then |
button:Show() |
else |
button:Hide() |
end |
if not button.db or not button.db.lock then |
button:SetScript("OnDragStart", onDragStart) |
button:SetScript("OnDragStop", onDragStop) |
else |
button:SetScript("OnDragStart", nil) |
button:SetScript("OnDragStop", nil) |
end |
end |
function lib:GetMinimapButton(name) |
return lib.objects[name] |
end |
function lib:EnableLibrary() |
lib.disabled = nil |
for name, object in pairs(lib.objects) do |
if not object.db or not object.db.hide then |
object:Show() |
updatePosition(object) |
end |
end |
for name, data in pairs(lib.notCreated) do |
if not data.db or not data.db.hide then |
createButton(name, data[1], data[2]) |
lib.notCreated[name] = nil |
end |
end |
end |
function lib:DisableLibrary() |
lib.disabled = true |
for name, object in pairs(lib.objects) do |
object:Hide() |
end |
end |
LibDataBroker is a small WoW addon library designed to provide a "MVC":http://en.wikipedia.org/wiki/Model-view-controller interface for use in various addons. |
LDB's primary goal is to "detach" plugins for TitanPanel and FuBar from the display addon. |
Plugins can provide data into a simple table, and display addons can receive callbacks to refresh their display of this data. |
LDB also provides a place for addons to register "quicklaunch" functions, removing the need for authors to embed many large libraries to create minimap buttons. |
Users who do not wish to be "plagued" by these buttons simply do not install an addon to render them. |
Due to it's simple generic design, LDB can be used for any design where you wish to have an addon notified of changes to a table. |
h2. Links |
* "API documentation":http://github.com/tekkub/libdatabroker-1-1/wikis/api |
* "Data specifications":http://github.com/tekkub/libdatabroker-1-1/wikis/data-specifications |
* "Addons using LDB":http://github.com/tekkub/libdatabroker-1-1/wikis/addons-using-ldb |
-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $ |
-- 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 |
-- 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] |
-- Check to see is this version of the stub is obsolete |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
-- LibStub:NewLibrary(major, minor) |
-- major (string) - the major version of the library |
-- minor (string or number ) - the minor version of the library |
-- |
-- returns nil if a newer or same version of the lib is already present |
-- returns empty library object or old library object if upgrade is needed |
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.") |
return self.libs[major], oldminor |
end |
-- LibStub:GetLibrary(major, [silent]) |
-- major (string) - the major version of the library |
-- silent (boolean) - if true, library is optional, silently return nil if its not found |
-- |
-- throws an error if the library can not be found (except silent is set) |
-- returns the library object if found |
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) |
return self.libs[major], self.minors[major] |
end |
function LibStub:IterateLibraries() return pairs(self.libs) end |
-- LibStub:IterateLibraries() |
-- |
-- Returns an iterator for the currently registered libraries |
function LibStub:IterateLibraries() |
return pairs(self.libs) |
end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
## Interface: 50001 |
## Title: Lib: LibStub |
## Notes: Universal Library Stub |
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel |
## X-Website: http://www.wowace.com/addons/libstub/ |
## X-Category: Library |
## X-License: Public Domain |
## X-Curse-Packaged-Version: 1.0.3-50001 |
## X-Curse-Project-Name: LibStub |
## X-Curse-Project-ID: libstub |
## X-Curse-Repository-ID: wow/libstub/mainline |
LibStub.lua |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
-- Pretend like loaded libstub is old and doesn't have :IterateLibraries |
assert(LibStub.minor) |
LibStub.minor = LibStub.minor - 0.0001 |
LibStub.IterateLibraries = nil |
loadfile("../LibStub.lua")() |
assert(type(LibStub.IterateLibraries)=="function") |
-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created |
LibStub.IterateLibraries = 123 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created |
LibStub.minor = LibStub.minor + 0.0001 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
-- Again with a huge number |
LibStub.minor = LibStub.minor + 1234567890 |
loadfile("../LibStub.lua")() |
assert(LibStub.IterateLibraries == 123) |
print("OK") |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy |
assert(lib) -- should return the library table |
assert(not oldMinor) -- should not return the old minor, since it didn't exist |
-- the following is to create data and then be able to check if the same data exists after the fact |
function lib:MyMethod() |
end |
local MyMethod = lib.MyMethod |
lib.MyTable = {} |
local MyTable = lib.MyTable |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail |
assert(not newLib) -- should not return since out of date |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail |
assert(not newLib) -- should not return since out of date |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version |
assert(newLib) -- library table |
assert(rawequal(newLib, lib)) -- should be the same reference as the previous |
assert(newOldMinor == 1) -- should return the minor version of the previous version |
assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved |
assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number) |
assert(newLib) -- library table |
assert(newOldMinor == 2) -- previous version was 2 |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number) |
assert(newLib) |
assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string) |
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string |
assert(newLib) |
assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string) |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
for major, library in LibStub:IterateLibraries() do |
-- check that MyLib doesn't exist yet, by iterating through all the libraries |
assert(major ~= "MyLib") |
end |
assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking |
assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error. |
local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib |
assert(lib) -- check it exists |
assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference |
assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version |
local count=0 |
for major, library in LibStub:IterateLibraries() do |
-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries |
if major == "MyLib" then -- we found it! |
count = count +1 |
assert(rawequal(library, lib)) -- verify that the references are equal |
end |
end |
assert(count == 1) -- verify that we actually found it, and only once |
debugstack = debug.traceback |
strmatch = string.match |
loadfile("../LibStub.lua")() |
local proxy = newproxy() -- non-string |
assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata |
local success, ret = pcall(LibStub.GetLibrary, proxy, true) |
assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered. |
assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it. |
assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement |
--[[ $Id: CallbackHandler-1.0.lua 895 2009-12-06 16:28:55Z nevcairiel $ ]] |
local MAJOR, MINOR = "CallbackHandler-1.0", 5 |
--[[ $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 |
regfunc = function(...) self[method](self,...) end |
end |
else |
-- function ref with self=object or self="addonId" |
if type(self)~="table" and type(self)~="string" then |
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2) |
-- 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! |