Wowpedia
Advertisement

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.
panel 
Frame - A panel with widgets (children) to control an AddOn.
addOn 
boolean? - Identifies an AddOn is from a third party; however, the argment has no effect because the function body checks issecure().
position 
number? - Position in the list of panels; omitting defaults to alphabetical order.
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")

f.defaults = {
	someOption = true,
}

function f:OnEvent(event, addOnName)
	if addOnName == "HelloWorld" then
		HelloWorldDB = HelloWorldDB or CopyTable(self.defaults)
		self.db = HelloWorldDB
		self:SetupOptions()
		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:SetupOptions()
	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")
	cb.SetValue = function(_, value)
		self.db.someOption = (value == "1") -- value can be either "0" or "1"
	end
	cb:SetChecked(self.db.someOption) -- set the initial checked state

	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

SlashCmdList.HELLOW = function(msg, editBox)
	-- https://github.com/Stanzilla/WoWUIBugs/issues/89
	InterfaceOptionsFrame_OpenToCategory(f.panel)
	InterfaceOptionsFrame_OpenToCategory(f.panel)  
end

SLASH_HELLOW1 = "/helloworld"
SLASH_HELLOW2 = "/hw"

Patch changes

References

 
  1. ^ Daniel Yates (Meorawr) 2021-04-13. InterfaceOptionsFrame_OpenToCategory requires two calls to open addon settings (#89). WoWUIBugs at GitHub.
  2. ^ 2008-10-14, UIOptionsFrame.lua, version 3.0.2.9056, near line 583, archived at Townlong-Yak
  3. ^ Shadnix 2020-11-13. ScrollFrame in the WoW Interface Options AddOn Panel. Cosmo Canyon.
Advertisement