Using the Interface Options Addons panel
Blizzard's InterfaceOptions frame can also display configuration options for third-party addons. This page describes how an addon can take advantage of the built-in Interface options UI.
The functionality described on this page is documented primarily in comments in FrameXML/InterfaceOptionsFrame.lua; search for "HOWTO: Add new categories of options."
Contents |
Summary
The InterfaceOptions framework requires an addon to supply its own configuration frame (panel). The supplied panel will be repositioned by FrameXML and displayed when the addon's configuration category is selected.
When the user presses the Okay, Cancel or Defaults buttons on the Interface Options frame, the panels will be notified by calling specific functions in the supplied frame table.
API Functions
The following functions are provided in FrameXML to interact with the InterfaceOptions framework:
- InterfaceOptions_AddCategory(panel[, _, position])
- Adds a configuration panel (with the fields described in #Panel fields below set) to the category list. The optional position argument (number) allows addons to insert top-level panels at arbitrary positions in the category list.
- InterfaceOptionsFrame_OpenToCategory(panelName or panel)
- Opens the Interface Options frame and navigates to the specified panel.
- InterfaceOptionsFrame_Show()
- Toggles visibility of the Interface Options frame.
Panel fields
The InterfaceOptions code uses certain fields on the configuration panel to interact with the panel:
- name
- Required, String - name displayed in the Interface Options category list (your addon name, or a panel-specific name)
- parent
- Optimal, String - the panel.name value of the parent configuration panel, used to display a hierarchical category tree. If the parent panel is not specified or does not exist, the panel is displayed as a top-level panel.
- refresh
- Optional, Function - called when the frame is initially displayed, and after requesting the default values to be restored.
- okay
- Optional, Function - called when the player presses the Okay button, indicating that settings should be saved.
- cancel
- Optional, Function - called when the player presses the Cancel button, indicating that changes made should be discarded.
- default
- Optional, Function - called when the player presses the Defaults button, indicating that default settings for the addon should be restored.
Thus, the minimum required code to create a custom Interface Options panel is:
local panel = CreateFrame("FRAME")
panel.name = "My Awesome Addon"
InterfaceOptions_AddCategory(panel)
Example XML with Okay and Cancel buttons
This example is taken from an addon called SC_ChaChing, available from http://wowui.incgamers.com/?p=mod&m=4934.
The XML frame
All we need to do first is to create the Frame. As we are using the Interface Options - Addon panels, we do not need to use any sizing or movement options.
The OnLoad script calls the Panel_OnLoad() function.
- XML Frame
<Frame name="SC_ChaChingGUIFrame">
. . .
<Scripts>
<OnLoad>
SC_ChaChingPanel_OnLoad(self);
</OnLoad>
</Scripts>
</Frame>
The Lua function
All we need to do with this function, is to set the name of the panel. Along with the Functions needed for the Okay and Cancel Buttons. Then to call the function that adds the Category to the Interface Options - Addon Category list.
- Lua Function
function SC_ChaChingPanel_OnLoad(panel)
. . .
-- Set the name for the Category for the Panel
--
panel.name = "SC_ChaChing " .. GetAddOnMetadata("SC_ChaChing", "Version");
-- When the player clicks okay, run this function.
--
panel.okay = function (self) SC_ChaChingPanel_Close(); end;
-- When the player clicks cancel, run this function.
--
panel.cancel = function (self) SC_ChaChingPanel_CancelOrLoad(); end;
-- Add the panel to the Interface Options
--
InterfaceOptions_AddCategory(panel);
end
Example entirely in Lua
MyAddon = {};
MyAddon.panel = CreateFrame( "Frame", "MyAddonPanel", UIParent );
-- Register in the Interface Addon Options GUI
-- Set the name for the Category for the Options Panel
MyAddon.panel.name = "MyAddon";
-- Add the panel to the Interface Options
InterfaceOptions_AddCategory(MyAddon.panel);
-- Make a child panel
MyAddon.childpanel = CreateFrame( "Frame", "MyAddonChild", MyAddon.panel);
MyAddon.childpanel.name = "MyChild";
-- Specify childness of this panel (this puts it under the little red [+], instead of giving it a normal AddOn category)
MyAddon.childpanel.parent = MyAddon.panel.name;
-- Add the child to the Interface Options
InterfaceOptions_AddCategory(MyAddon.childpanel);
Removing an existing options panel
FrameXML does not provide an API to remove an existing addon options panel from the list. Should you want to do so, you could use the following function:
local function RemoveInterfaceOptions(frameName, bParent)
-- Ensure that the variables passed are valid
assert(type(frameName) == "string" and (type(bParent) == "boolean" or bParent == nil), 'Syntax: RemoveInterfaceOptions(frameName[, bParent])');
-- Setup local variables
local removeList = {};
local nextFreeArraySpace = 1;
-- If the name given is NOT a parent frame
if not(bParent) then
-- Add this frame to the list to be deleted
removeList[frameName] = true;
end
-- Loop though Bliz's Interface Options Frames looking for the frames to remove
for i=1, #INTERFACEOPTIONS_ADDONCATEGORIES do
-- Store this Interface frame
local v = INTERFACEOPTIONS_ADDONCATEGORIES[i];
-- Check if this is the frame we want to remove or if bParent
-- the child of the want we want to remove
-- or just one we want to keep
if (removeList[v.name] or (bParent and v.parent == frameName)) or (bParent and removeList[v.parent]) then
-- Wipe this frame from the array by making it 'true'
removeList[v.name] = true;
else
-- We want to keep this frame so move it up the array
-- to remove any holes caused by the deleted frames
INTERFACEOPTIONS_ADDONCATEGORIES[nextFreeArraySpace] = INTERFACEOPTIONS_ADDONCATEGORIES[i];
nextFreeArraySpace = nextFreeArraySpace + 1;
end;
end;
-- Loop though all of the interface frames after the last good one removing them
for i=nextFreeArraySpace, #INTERFACEOPTIONS_ADDONCATEGORIES do
INTERFACEOPTIONS_ADDONCATEGORIES[i] = nil;
end;
-- Tell Bliz's interface frame to update now to reflect the removed frames
InterfaceAddOnsList_Update();
end
The function takes a string argument frameName, which specifies which panel (along with all of its children) should be removed from the category list. If the optional boolean argument bParent is true, only panels with the specified frameName as there parent (and their children) will be removed.
Notes
- The InterfaceOptions framework calls the panel okay/cancel/default/refresh methods using pcall: you will ordinarily not be notified of any errors that occur. For debugging reasons, it may be convenient to wrap your code in an xpcall, ensuring that any errors are displayed:
function panel.okay() xpcall(function() -- your original panel.okay() code goes here end, geterrorhandler()) end