Using the Interface Options Addons panel

From Wowpedia
Jump to: navigation, search

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."

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