CallbackHandler is a back-end utility library that makes it easy for a library to fire its events to interested parties. It removes the need for addons to be aware of e.g. AceEvent.
The one remaining use for AceEvent Messages is messages that do not have a fixed source - ones that multiple libraries or addons can fire.
Including CallbackHandler-1.0 into your project
Library
if using the WoWAce repositories
- setup an external pointing to svn://svn.wowace.com/wow/callbackhandler/mainline/trunk/CallbackHandler-1.0 in the .pkgmeta file
- disable nolib creation by adding enable-nolib-creation: no to the .pkgmeta file
- set up your <library>.toc file to load CallbackHandler-1.0.xml (in case you support stand alone loading of the lib)
- don't load CallbackHandler-1.0 via the xml file ment for embedded loading of your lib
- don't set CallbackHandler-1.0 as X-embeded or OptDep
otherwise
- get a copy of the current version
- copy CallbackHandler-1.0.lua into your library's folder
- set up your <library>.toc file to load CallbackHandler-1.0.lua (in case you support stand alone loading of the lib)
- don't load CallbackHandler-1.0 via the xml file ment for embedded loading of your lib
- don't set CallbackHandler-1.0 as X-embeded or OptDep
AddOn
if using the WoWAce repositories
- set up an external pointing to svn://svn.wowace.com/wow/callbackhandler/mainline/trunk/CallbackHandler-1.0 in the .pkgmeta file
- set up your <addon>.toc or embeds.xml file to load CallbackHandler-1.0.xml
- don't set CallbackHandler-1.0 as X-embeded or OptDep
otherwise
- get a copy of the current version
- copy CallbackHandler-1.0.lua into your addon's folder or a subfolder of it
- set up your <addon>.toc or embeds.xml file to load CallbackHandler-1.0.lua
- don't set CallbackHandler-1.0 as X-embeded or OptDep
Mixing in the CallbackHandler functions in your library
MyLib.callbacks = MyLib.callbacks or
LibStub("CallbackHandler-1.0"):New(MyLib)
This adds 3 methods to your library:
- MyLib.RegisterCallback(self, "eventName"[, method, [arg]])
- MyLib.UnregisterCallback(self, "eventname")
- MyLib.UnregisterAllCallbacks(self)
Make sure that the passed in self is your addon, and not the library itself, so the double-colon syntax will not work.
The "MyLib.callbacks" object is the callback registry itself, which you need to keep track of across library upgrades.
Firing events
Assuming your callback registry is "MyLib.callbacks", firing named events is as easy as:
MyLib.callbacks:Fire("EventName", arg1, arg2, ...)
All arguments supplied to :Fire() are passed to the functions listening to the event.
Advanced uses
Renaming the methods
You can specify your own names for the methods installed by CallbackHandler:
MyLib.callbacks= MyLib.callbacks or
LibStub("CallbackHandler-1.0"):New(MyLib,
"MyRegisterFunc", "MyUnregisterFunc", "MyUnregisterAllFunc" or false)
Giving false as the name for UnregisterAll means that you do not want to give users access to that API at all - it will not be installed.
Tracking events being used
In some cases, it makes sense to know which events are being requested by your users. Perhaps to enable/disable code needed to track them.
CallbackHandler will always call registry:OnUsed() and :OnUnused() when an event starts/stops being used:
function MyLib.callbacks:OnUsed(target, eventname)
-- "target" is == MyLib here
print("Someone just registered for "..eventname.."!")
end
function MyLib.callbacks:OnUnused(target, eventname)
print("Noone wants "..eventname.." any more")
end
"OnUsed" is only called if the event was previously unused. "OnUnused" is only called when the last user unregisters from an event. In other words, you won't see an "OnUnused" unless "OnUsed" has been called for an event. And you won't ever see two "OnUsed" in a row without "OnUnused" in between for an event.
Multiple event registries
As you may or may not know, CallbackHandler is the workhorse of [[AceEvent-3.0|AceEvent]]. It is used twice in AceEvent: once for in-game events, which cannot be fired by users, and once for "messages", which can be fired by users.
Providing multiple registries in AceEvent was as easy as:
AceEvent.events = AceEvent.events or
LibStub("CallbackHandler-1.0"):New(AceEvent,
"RegisterEvent", "UnregisterEvent", "UnregisterAllEvents")
AceEvent.messages = AceEvent.messages or
LibStub("CallbackHandler-1.0"):New(AceEvent,
"RegisterMessage", "UnregisterMessage", "UnregisterAllMessages")
AceEvent.SendMessage = AceEvent.messages.Fire
Of course, there is also some code in AceEvent to do the actual driving of in-game events (using OnUsed and OnUnused), but this is really the core of it.
------------------------------------------------------------------------
r11 | mikk | 2009-09-17 10:51:46 +0000 (Thu, 17 Sep 2009) | 1 line
Changed paths:
A /tags/1.0.5 (from /trunk:10)
Tagging as 1.0.5
------------------------------------------------------------------------
r10 | arrowmaster | 2009-09-17 10:50:07 +0000 (Thu, 17 Sep 2009) | 1 line
Changed paths:
M /trunk/CallbackHandler-1.0.toc
D /trunk/CallbackHandler-1.0.xml
Load LibStub from the toc and remove root CallbackHandler-1.0.xml file to avoid confusion for addon authors on which xml to use
------------------------------------------------------------------------
r9 | mikk | 2009-09-17 10:38:10 +0000 (Thu, 17 Sep 2009) | 1 line
Changed paths:
M /trunk/CallbackHandler-1.0/CallbackHandler-1.0.lua
Ripping out nevc's changes which have many problems and cause errors out in the field. Bump to 1.0.5.
------------------------------------------------------------------------
r8 | nevcairiel | 2009-09-16 11:21:37 +0000 (Wed, 16 Sep 2009) | 2 lines
Changed paths:
M /trunk/CallbackHandler-1.0.toc
Bump the .toc while we're at it.
------------------------------------------------------------------------
r7 | nevcairiel | 2009-09-16 11:19:08 +0000 (Wed, 16 Sep 2009) | 2 lines
Changed paths:
M /trunk/CallbackHandler-1.0/CallbackHandler-1.0.lua
Bail out early in the Register function if we're trying to register the exact same callback function.
------------------------------------------------------------------------
Installation Guide
- Exit "World of Warcraft" completely
- Download the mod you want to install
- Make a folder on your desktop called "My Mods"
- Save the .zip/.rar files to this folder.
- If, when you try to download the file, it automatically "opens" it... you need to RIGHT click on the link and "save as..." or "Save Target As".
- Extract the file - commonly known as 'unzipping'
Do this ONE FILE AT A TIME!
- Windows
- Windows XP has a built in ZIP extractor. Double click on the file to open it, inside should be the file or folders needed. Copy these outside to the "My Mods" folder.
- WinRAR: Right click the file, select "Extract Here"
- WinZip: You MUST make sure the option to "Use Folder Names" is CHECKED or it will just extract the files and not make the proper folders how the Authors designed
- Mac Users
- StuffitExpander: Double click the archive to extract it to a folder in the current directory.
- Verify your WoW Installation Path
That is where you are running WoW from and THAT is where you need to install your mods.
- Move to the Addon folder
- Open your World of Warcraft folder. (default is C:\Program Files\World of Warcraft\)
- Go into the "Interface" folder.
- Go into the "AddOns" folder.
- In a new window, open the "My Mods" folder.
- The "My Mods" folder should have the "Addonname" folder in it.
- Move the "Addonname" folder into the "AddOns" folder
- Start World of Warcraft
- Make sure AddOns are installed
- Log in
- At the Character Select screen, look in lower left corner for the "addons" button.
- If button is there: make sure all the mods you installed are listed and make sure "load out of date addons" is checked.
- If the button is NOT there: means you did not install the addons properly. Look at the above screenshots. Try repeating the steps or getting someone who knows more about computers than you do to help.
Translations
When you download a mod, please be sure that the mod is compatible with your translation of wow. Some mods only work on the US versions, while some only work on some of the various European versions. These variations are called "Localizations".
TOC Numbers (Out of Date Mods)
When Blizzard patches WoW, they change the Interface number. This means that all mods will be "out of date" unless or until the author releases a new version for that interface. Some people go into the .toc files and update the numbers themselves, but this is STRONGLY advised against as it will cause problems locating possible incompatibilities addons. When you log into WoW after a patch, you DO NOT have to delete your interface directory. All you have to do is simply tell WoW to ignore the interface numbers and load all the mods anyway. All you have to do is, while at the "character select" screen, look in the lower left corner and click on the "addons" button. A window will pop up listing all your installed mods.
If you look in the upper left corner of that window there should be a box that says "Load Out of Date AddOns". You want to CHECK this box. Now simply go into WoW normally and all your mods should load. As of the 1.9 patch, you will have to do this after EVERY patch/update that Blizzard posts! If you encounter any problems with a mod after a patch, please be sure to let the author of the mod know so they can fix it.
See also: About "Out Of Date AddOns"
Mac Support
WoW addons are not platformed based. As such, they can be used on either Mac or PC. You can extract both .zip and .rar files on a Mac using StuffitExpander.
Directory Structure
World of Warcraft
|_ Interface
|_AddOns
|_*AddonName*
|_ *AddonName*.toc
|_ *AddonName*.xml
|_ *AddonName*.lua
|_ (possibly others as well)...