The Interface window includes a tab for third-party AddOns to share a common look and feel. This tutorial expands on instructions in the source code at FrameXML/InterfaceOptionsFrame.lua:483
.
Minimum requirements[]
It is minimally necessary to create a frame (panel), assign the .name
field, and pass it to InterfaceOptions_AddCategory():
local panel = CreateFrame("Frame")
panel.name = "MyAddOn" -- see panel fields
InterfaceOptions_AddCategory(panel) -- see InterfaceOptions API
-- add widgets to the panel as desired
local title = panel:CreateFontString("ARTWORK", nil, "GameFontNormalLarge")
title:SetPoint("TOP")
title:SetText("MyAddOn")
Panel fields[]
- Fields used when registering a new panel:
-
- name
- string - Name in the list of panels (customarily the AddOn name, unless it is a sub-panel).
- parent
- string? - The name of another panel to appear as a its sub-panel. If omitted, or if the other panel is not found, then this panel remains top-level.
- Fields used during user interaction:
-
- refresh
- function? - Callback when the panel first appears and also after default().
- okay
- function? - Callback when the user presses the Okay button to save settings.
- cancel
- function? - Callback when the user presses the Cancel button to discard changes.
- default
- function? - Callback when the user presses the Default button to restore default settings; followed by refresh().
InterfaceOptions API[]
- InterfaceOptions_AddCategory(panel [, addOn, position])
- Adds a configuration panel.
- InterfaceAddOnsList_Update()
- Prepares the InterfaceOptionsFrameAddOns buttons list, ensuring future calls to InterfaceOptionsFrame_OpenToCategory() will succeed.[1]
- InterfaceOptionsFrame_OpenToCategory(panel)
- Opens the Interface window to the chosen panel; however, this may fail the first time it is called unless preceeded by InterfaceAddOnsList_Update().
- panel
- Frame|string - The registered panel, or its name.
- InterfaceOptionsFrame_Show()
- Toggles visibility of the Interface Options frame.
Details[]
- The panel's parent, anchors and visibility are controlled by the InterfaceOptions API.
- okay(), cancel(), default() and refresh() are called using pcall() so errors in one AddOn do not prevent another from applying changes. During debugging, it is necessary to wrap code in xpcall to identify errors.
function panel.okay()
xpcall(function()
-- your original panel.okay() code goes here
end, geterrorhandler())
end
Examples[]
Fitting many options inside the border texture using a ScrollFrame:
local panel = CreateFrame("Frame")
panel.name = "MyAddOn"
InterfaceOptions_AddCategory(panel)
-- Create the scrolling parent frame and size it to fit inside the texture
local scrollFrame = CreateFrame("ScrollFrame", nil, panel, "UIPanelScrollFrameTemplate")
scrollFrame:SetPoint("TOPLEFT", 3, -4)
scrollFrame:SetPoint("BOTTOMRIGHT", -27, 4)
-- Create the scrolling child frame, set its width to fit, and give it an arbitrary minimum height (such as 1)
local scrollChild = CreateFrame("Frame")
scrollFrame:SetScrollChild(scrollChild)
scrollChild:SetWidth(InterfaceOptionsFramePanelContainer:GetWidth()-18)
scrollChild:SetHeight(1)
-- Add widgets to the scrolling child frame as desired
local title = scrollChild:CreateFontString("ARTWORK", nil, "GameFontNormalLarge")
title:SetPoint("TOP")
title:SetText("MyAddOn")
local footer = scrollChild:CreateFontString("ARTWORK", nil, "GameFontNormal")
footer:SetPoint("TOP", 0, -5000)
footer:SetText("This is 5000 below the top, so the scrollChild automatically expanded.")
HelloWorld example from Create a WoW AddOn in 15 Minutes:
local f = CreateFrame("Frame")
local defaults = {
someOption = true,
}
function f:OnEvent(event, addOnName)
if addOnName == "HelloWorld" then
HelloWorldDB = HelloWorldDB or CopyTable(defaults)
self.db = HelloWorldDB
self:InitializeOptions()
hooksecurefunc("JumpOrAscendStart", function()
if self.db.someOption then
print("Your character jumped.")
end
end)
end
end
f:RegisterEvent("ADDON_LOADED")
f:SetScript("OnEvent", f.OnEvent)
function f:InitializeOptions()
self.panel = CreateFrame("Frame")
self.panel.name = "HelloWorld"
local cb = CreateFrame("CheckButton", nil, self.panel, "InterfaceOptionsCheckButtonTemplate")
cb:SetPoint("TOPLEFT", 20, -20)
cb.Text:SetText("Print when you jump")
-- there already is an existing OnClick script that plays a sound, hook it
cb:HookScript("OnClick", function(_, btn, down)
self.db.someOption = cb:GetChecked()
end)
cb:SetChecked(self.db.someOption)
local btn = CreateFrame("Button", nil, self.panel, "UIPanelButtonTemplate")
btn:SetPoint("TOPLEFT", cb, 0, -40)
btn:SetText("Click me")
btn:SetWidth(100)
btn:SetScript("OnClick", function()
print("You clicked me!")
end)
InterfaceOptions_AddCategory(self.panel)
end
SLASH_HELLOW1 = "/hw"
SLASH_HELLOW2 = "/helloworld"
SlashCmdList.HELLOW = function(msg, editBox)
InterfaceOptionsFrame_OpenToCategory(f.panel)
end
Patch changes[]
- Patch 3.0.2 (2008-10-14): Third argument added to InterfaceOptions_AddCategory()[2]
- Patch 2.4.0 (2008-03-25): Added.[3]
References[]
- ^ Daniel Yates (Meorawr) 2021-04-13. InterfaceOptionsFrame_OpenToCategory requires two calls to open addon settings (#89). WoWUIBugs at GitHub.
- ^ 2008-10-14, UIOptionsFrame.lua, version 3.0.2.9056, near line 583, archived at Townlong-Yak
- ^ Shadnix 2020-11-13. ScrollFrame in the WoW Interface Options AddOn Panel. Cosmo Canyon.