Thursday, January 1, 2009

Fun with AceConfig-3.0

My first hacked up solution to the channel lock problem was a quick-n-dirty little addon that I created using the Dongle framework. Dongle is a great addon framework for things that need a bit more than nothing, but not as much as a full-featured configurable UI.

When I decided to work toward releasing ChannelLock (after pressure from guildies to give it up) I realized that doing the config UI I wanted using Dongle and native Wow UI manipulation would have been, to put it mildly, a pain in the ass. On the other hand, using AceConfig would make it easy.

Converting the DB code from Dongle to AceConfig was basically a no-op. AceDB-3.0 doesn’t use a mixin any more, while dongle does, but with a few minor changes, it just worked.

But the whole reason I made this switch was the get the integration with the in-game addon config system for free. Ultimately I wanted the tree in the addon list to have the following entries

  • ChannelLock – shows “about” info
    • Channels – config for the channel setups
    • Profiles – standard Ace3 profile management

For the “about” info, I’ve been using Tekkub’s tekKonfigAboutPanel.lua code for a while. It is simple and “just works”. But I hadn’t tried to integrate it with Ace3 config before.

Getting all of this to work as expected took some experimentation, but ultimately it was quite easy:

LibStub("AceConfig-3.0"):RegisterOptionsTable("ChannelLock", self.options )
LibStub("tekKonfig-AboutPanel").new(nil, "ChannelLock")

(Line numbers added to enable better explanation of the code.)

Line 1 takes the Lua table stored in self.options (it is just a standard Ace3Config table) and registers it with the AceConfig-3.0 registry using the name “ChannelLock”. This let us later add the options described in the table to the config system, to slash commands, etc.

Line 2 uses Tekkubs code to create an About box panel that contains various bits of information from the TOC file. By passing nil as the first parameter to new(), it tells the library to make this a root node in the config tree. The name is passed as the second parameter.

So far so good. We’ve got our root config node and we’ve registered our options table. Before I show you the next bit, however, let’s take a look at what is inside the options table. It looks something like this:

self.options = {
type = 'group',
name = "ChannelLock",
args = {
channels = {
name = 'Channels',
type = 'group',
args = {},

profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)

The trick is that the table contains two sub-tables: channels and profiles. The channels table is filled in dynamically by other code in my addon and the profiles table is filled in by the AceDBOptions-3.0 library. That library automatically creates an options table for all the typical profile operations (copy, new, delete, etc.) so I don’t have to.

We’ve registered the table with the AceConfig registry up above, now what we want to do is insert the channels and profile sub-tables as separate pages underneath the root page. We do that using the AceConfigDialog library and the AddToBlizOptions method. The arguments are: registered table name, display text, parent and sub-table key. The code looks like this:

LibStub("AceConfigDialog-3.0"):AddToBlizOptions("ChannelLock", "Channels", "ChannelLock", "channels")
LibStub("AceConfigDialog-3.0"):AddToBlizOptions("ChannelLock", "Profiles", "ChannelLock", "profiles")

Line 1 adds the channels subtable and Line 2 adds the profiles subtable.

That’s it!

No comments:

Post a Comment