# Ace3 Documentation — Full Reference
> Documentation for the Ace3 World of Warcraft addon framework: a suite of embeddable Lua libraries for addon structure, saved variables, configuration, events, timers, communication, serialization, localization, and GUI.
---
# Getting Started
URL: https://wowace-docs.nickdnk.workers.dev/getting-started
# Getting Started
New to World of Warcraft addons? You're in the right place. This guide takes you from an empty folder to a working addon
built on **Ace3**, and explains the pieces as it goes.
::: tip Using an AI assistant?
Load [`/llms-full.txt`](/llms-full.txt) into your AI's context for the complete Ace3 reference in one file.
:::
## What is Ace3, and why use it?
Ace3 is the most widely used **addon framework** for World of Warcraft: a set of small, focused libraries that handle
the repetitive parts of addon development so you can focus on what your addon does. It isn't one monolithic library; you
**embed only the pieces you need** and ignore the rest. What that buys you:
- **Less boilerplate**: a clean addon lifecycle (`OnInitialize` / `OnEnable` / `OnDisable`) instead of hand-wiring
[`ADDON_LOADED`](https://warcraft.wiki.gg/wiki/ADDON_LOADED).
- **Settings that just work**: [AceDB-3.0](/api/ace-db) stores `SavedVariables` with per-character profiles and smart
defaults.
- **Configuration for free**: describe your options once and [AceConfig-3.0](/api/ace-config) builds both a settings GUI
*and* slash commands from it.
- **Event handling**: [AceEvent-3.0](/api/ace-event) registers and dispatches game events and inter-addon messages, with
throttling for bursty events via [AceBucket-3.0](/api/ace-bucket).
- **Leak-free custom UI**: [AceGUI-3.0](/acegui/) builds windows from a pool of recycled widgets, so rebuilding your
interface never leaks frames for the session.
- **Addon communication**: [AceComm-3.0](/api/ace-comm) sends messages of any length to other copies of your addon
across the group or guild.
- **…and more**: timers ([AceTimer-3.0](/api/ace-timer)), data serialization ([AceSerializer-3.0](/api/ace-serializer)),
localization ([AceLocale-3.0](/api/ace-locale)), safe function hooks ([AceHook-3.0](/api/ace-hook)) and other
utilities.
The rest of this page walks through setting up an addon and points you at the library for each task.
## Download
Get the latest Ace3 release:
Download Ace3
Ace3 is a bundle of libraries you **embed inside your own addon**; there's no separate install for players. Unzip the
libraries you need into a `Libs/` subdirectory of your addon folder and reference them from your `.toc` or
`embeds.xml` (see [load order](#basic-addon-file-setup) below). You only need to ship the libraries you actually use.
## Basic Addon File Setup
Create a folder for your addon in `\Interface\AddOns`. The name must be unique; pick something
descriptive. Inside it you'll create a few text files.
### The `.toc` file
Name it the same as the folder, with `.toc` appended (e.g. `MyAddon/MyAddon.toc`). Lines beginning with `##` are
metadata; the rest is the list of files to load. The key field is `## Interface`, which declares the game build(s) your
addon supports:
```toc
## Interface: 11508, 20505
## Title: My Addon's Title
## Notes: Some notes about this addon.
## Author: Your Name Here
## Version: 0.1
## SavedVariables: MyAddonDB
```
::: tip Interface numbers & supporting multiple versions
Each interface number identifies a game version, and it increases as the game is patched. `## Interface` accepts a
**comma-separated list**, so one `.toc` can support several client flavors at once. The example targets two:
- **`11508`**: Classic Era, patch 1.15.8
- **`20505`**: Burning Crusade Classic (Anniversary), patch 2.5.5
Add the current retail number too (`120005` at the time of writing) to cover retail in the same file:
```toc
## Interface: 11508, 20505, 120005
```
Each listed client loads the addon and reports its own number; read it at runtime from
[`GetBuildInfo`](https://warcraft.wiki.gg/wiki/API_GetBuildInfo) (the `interfaceVersion` return, the 4th value, not the
build number).
The alternative to a CSV list is shipping a **separate TOC per flavor**, named with a suffix WoW recognizes:
- `MyAddon_Mainline.toc`: retail
- `MyAddon_Vanilla.toc`: Classic Era
- `MyAddon_TBC.toc`: Burning Crusade Classic
- `MyAddon_Wrath.toc`: Wrath Classic
- `MyAddon_Cata.toc`: Cataclysm Classic
- `MyAddon_Mists.toc`: Mists of Pandaria Classic
`_Mainline`/`_Classic` are lower priority than expansion-specific suffixes, so a `_Cata.toc` wins over `_Classic.toc` on
a Cataclysm Classic client. The CSV approach keeps everything in one file.
For the complete list of fields and flavor suffixes, see
the [TOC format reference](https://warcraft.wiki.gg/wiki/TOC_format).
:::
### Loading the libraries
After the metadata, the `.toc` lists the files to load, top to bottom. There are **two equivalent ways** to pull in the
Ace3 libraries; pick one. With the **direct** approach the library files are listed in the `.toc` itself; with the
**embeds.xml** approach that list moves to a separate file (the `embeds.xml` tab below), keeping your own code visually
separate. Either way, `LibStub` must be loaded first, followed by `CallbackHandler-1.0`.
::: code-group
```toc [MyAddon.toc (direct)]
## Interface: 11508, 20505
## Title: My Addon's Title
## SavedVariables: MyAddonDB
# load each library (LibStub first), then your own code
Libs\LibStub\LibStub.lua
Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml
Libs\AceAddon-3.0\AceAddon-3.0.xml
Core.lua
```
```toc [MyAddon.toc (with embeds.xml)]
## Interface: 11508, 20505
## Title: My Addon's Title
## SavedVariables: MyAddonDB
embeds.xml
Core.lua
```
```xml [embeds.xml]
```
:::
The **embeds.xml** tab pairs with the **with embeds.xml** `.toc`: that `.toc` loads `embeds.xml`, which in turn
`Include`s each library. Whichever approach you choose, libraries must load **before** the code that uses them:
::: warning Load order matters
WoW loads the files **in the exact order they are listed** in the `.toc` (and `embeds.xml`), top to bottom. A file can
only use code that was already loaded above it, so order dependencies correctly:
1. **`LibStub`** first: the shared version stub every Ace library registers with, and that you call as
`LibStub("AceX-3.0")` to fetch one.
2. **Libraries** next, before any of your code that calls `LibStub(...)` for them.
3. **Locale files** ([AceLocale](/api/ace-locale)) before the code that reads the translations.
4. **Your main code** (e.g. `Core.lua`) last, once its dependencies exist.
Getting this wrong gives `nil`/"attempt to index" errors at load because a library or value isn't available yet.
:::
### Your code files
`Core.lua` is just a conventional name. **WoW doesn't require any particular file name.** Name your `.lua` files
whatever you like and split your code across as many as you want; all that matters is that each file is listed in the
`.toc` (or an `embeds.xml`) and appears in the correct [load order](#basic-addon-file-setup) relative to the things it
depends on.
A common starting point is a single main file (named `Core.lua`, or after the addon)
using [AceAddon-3.0](/api/ace-addon), which gives your addon an object with an `OnInitialize`/`OnEnable`/`OnDisable`
lifecycle to hang the rest of your code on.
## A complete example
Here is a tiny but complete addon, **MyAddon**, that uses [AceAddon-3.0](/api/ace-addon) for its
lifecycle, [AceConsole-3.0](/api/ace-console) for output and a slash command, [AceEvent-3.0](/api/ace-event) to react to
a game event, [AceDB-3.0](/api/ace-db) to save settings, and [AceGUI-3.0](/acegui/) to open a small window. The folder
looks like this:
```
MyAddon/
├── MyAddon.toc
├── embeds.xml
├── Core.lua
└── Libs/
├── LibStub/
├── CallbackHandler-1.0/
├── AceAddon-3.0/
├── AceConsole-3.0/
├── AceEvent-3.0/
├── AceDB-3.0/
└── AceGUI-3.0/
```
::: code-group
```toc [MyAddon.toc]
## Interface: 11508, 20505
## Title: MyAddon
## Notes: A tiny example addon built on Ace3.
## Author: Your Name
## Version: 1.0
## SavedVariables: MyAddonDB
## IconTexture: Interface\Icons\TEMP
embeds.xml
Core.lua
```
```xml [embeds.xml]
```
```lua [Core.lua]
-- Create the addon object, mixing in AceConsole and AceEvent so their
-- methods are available directly on MyAddon (called via self).
local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0", "AceEvent-3.0")
-- AceGUI isn't embeddable; fetch it directly when you need it.
local AceGUI = LibStub("AceGUI-3.0")
-- Default settings. AceDB serves these until the user changes a value, and
-- never writes them to disk, so SavedVariables stays small.
local defaults = {
profile = {
greeting = "Hello from the button!",
timesOpened = 0,
},
}
-- Runs once, after this addon's SavedVariables have loaded.
function MyAddon:OnInitialize()
-- AceDB isn't embeddable; create the database here, matching the
-- "## SavedVariables: MyAddonDB" line in the TOC.
self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults)
self:RegisterChatCommand("myaddon", "OpenWindow") -- /myaddon
self:Print("loaded. Type /myaddon to open the window.")
end
-- Runs when the addon is enabled (first during PLAYER_LOGIN).
function MyAddon:OnEnable()
self:RegisterEvent("PLAYER_ENTERING_WORLD", "OnEnteringWorld")
end
-- Handlers receive the event name first, then the event's own arguments.
function MyAddon:OnEnteringWorld(event, isInitialLogin, isReloadingUi)
if isInitialLogin then
self:Print("Welcome!")
end
end
-- Slash-command handler: build and show a small AceGUI window.
function MyAddon:OpenWindow()
-- self.db.profile is the active profile's saved settings; this count
-- persists across reloads and sessions.
self.db.profile.timesOpened = self.db.profile.timesOpened + 1
local frame = AceGUI:Create("Frame")
frame:SetTitle("MyAddon")
frame:SetStatusText(("Opened %d time(s)"):format(self.db.profile.timesOpened))
frame:SetLayout("Flow")
-- release the widget back to the pool when the window is closed
frame:SetCallback("OnClose", function(widget) AceGUI:Release(widget) end)
local button = AceGUI:Create("Button")
button:SetText("Say hi")
button:SetWidth(140)
button:SetCallback("OnClick", function()
-- read a saved value back out
MyAddon:Print(MyAddon.db.profile.greeting)
end)
frame:AddChild(button)
end
```
:::
Drop this into `\Interface\AddOns\MyAddon\` (with the libraries unzipped into `Libs/`), reload, and `/myaddon`
opens the window.
## The Ace3 libraries
Each library is independent; embed only what you need.
**Addon Structure**
- [AceAddon-3.0](/api/ace-addon): addon object with `OnInitialize`/`OnEnable`/`OnDisable` lifecycle and modules.
- [AceConsole-3.0](/api/ace-console): chat output and slash commands.
- [AceEvent-3.0](/api/ace-event): register for game events and inter-addon messages.
- [AceBucket-3.0](/api/ace-bucket): throttle bursts of events into a single callback.
- [AceHook-3.0](/api/ace-hook): safely hook functions and frame scripts.
- [AceTimer-3.0](/api/ace-timer): one-shot and repeating timers.
**Persisting Data**
- [AceDB-3.0](/api/ace-db): `SavedVariables` with profiles, smart defaults and namespaces.
- [AceDBOptions-3.0](/api/ace-db-options): a ready-made profile-management options table.
**Configuration**
- [AceConfig-3.0](/api/ace-config): turn a single options table into a GUI and slash commands.
- [AceConfigCmd-3.0](/api/ace-config-cmd): command-line access to an options table.
- [AceConfigDialog-3.0](/api/ace-config-dialog): AceGUI dialog windows generated from an options table.
- [AceConfigRegistry-3.0](/api/ace-config-registry): central options-table registry and change notifications.
- [Options Tables](/api/ace-config-options): the options-table format reference.
**Communication & Data**
- [AceComm-3.0](/api/ace-comm): send addon messages of any length between clients.
- [AceSerializer-3.0](/api/ace-serializer): encode values to a string for transport or storage.
- [AceLocale-3.0](/api/ace-locale): localization with fallback to a base locale.
- [AceTab-3.0](/api/ace-tab): tab-completion for chat input.
- [CallbackHandler-1.0](/api/callback-handler): the callback/message dispatch engine the other libraries build on.
**Design & Presentation**
- [AceGUI-3.0](/acegui/): a pooled widget toolkit for building custom GUIs.
---
# Common Tasks
URL: https://wowace-docs.nickdnk.workers.dev/common-tasks
# Common Tasks
A quick map from "how do I…" to the Ace3 library that does it. Each entry links to the full reference; start
with [Getting Started](/getting-started) if you are setting up your first addon.
## How do I structure an addon and split it into modules?
Use [AceAddon-3.0](/api/ace-addon). It gives your addon an object with a clean lifecycle
([`OnInitialize`](/api/ace-addon#oninitialize), [`OnEnable`](/api/ace-addon#onenable),
[`OnDisable`](/api/ace-addon#ondisable)) and lets you split features into [modules](/api/ace-addon#newmodule).
## How do I save settings between sessions?
Use [AceDB-3.0](/api/ace-db). It wraps your `SavedVariables` with [scopes](/api/ace-db#scopes) (per-character,
per-realm, account-wide, and more), plus smart [defaults](/api/ace-db#defaults) that are never written to disk.
## How do I let users switch, copy and reset profiles?
Drop in [AceDBOptions-3.0](/api/ace-db-options): [`:GetOptionsTable`](/api/ace-db-options#getoptionstable) returns a
ready-made profile-management group you slot into your options table.
## How do I build an options screen and slash commands?
Describe your options once as an [options table](/api/ace-config-options), then register it
with [AceConfig-3.0](/api/ace-config#registeroptionstable). AceConfig builds both a settings GUI (
via [AceConfigDialog-3.0](/api/ace-config-dialog)) and slash commands (via [AceConfigCmd-3.0](/api/ace-config-cmd)) from
the same table.
## How do I react to a game event?
Use [AceEvent-3.0](/api/ace-event): [`:RegisterEvent`](/api/ace-event#registerevent) calls your handler when the event
fires, and registrations are cleaned up automatically when your addon is disabled.
## How do I handle events that fire in rapid bursts?
Use [AceBucket-3.0](/api/ace-bucket) to collect a burst of events and fire your callback once per interval instead of
once per event.
## How do I run code after a delay or on a repeat?
Use [AceTimer-3.0](/api/ace-timer): [`:ScheduleTimer`](/api/ace-timer#scheduletimer) for one-shot and
[`:ScheduleRepeatingTimer`](/api/ace-timer#schedulerepeatingtimer) for recurring work, both cancellable.
## How do I safely hook a Blizzard function?
Use [AceHook-3.0](/api/ace-hook). It tracks your hooks so they can be cleanly removed, keeping the hook chain intact
when you unhook.
## How do I print to chat or add a simple slash command?
Use [AceConsole-3.0](/api/ace-console): [`:Print`](/api/ace-console#print)/[`:Printf`](/api/ace-console#printf) for
output and [`:RegisterChatCommand`](/api/ace-console#registerchatcommand) for a quick command. For a full options-driven
command, prefer AceConfig above.
## How do I send data to other players running my addon?
Use [AceComm-3.0](/api/ace-comm) to send messages of any length over the addon channels,
and [AceSerializer-3.0](/api/ace-serializer) to turn Lua tables into strings to send (and back again on receipt).
## How do I translate or localize my addon?
Use [AceLocale-3.0](/api/ace-locale): register a base locale and per-language tables, then look up translated strings by
key.
## How do I build a custom window or UI?
Use [AceGUI-3.0](/acegui/), a pooled widget toolkit. Create a [container](/acegui/containers/frame) such as a `Frame`,
add [widgets](/acegui/widgets/button) (buttons, editboxes, sliders, dropdowns, trees, tabs), and release it when done so
the frames return to the pool.
## How do I add tab-completion to a slash command?
Use [AceTab-3.0](/api/ace-tab) to register completions that fire when the user presses Tab in a chat command.
---
# Getting Started
URL: https://wowace-docs.nickdnk.workers.dev/getting-started
# Getting Started
New to World of Warcraft addons? You're in the right place. This guide takes you from an empty folder to a working addon
built on **Ace3**, and explains the pieces as it goes.
::: tip Using an AI assistant?
Load [`/llms-full.txt`](/llms-full.txt) into your AI's context for the complete Ace3 reference in one file.
:::
## What is Ace3, and why use it?
Ace3 is the most widely used **addon framework** for World of Warcraft: a set of small, focused libraries that handle
the repetitive parts of addon development so you can focus on what your addon does. It isn't one monolithic library; you
**embed only the pieces you need** and ignore the rest. What that buys you:
- **Less boilerplate**: a clean addon lifecycle (`OnInitialize` / `OnEnable` / `OnDisable`) instead of hand-wiring
[`ADDON_LOADED`](https://warcraft.wiki.gg/wiki/ADDON_LOADED).
- **Settings that just work**: [AceDB-3.0](/api/ace-db) stores `SavedVariables` with per-character profiles and smart
defaults.
- **Configuration for free**: describe your options once and [AceConfig-3.0](/api/ace-config) builds both a settings GUI
*and* slash commands from it.
- **Event handling**: [AceEvent-3.0](/api/ace-event) registers and dispatches game events and inter-addon messages, with
throttling for bursty events via [AceBucket-3.0](/api/ace-bucket).
- **Leak-free custom UI**: [AceGUI-3.0](/acegui/) builds windows from a pool of recycled widgets, so rebuilding your
interface never leaks frames for the session.
- **Addon communication**: [AceComm-3.0](/api/ace-comm) sends messages of any length to other copies of your addon
across the group or guild.
- **…and more**: timers ([AceTimer-3.0](/api/ace-timer)), data serialization ([AceSerializer-3.0](/api/ace-serializer)),
localization ([AceLocale-3.0](/api/ace-locale)), safe function hooks ([AceHook-3.0](/api/ace-hook)) and other
utilities.
The rest of this page walks through setting up an addon and points you at the library for each task.
## Download
Get the latest Ace3 release:
Download Ace3
Ace3 is a bundle of libraries you **embed inside your own addon**; there's no separate install for players. Unzip the
libraries you need into a `Libs/` subdirectory of your addon folder and reference them from your `.toc` or
`embeds.xml` (see [load order](#basic-addon-file-setup) below). You only need to ship the libraries you actually use.
## Basic Addon File Setup
Create a folder for your addon in `\Interface\AddOns`. The name must be unique; pick something
descriptive. Inside it you'll create a few text files.
### The `.toc` file
Name it the same as the folder, with `.toc` appended (e.g. `MyAddon/MyAddon.toc`). Lines beginning with `##` are
metadata; the rest is the list of files to load. The key field is `## Interface`, which declares the game build(s) your
addon supports:
```toc
## Interface: 11508, 20505
## Title: My Addon's Title
## Notes: Some notes about this addon.
## Author: Your Name Here
## Version: 0.1
## SavedVariables: MyAddonDB
```
::: tip Interface numbers & supporting multiple versions
Each interface number identifies a game version, and it increases as the game is patched. `## Interface` accepts a
**comma-separated list**, so one `.toc` can support several client flavors at once. The example targets two:
- **`11508`**: Classic Era, patch 1.15.8
- **`20505`**: Burning Crusade Classic (Anniversary), patch 2.5.5
Add the current retail number too (`120005` at the time of writing) to cover retail in the same file:
```toc
## Interface: 11508, 20505, 120005
```
Each listed client loads the addon and reports its own number; read it at runtime from
[`GetBuildInfo`](https://warcraft.wiki.gg/wiki/API_GetBuildInfo) (the `interfaceVersion` return, the 4th value, not the
build number).
The alternative to a CSV list is shipping a **separate TOC per flavor**, named with a suffix WoW recognizes:
- `MyAddon_Mainline.toc`: retail
- `MyAddon_Vanilla.toc`: Classic Era
- `MyAddon_TBC.toc`: Burning Crusade Classic
- `MyAddon_Wrath.toc`: Wrath Classic
- `MyAddon_Cata.toc`: Cataclysm Classic
- `MyAddon_Mists.toc`: Mists of Pandaria Classic
`_Mainline`/`_Classic` are lower priority than expansion-specific suffixes, so a `_Cata.toc` wins over `_Classic.toc` on
a Cataclysm Classic client. The CSV approach keeps everything in one file.
For the complete list of fields and flavor suffixes, see
the [TOC format reference](https://warcraft.wiki.gg/wiki/TOC_format).
:::
### Loading the libraries
After the metadata, the `.toc` lists the files to load, top to bottom. There are **two equivalent ways** to pull in the
Ace3 libraries; pick one. With the **direct** approach the library files are listed in the `.toc` itself; with the
**embeds.xml** approach that list moves to a separate file (the `embeds.xml` tab below), keeping your own code visually
separate. Either way, `LibStub` must be loaded first, followed by `CallbackHandler-1.0`.
::: code-group
```toc [MyAddon.toc (direct)]
## Interface: 11508, 20505
## Title: My Addon's Title
## SavedVariables: MyAddonDB
# load each library (LibStub first), then your own code
Libs\LibStub\LibStub.lua
Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml
Libs\AceAddon-3.0\AceAddon-3.0.xml
Core.lua
```
```toc [MyAddon.toc (with embeds.xml)]
## Interface: 11508, 20505
## Title: My Addon's Title
## SavedVariables: MyAddonDB
embeds.xml
Core.lua
```
```xml [embeds.xml]
```
:::
The **embeds.xml** tab pairs with the **with embeds.xml** `.toc`: that `.toc` loads `embeds.xml`, which in turn
`Include`s each library. Whichever approach you choose, libraries must load **before** the code that uses them:
::: warning Load order matters
WoW loads the files **in the exact order they are listed** in the `.toc` (and `embeds.xml`), top to bottom. A file can
only use code that was already loaded above it, so order dependencies correctly:
1. **`LibStub`** first: the shared version stub every Ace library registers with, and that you call as
`LibStub("AceX-3.0")` to fetch one.
2. **Libraries** next, before any of your code that calls `LibStub(...)` for them.
3. **Locale files** ([AceLocale](/api/ace-locale)) before the code that reads the translations.
4. **Your main code** (e.g. `Core.lua`) last, once its dependencies exist.
Getting this wrong gives `nil`/"attempt to index" errors at load because a library or value isn't available yet.
:::
### Your code files
`Core.lua` is just a conventional name. **WoW doesn't require any particular file name.** Name your `.lua` files
whatever you like and split your code across as many as you want; all that matters is that each file is listed in the
`.toc` (or an `embeds.xml`) and appears in the correct [load order](#basic-addon-file-setup) relative to the things it
depends on.
A common starting point is a single main file (named `Core.lua`, or after the addon)
using [AceAddon-3.0](/api/ace-addon), which gives your addon an object with an `OnInitialize`/`OnEnable`/`OnDisable`
lifecycle to hang the rest of your code on.
## A complete example
Here is a tiny but complete addon, **MyAddon**, that uses [AceAddon-3.0](/api/ace-addon) for its
lifecycle, [AceConsole-3.0](/api/ace-console) for output and a slash command, [AceEvent-3.0](/api/ace-event) to react to
a game event, [AceDB-3.0](/api/ace-db) to save settings, and [AceGUI-3.0](/acegui/) to open a small window. The folder
looks like this:
```
MyAddon/
├── MyAddon.toc
├── embeds.xml
├── Core.lua
└── Libs/
├── LibStub/
├── CallbackHandler-1.0/
├── AceAddon-3.0/
├── AceConsole-3.0/
├── AceEvent-3.0/
├── AceDB-3.0/
└── AceGUI-3.0/
```
::: code-group
```toc [MyAddon.toc]
## Interface: 11508, 20505
## Title: MyAddon
## Notes: A tiny example addon built on Ace3.
## Author: Your Name
## Version: 1.0
## SavedVariables: MyAddonDB
## IconTexture: Interface\Icons\TEMP
embeds.xml
Core.lua
```
```xml [embeds.xml]
```
```lua [Core.lua]
-- Create the addon object, mixing in AceConsole and AceEvent so their
-- methods are available directly on MyAddon (called via self).
local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0", "AceEvent-3.0")
-- AceGUI isn't embeddable; fetch it directly when you need it.
local AceGUI = LibStub("AceGUI-3.0")
-- Default settings. AceDB serves these until the user changes a value, and
-- never writes them to disk, so SavedVariables stays small.
local defaults = {
profile = {
greeting = "Hello from the button!",
timesOpened = 0,
},
}
-- Runs once, after this addon's SavedVariables have loaded.
function MyAddon:OnInitialize()
-- AceDB isn't embeddable; create the database here, matching the
-- "## SavedVariables: MyAddonDB" line in the TOC.
self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults)
self:RegisterChatCommand("myaddon", "OpenWindow") -- /myaddon
self:Print("loaded. Type /myaddon to open the window.")
end
-- Runs when the addon is enabled (first during PLAYER_LOGIN).
function MyAddon:OnEnable()
self:RegisterEvent("PLAYER_ENTERING_WORLD", "OnEnteringWorld")
end
-- Handlers receive the event name first, then the event's own arguments.
function MyAddon:OnEnteringWorld(event, isInitialLogin, isReloadingUi)
if isInitialLogin then
self:Print("Welcome!")
end
end
-- Slash-command handler: build and show a small AceGUI window.
function MyAddon:OpenWindow()
-- self.db.profile is the active profile's saved settings; this count
-- persists across reloads and sessions.
self.db.profile.timesOpened = self.db.profile.timesOpened + 1
local frame = AceGUI:Create("Frame")
frame:SetTitle("MyAddon")
frame:SetStatusText(("Opened %d time(s)"):format(self.db.profile.timesOpened))
frame:SetLayout("Flow")
-- release the widget back to the pool when the window is closed
frame:SetCallback("OnClose", function(widget) AceGUI:Release(widget) end)
local button = AceGUI:Create("Button")
button:SetText("Say hi")
button:SetWidth(140)
button:SetCallback("OnClick", function()
-- read a saved value back out
MyAddon:Print(MyAddon.db.profile.greeting)
end)
frame:AddChild(button)
end
```
:::
Drop this into `\Interface\AddOns\MyAddon\` (with the libraries unzipped into `Libs/`), reload, and `/myaddon`
opens the window.
## The Ace3 libraries
Each library is independent; embed only what you need.
**Addon Structure**
- [AceAddon-3.0](/api/ace-addon): addon object with `OnInitialize`/`OnEnable`/`OnDisable` lifecycle and modules.
- [AceConsole-3.0](/api/ace-console): chat output and slash commands.
- [AceEvent-3.0](/api/ace-event): register for game events and inter-addon messages.
- [AceBucket-3.0](/api/ace-bucket): throttle bursts of events into a single callback.
- [AceHook-3.0](/api/ace-hook): safely hook functions and frame scripts.
- [AceTimer-3.0](/api/ace-timer): one-shot and repeating timers.
**Persisting Data**
- [AceDB-3.0](/api/ace-db): `SavedVariables` with profiles, smart defaults and namespaces.
- [AceDBOptions-3.0](/api/ace-db-options): a ready-made profile-management options table.
**Configuration**
- [AceConfig-3.0](/api/ace-config): turn a single options table into a GUI and slash commands.
- [AceConfigCmd-3.0](/api/ace-config-cmd): command-line access to an options table.
- [AceConfigDialog-3.0](/api/ace-config-dialog): AceGUI dialog windows generated from an options table.
- [AceConfigRegistry-3.0](/api/ace-config-registry): central options-table registry and change notifications.
- [Options Tables](/api/ace-config-options): the options-table format reference.
**Communication & Data**
- [AceComm-3.0](/api/ace-comm): send addon messages of any length between clients.
- [AceSerializer-3.0](/api/ace-serializer): encode values to a string for transport or storage.
- [AceLocale-3.0](/api/ace-locale): localization with fallback to a base locale.
- [AceTab-3.0](/api/ace-tab): tab-completion for chat input.
- [CallbackHandler-1.0](/api/callback-handler): the callback/message dispatch engine the other libraries build on.
**Design & Presentation**
- [AceGUI-3.0](/acegui/): a pooled widget toolkit for building custom GUIs.
---
# Common Tasks
URL: https://wowace-docs.nickdnk.workers.dev/common-tasks
# Common Tasks
A quick map from "how do I…" to the Ace3 library that does it. Each entry links to the full reference; start
with [Getting Started](/getting-started) if you are setting up your first addon.
## How do I structure an addon and split it into modules?
Use [AceAddon-3.0](/api/ace-addon). It gives your addon an object with a clean lifecycle
([`OnInitialize`](/api/ace-addon#oninitialize), [`OnEnable`](/api/ace-addon#onenable),
[`OnDisable`](/api/ace-addon#ondisable)) and lets you split features into [modules](/api/ace-addon#newmodule).
## How do I save settings between sessions?
Use [AceDB-3.0](/api/ace-db). It wraps your `SavedVariables` with [scopes](/api/ace-db#scopes) (per-character,
per-realm, account-wide, and more), plus smart [defaults](/api/ace-db#defaults) that are never written to disk.
## How do I let users switch, copy and reset profiles?
Drop in [AceDBOptions-3.0](/api/ace-db-options): [`:GetOptionsTable`](/api/ace-db-options#getoptionstable) returns a
ready-made profile-management group you slot into your options table.
## How do I build an options screen and slash commands?
Describe your options once as an [options table](/api/ace-config-options), then register it
with [AceConfig-3.0](/api/ace-config#registeroptionstable). AceConfig builds both a settings GUI (
via [AceConfigDialog-3.0](/api/ace-config-dialog)) and slash commands (via [AceConfigCmd-3.0](/api/ace-config-cmd)) from
the same table.
## How do I react to a game event?
Use [AceEvent-3.0](/api/ace-event): [`:RegisterEvent`](/api/ace-event#registerevent) calls your handler when the event
fires, and registrations are cleaned up automatically when your addon is disabled.
## How do I handle events that fire in rapid bursts?
Use [AceBucket-3.0](/api/ace-bucket) to collect a burst of events and fire your callback once per interval instead of
once per event.
## How do I run code after a delay or on a repeat?
Use [AceTimer-3.0](/api/ace-timer): [`:ScheduleTimer`](/api/ace-timer#scheduletimer) for one-shot and
[`:ScheduleRepeatingTimer`](/api/ace-timer#schedulerepeatingtimer) for recurring work, both cancellable.
## How do I safely hook a Blizzard function?
Use [AceHook-3.0](/api/ace-hook). It tracks your hooks so they can be cleanly removed, keeping the hook chain intact
when you unhook.
## How do I print to chat or add a simple slash command?
Use [AceConsole-3.0](/api/ace-console): [`:Print`](/api/ace-console#print)/[`:Printf`](/api/ace-console#printf) for
output and [`:RegisterChatCommand`](/api/ace-console#registerchatcommand) for a quick command. For a full options-driven
command, prefer AceConfig above.
## How do I send data to other players running my addon?
Use [AceComm-3.0](/api/ace-comm) to send messages of any length over the addon channels,
and [AceSerializer-3.0](/api/ace-serializer) to turn Lua tables into strings to send (and back again on receipt).
## How do I translate or localize my addon?
Use [AceLocale-3.0](/api/ace-locale): register a base locale and per-language tables, then look up translated strings by
key.
## How do I build a custom window or UI?
Use [AceGUI-3.0](/acegui/), a pooled widget toolkit. Create a [container](/acegui/containers/frame) such as a `Frame`,
add [widgets](/acegui/widgets/button) (buttons, editboxes, sliders, dropdowns, trees, tabs), and release it when done so
the frames return to the pool.
## How do I add tab-completion to a slash command?
Use [AceTab-3.0](/api/ace-tab) to register completions that fire when the user presses Tab in a chat command.
---
# AceAddon-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-addon
# AceAddon-3.0
AceAddon-3.0 is the conventional foundation of an Ace3 addon. It creates your addon object, provides lifecycle
callbacks ([`OnInitialize`](#oninitialize), [`OnEnable`](#onenable), [`OnDisable`](#ondisable)) that fire at the right
points during loading, and is where you declare which [other Ace3 libraries](/getting-started#the-ace3-libraries)
to [embed as mixins](#mixins-vs-on-demand-libraries).
## Usage
### Creating an addon object
Once LibStub and AceAddon-3.0 are referenced, your main Lua file creates an addon instance:
```lua
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
```
You can mix in other libraries by listing them; for example, adding AceConsole for chat/slash-command abilities:
```lua
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0")
```
### Mixins vs. on-demand libraries
The extra arguments to [`:NewAddon`](#newaddon) (and [`:NewModule`](#newmodule)) are libraries to **mix in** (embed).
Embedding copies that library's methods onto your addon object, so you call them on `self`:
```lua
local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0", "AceConsole-3.0")
function MyAddon:OnEnable()
self:RegisterEvent("PLAYER_REGEN_DISABLED") -- from AceEvent, now a method on MyAddon
self:Print("Enabled!") -- from AceConsole
end
```
The library uses your addon as its `self`, so it tracks registrations *per addon*, and AceAddon automatically cleans
them up when your addon is disabled (events unregistered, hooks removed, timers cancelled).
Contrast this with grabbing a library **on demand** via `LibStub`, which returns the single shared library object:
```lua
local AceEvent = LibStub("AceEvent-3.0")
-- not embedded: you must supply your own 'self' and manage cleanup yourself
AceEvent.RegisterEvent(MyAddon, "PLAYER_REGEN_DISABLED")
```
#### The `:Embed` method
Every embeddable library has an `:Embed(target)` method that copies its methods onto the table you pass, so you can then
call them on that table.
You normally never call it yourself. Listing a library in [`:NewAddon`](#newaddon) or [`:NewModule`](#newmodule) calls
`:Embed` on your addon for you, and the copying is identical either way. The reason to let AceAddon do it is
**cleanup**: AceAddon knows when your addon is enabled and disabled, so it can tell each embedded library to tear down
its registrations (events, hooks, timers) when the addon is disabled. A table you embed into by hand is not an addon
AceAddon manages, so nothing cleans it up.
In short: use `:NewAddon`/`:NewModule` to embed; call `:Embed` directly only to add a library's methods to an object
that isn't an Ace addon.
Use mixins for the embeddable libraries you call throughout your addon (**AceConsole, AceEvent, AceBucket, AceHook,
AceComm, AceTimer, AceSerializer**): it's less typing and you get automatic cleanup. Libraries that produce their own
objects or tables (**AceDB**, **AceConfig**/**AceConfigDialog**, **AceGUI**, **AceLocale**, **AceDBOptions**) are not
embeddable; fetch them with `LibStub(...)` when you need them.
::: tip
For modules, [`:SetDefaultModuleLibraries`](#setdefaultmodulelibraries) lets you embed the same set of libraries into
every module the addon creates, without repeating them on each [`:NewModule`](#newmodule) call.
:::
### Standard methods
AceAddon calls up to three lifecycle callbacks on your addon object: [`OnInitialize`](#oninitialize),
[`OnEnable`](#onenable) and [`OnDisable`](#ondisable). [`OnInitialize`](#oninitialize) runs once at load;
[`OnEnable`](#onenable)/[`OnDisable`](#ondisable) may run multiple times without a full UI reload.
The [Example](#example) below uses all three.
## Example
```lua
-- A small (but complete) addon, that doesn't do anything,
-- but shows usage of the callbacks.
local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
function MyAddon:OnInitialize()
-- do init tasks here, like loading the Saved Variables,
-- or setting up slash commands.
end
function MyAddon:OnEnable()
-- Do more initialization here, that really enables the use of your addon.
-- Register Events, Hook functions, Create Frames, Get information from
-- the game that wasn't available in OnInitialize
end
function MyAddon:OnDisable()
-- Unhook, Unregister Events, Hide frames that you created.
-- You would probably only use an OnDisable if you want to
-- build a "standby" mode, or be able to toggle modules on/off.
end
```
## API Reference
````apimethod
name: MyAddon:Disable
kind: method
returns: { type = "boolean", desc = "`true` or `false` depending on whether the addon was successfully disabled." }
---
Disables the addon if possible. This internally calls `AceAddon:DisableAddon()`, thus dispatching a [`OnDisable`](#ondisable) callback and disabling all modules of the addon.
`:Disable()` also sets the internal `enabledState` variable to false.
---
```lua
-- Disable MyAddon
MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
MyAddon:Disable()
```
````
````apimethod
name: MyAddon:DisableModule
kind: method
params:
- { name = "name", type = "string", desc = "Unique name of the module to disable." }
returns: { type = "boolean", desc = "`true` or `false` depending on whether the module was successfully disabled." }
---
Disables the module if possible. Short-hand function that retrieves the module via [`:GetModule`](#getmodule) and calls [`:Disable`](#disable) on the module object.
---
```lua
-- Disable MyModule using :GetModule
MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
MyModule = MyAddon:GetModule("MyModule")
MyModule:Disable()
-- Disable MyModule using the short-hand
MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
MyAddon:DisableModule("MyModule")
```
````
````apimethod
name: MyAddon:Enable
kind: method
returns: { type = "boolean", desc = "`true` or `false` depending on whether the addon was successfully enabled (`nil` if enabling was deferred because the addon is still queued for initialization)." }
---
Enables the addon if possible. This internally calls `AceAddon:EnableAddon()`, thus dispatching a [`OnEnable`](#onenable) callback and enabling all modules of the addon (unless explicitly disabled).
`:Enable()` also sets the internal `enabledState` variable to true. If the addon is still queued for initialization, enabling is deferred until after the init process completes.
---
```lua
-- Enable MyModule
MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
MyModule = MyAddon:GetModule("MyModule")
MyModule:Enable()
```
````
````apimethod
name: MyAddon:EnableModule
kind: method
params:
- { name = "name", type = "string", desc = "Unique name of the module to enable." }
returns: { type = "boolean", desc = "`true` or `false` depending on whether the module was successfully enabled." }
---
Enables the module if possible. Short-hand function that retrieves the module via [`:GetModule`](#getmodule) and calls [`:Enable`](#enable) on the module object.
---
```lua
-- Enable MyModule using :GetModule
MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
MyModule = MyAddon:GetModule("MyModule")
MyModule:Enable()
-- Enable MyModule using the short-hand
MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
MyAddon:EnableModule("MyModule")
```
````
````apimethod
name: MyAddon:GetModule
kind: method
params:
- { name = "name", type = "string", desc = "Unique name of the module." }
- { name = "silent", type = "boolean", optional = true, desc = "If true, the module is optional, silently return nil if its not found." }
returns: { type = "table", desc = "The module object, or `nil` if it could not be found and `silent` is set." }
---
Return the specified module from an addon object.
Throws an error if the addon object cannot be found (except if silent is set)
---
```lua
-- Get the Addon
MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-- Get the Module
MyModule = MyAddon:GetModule("MyModule")
```
````
````apimethod
name: MyAddon:GetName
kind: method
returns: { type = "string", desc = "The name of the addon or module." }
---
Returns the real name of the addon or module, without any prefix. For modules this returns the module's own name rather than the internal `parent_module` composite name.
````
````apimethod
name: MyAddon:IsEnabled
kind: method
returns: { type = "boolean", desc = "The current `enabledState` (`true` if enabled, `false` if disabled)." }
---
Query the enabledState of an addon.
---
```lua
if MyAddon:IsEnabled() then
MyAddon:Disable()
end
```
````
````apimethod
name: MyAddon:IterateModules
kind: method
returns: { type = "function", desc = "A `pairs` iterator over the addon's modules (yielding `name, module`)." }
---
Return an iterator of all modules associated to the addon.
---
```lua
-- Enable all modules
for name, module in MyAddon:IterateModules() do
module:Enable()
end
```
````
````apimethod
name: MyAddon:IterateEmbeds
kind: method
returns: { type = "function", desc = "A `pairs` iterator over the list of library names embedded in the addon." }
---
Returns an iterator of all libraries embedded in the addon.
---
```lua
for _, lib in MyAddon:IterateEmbeds() do
print("Embedded: " .. lib)
end
```
````
````apimethod
name: MyAddon:NewModule
kind: method
params:
- { name = "name", type = "string", desc = "Unique name of the module." }
- { name = "prototype|lib", type = "table|string", optional = true, desc = "A prototype table to mix into the module, or a library name to embed. If a table, its methods and values are mixed into the module; if a string, it is treated as the first library to embed." }
- { name = "...", type = "string", desc = "Additional libraries to embed into the module." }
returns: { type = "table", desc = "The newly created module object." }
---
Create a new module for the addon.
The new module can have its own embedded libraries and/or use a module prototype to be mixed into the module.
A module has the same functionality as a real addon, it can have modules of its own, and has the same API as an addon object.
---
```lua
-- Create a module with some embeded libraries
MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
-- Create a module with a prototype
local prototype = { OnEnable = function(self) print("OnEnable called!") end }
MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
```
````
````apimethod
name: MyAddon:SetDefaultModuleLibraries
kind: method
params:
- { name = "...", type = "string", desc = "Names of libraries to embed into every module created by this object." }
---
Set the default libraries to be mixed into all modules created by this object.
Note that you can only change the default module libraries before any module is created.
---
```lua
-- Create the addon object
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
-- Configure default libraries for modules (all modules need AceEvent-3.0)
MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
-- Create a module
MyModule = MyAddon:NewModule("MyModule")
```
````
````apimethod
name: MyAddon:SetDefaultModulePrototype
kind: method
params:
- { name = "prototype", type = "table", desc = "Default prototype for the new modules." }
---
Set the default prototype to use for new modules on creation.
Note that you can only change the default prototype before any module is created.
---
```lua
-- Define a prototype
local prototype = { OnEnable = function(self) print("OnEnable called!") end }
-- Set the default prototype
MyAddon:SetDefaultModulePrototype(prototype)
-- Create a module and explicitly Enable it
MyModule = MyAddon:NewModule("MyModule")
MyModule:Enable()
-- should print "OnEnable called!" now
```
**See also:** [NewModule]
````
````apimethod
name: MyAddon:SetDefaultModuleState
kind: method
params:
- { name = "state", type = "boolean", desc = "Default state for new modules, true for enabled, false for disabled." }
---
Set the default state in which new modules are being created.
Note that you can only change the default state before any module is created.
---
```lua
-- Create the addon object
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
-- Set the default state to "disabled"
MyAddon:SetDefaultModuleState(false)
-- Create a module and explicitly enable it
MyModule = MyAddon:NewModule("MyModule")
MyModule:Enable()
```
````
````apimethod
name: MyAddon:SetEnabledState
kind: method
params:
- { name = "state", type = "boolean", desc = "The state of an addon or module (enabled=true, disabled=false)." }
---
Set the state of an addon or module. This sets the internal `enabledState` and should only be called before any enabling actually happens, e.g. in/before [`OnInitialize`](#oninitialize).
---
```lua
function MyAddon:OnInitialize()
-- start disabled until the user opts in
self:SetEnabledState(false)
end
```
````
````apimethod
name: AceAddon:GetAddon
kind: method
params:
- { name = "name", type = "string", desc = "Unique name of the addon object." }
- { name = "silent", type = "boolean", optional = true, desc = "If true, the addon is optional, silently return nil if its not found." }
returns: { type = "table", desc = "The addon object, or `nil` if it could not be found and `silent` is set." }
---
Get the addon object by its name from the internal AceAddon registry.
Throws an error if the addon object cannot be found (except if silent is set).
````
````apimethod
name: AceAddon:IterateAddonStatus
kind: method
returns: { type = "function", desc = "A `pairs` iterator over the status registry (yielding `name, status`)." }
---
Get an iterator over the internal status registry.
---
```lua
-- Print a list of all enabled addons
for name, status in AceAddon:IterateAddonStatus() do
if status then
print("EnabledAddon: " .. name)
end
end
```
````
````apimethod
name: AceAddon:IterateAddons
kind: method
returns: { type = "function", desc = "A `pairs` iterator over all registered addons (yielding `name, addon`)." }
---
Get an iterator over all registered addons.
---
```lua
-- Print a list of all installed AceAddon's
for name, addon in AceAddon:IterateAddons() do
print("Addon: " .. name)
end
```
````
````apimethod
name: AceAddon:NewAddon
kind: method
params:
- { name = "object", type = "table", optional = true, desc = "Table to use as a base for the addon." }
- { name = "name", type = "string", desc = "Name of the addon object to create." }
- { name = "...", type = "string", desc = "Names of libraries to embed into the addon." }
returns: { type = "table", desc = "The new addon object, with all specified libraries embedded." }
---
Create a new AceAddon-3.0 addon.
Any libraries you specified will be embedded, and the addon will be scheduled for its [`OnInitialize`](#oninitialize) and [`OnEnable`](#onenable) callbacks. The final addon object, with all libraries embedded, will be returned.
`object` is not a true positional argument: the first argument is used as the base object only if it is a table, otherwise it is taken as the `name` and a fresh object is created. So `NewAddon("MyAddon", ...)` and `NewAddon(myTable, "MyAddon", ...)` are both valid.
---
```lua
-- Create a simple addon object
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
-- Create a Addon object based on the table of a frame
local MyFrame = CreateFrame("Frame")
MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
```
````
## Callbacks
AceAddon calls these lifecycle methods automatically if you define them — no registration required.
````apimethod
name: MyAddon:OnInitialize
kind: callback
---
Called once, directly after the addon is fully loaded, after its `SavedVariables` are available. The place to create your database, register options, set up slash commands, and do other one-time setup. Runs exactly once per session.
````
````apimethod
name: MyAddon:OnEnable
kind: callback
---
Called when the addon is enabled: the first time during the [`PLAYER_LOGIN`](https://warcraft.wiki.gg/wiki/PLAYER_LOGIN) event, when most game data is available. Register events, apply hooks, create frames and read game state here. May run more than once if the addon is toggled off and on (it is **not** tied to a UI reload).
````
````apimethod
name: MyAddon:OnDisable
kind: callback
---
Called when the addon is disabled. Undo what [`OnEnable`](#onenable) did: unregister events, remove hooks, hide frames. Only happens when the addon (or module) is explicitly disabled, so most addons that are never disabled won't need it.
````
````apimethod
name: MyAddon:OnModuleCreated
kind: callback
params:
- { name = "module", type = "table", desc = "The newly created module object." }
---
Called on the parent addon each time it creates a module (via [`:NewModule`](#newmodule)), if the addon defines it. Handy for applying shared setup to every module as it is created.
````
---
# AceConsole-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-console
# AceConsole-3.0
AceConsole-3.0 provides registration facilities for slash commands. You can register slash commands to your custom
functions and use the [`GetArgs`](#getargs) function to parse them to your addons individual needs.
## Usage
### Output
Call [`:Print`](#print) with the text to output. As a mixin it's available on your addon object:
```lua
-- AceConsole used as a mixin
MyAddon:Print("Hello, world!")
-- print to a specific chat frame
MyAddon:Print(ChatFrame1, "Hello, World!")
```
### Slash commands
Register a command (without the leading slash) and a handler (a method name or a function):
```lua
MyAddon:RegisterChatCommand("myslash", "MySlashProcessorFunc")
function MyAddon:MySlashProcessorFunc(input)
-- 'input' contains whatever follows the slash command
end
```
In many cases it's simpler to let [AceConfig](/api/ace-config) generate slash commands automatically.
## API Reference
````apimethod
name: AceConsole:Embed
kind: method
params:
- { name = "target", type = "table", desc = "Target object to embed AceConsole in." }
returns: { type = "table", desc = "The `target` object that was embedded." }
---
Copies AceConsole's methods onto `target` so you can call them on it directly. See [The `:Embed` method](/api/ace-addon#the-embed-method).
---
```lua
LibStub("AceConsole-3.0"):Embed(MyObject)
```
````
````apimethod
name: AceConsole:GetArgs
kind: method
params:
- { name = "str", type = "string", desc = "The raw argument string." }
- { name = "numargs", type = "number", default = "1", desc = "How many arguments to get." }
- { name = "startpos", type = "number", default = "1", desc = "Where in the string to start scanning." }
returns:
- { type = "string", desc = "One value per requested argument (`numargs` in total), in order. A missing argument is returned as `nil`." }
- { name = "nextposition", type = "number", desc = "Returned after the arguments: the position in the string just after the last parsed argument, to feed back as `startpos`. Returned as `1e9` once the end of the string is reached." }
---
Retrieve one or more space-separated arguments from a string.
Treats quoted strings and itemlinks as non-spaced.
---
```lua
function MyAddon:MySlashProcessorFunc(input)
local arg1, arg2 = self:GetArgs(input, 2)
end
```
````
````apimethod
name: AceConsole:IterateChatCommands
kind: method
returns: { type = "function", desc = "Iterator (`pairs`) over all commands." }
---
Get an iterator over all Chat Commands registered with AceConsole.
---
```lua
for command in self:IterateChatCommands() do
self:Print(command)
end
```
````
````apimethod
name: AceConsole:Print
kind: method
params:
- { name = "chatframe", type = "table", optional = true, desc = "Custom ChatFrame to print to (or any frame with an `.AddMessage` function)." }
- { name = "...", type = "any", desc = "List of any values to be printed." }
---
Print to [`DEFAULT_CHAT_FRAME`](https://warcraft.wiki.gg/wiki/DEFAULT_CHAT_FRAME) or given ChatFrame (anything with an `.AddMessage` function).
`chatframe` is not a true positional argument: `Print` takes only `...` and inspects the first value. If it is a table with an `.AddMessage` method it is used as the target frame; otherwise it is treated as the first value to print and output goes to `DEFAULT_CHAT_FRAME`.
````
````apimethod
name: AceConsole:Printf
kind: method
params:
- { name = "chatframe", type = "table", optional = true, desc = "Custom ChatFrame to print to (or any frame with an `.AddMessage` function)." }
- { name = "format", type = "string", desc = "Format string - same syntax as standard Lua `format()`." }
- { name = "...", type = "any", desc = "Arguments to the format string." }
---
Formatted (using [`format()`](https://warcraft.wiki.gg/wiki/Format)) print to `DEFAULT_CHAT_FRAME` or given ChatFrame (anything with an `.AddMessage` function).
As with [`:Print`](#print), `chatframe` is detected by type rather than position: the first argument is used as the target frame only if it is a table with an `.AddMessage` method, otherwise it is taken as the format string.
````
````apimethod
name: AceConsole:RegisterChatCommand
kind: method
params:
- { name = "command", type = "string", desc = "Chat command to be registered WITHOUT leading \"/\"." }
- { name = "func", type = "funcref|methodname", desc = "Function to call when the slash command is being used." }
- { name = "persist", type = "boolean", default = "true", desc = "When `false`, the command is tied to your addon's enabled state: AceConsole registers it when the addon (or module) is enabled and unregisters it when disabled. This only takes effect when AceConsole is embedded as a mixin, since the enable/disable hooks come from AceAddon. The default `true` keeps the command registered for the whole session." }
returns: { type = "boolean", desc = "`true` on successful registration." }
---
Register a simple chat command. Sets up the [`SlashCmdList`](https://warcraft.wiki.gg/wiki/World_of_Warcraft_API) entry and the `SLASH_*1` global for the command. If `func` is a string it is treated as a method name and invoked on the embedding object (`self`); otherwise it is used directly as the handler. Non-persisting commands are tracked so they can be re-registered/unregistered as the addon is enabled/disabled.
---
```lua
function MyAddon:OnEnable()
self:RegisterChatCommand("myslash", "MySlashProcessorFunc")
end
```
````
````apimethod
name: AceConsole:UnregisterChatCommand
kind: method
params:
- { name = "command", type = "string", desc = "Chat command to be unregistered WITHOUT leading \"/\"." }
---
Unregister a chatcommand.
````
---
# AceEvent-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-event
# AceEvent-3.0
AceEvent-3.0 provides event registration and secure dispatching. All dispatching is done
using [CallbackHandler-1.0](/api/callback-handler). AceEvent is a simple wrapper around CallbackHandler, and dispatches
all game events or addon message to the registrees.
## Usage
### Subscribing to events
```lua
MyAddon:RegisterEvent("NAME_OF_EVENT")
function MyAddon:NAME_OF_EVENT()
-- process the event
end
```
Specify a handler method/function instead of the default name:
```lua
MyAddon:RegisterEvent("NAME_OF_EVENT", "MyHandlerMethod")
MyAddon:RegisterEvent("NAME_OF_OTHER_EVENT", function() doSomethingSpiffy() end)
```
The first argument to a handler is always the event name, then the event's own arguments:
```lua
function MyAddon:NAME_OF_EVENT(eventName, arg1, arg2, arg3)
-- ...
end
```
### Inter-addon messages
Messages work like events but are fired by addons rather than the client:
```lua
MyAddon:RegisterMessage("NAME_OF_MESSAGE")
MyAddon:SendMessage("NAME_OF_MESSAGE")
MyAddon:SendMessage("NAME_OF_OTHER_MESSAGE", arg1, arg2)
```
Messages are local to the client. To talk between players' addons, use [AceComm](/api/ace-comm).
## API Reference
````apimethod
name: AceEvent:Embed
kind: method
params:
- { name = "target", type = "table", desc = "Target object to embed AceEvent in." }
returns: { type = "table", desc = "The `target` object that was embedded." }
---
Copies AceEvent's methods onto `target` so you can call them on it directly. See [The `:Embed` method](/api/ace-addon#the-embed-method).
````
````apimethod
name: AceEvent:RegisterEvent
kind: method
params:
- { name = "event", type = "string", desc = "The event to register for." }
- { name = "callback", type = "funcref|methodname", optional = true, desc = "The callback function to call when the event is triggered (defaults to a method with the event name)." }
- { name = "arg", type = "any", optional = true, desc = "An optional argument to pass to the callback function." }
---
Register for a Blizzard [Event](https://warcraft.wiki.gg/wiki/Events).
The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied). Any arguments to the event will be passed on after that.
---
```lua
function MyAddon:OnEnable()
self:RegisterEvent("BAG_UPDATE", "UpdateBags")
end
function MyAddon:UpdateBags(event, bagID)
-- ...
end
```
````
````apimethod
name: AceEvent:RegisterMessage
kind: method
params:
- { name = "message", type = "string", desc = "The message to register for." }
- { name = "callback", type = "funcref|methodname", optional = true, desc = "The callback function to call when the message is triggered (defaults to a method with the event name)." }
- { name = "arg", type = "any", optional = true, desc = "An optional argument to pass to the callback function." }
---
Register for a custom AceEvent-internal message.
The callback will be called with the optional `arg` as the first argument (if supplied), and the event name as the second (or first, if no arg was supplied). Any arguments to the event will be passed on after that.
````
````apimethod
name: AceEvent:SendMessage
kind: method
params:
- { name = "message", type = "string", desc = "The message to send." }
- { name = "...", type = "any", desc = "Any arguments to the message." }
---
Send a message over the AceEvent-3.0 internal message system to other addons registered for this message.
---
```lua
function MyAddon:SetFontSize(size)
self:SendMessage("MyAddon_ConfigChanged", "fontSize", size)
end
```
````
````apimethod
name: AceEvent:UnregisterEvent
kind: method
params:
- { name = "event", type = "string", desc = "The event to unregister." }
---
Unregister an event.
````
````apimethod
name: AceEvent:UnregisterMessage
kind: method
params:
- { name = "message", type = "string", desc = "The message to unregister." }
---
Unregister a message.
````
````apimethod
name: AceEvent:UnregisterAllEvents
kind: method
---
Unregister all events registered by this addon object (or custom "self").
---
```lua
function MyAddon:OnDisable()
self:UnregisterAllEvents()
end
```
````
````apimethod
name: AceEvent:UnregisterAllMessages
kind: method
---
Unregister all messages registered by this addon object (or custom "self").
---
```lua
function MyAddon:OnDisable()
self:UnregisterAllMessages()
end
```
````
---
# AceBucket-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-bucket
# AceBucket-3.0
A bucket to catch events in.
AceBucket-3.0 provides throttling of events that fire in bursts and your addon only needs to know about the full burst.
This Bucket implementation works as follows:
Initially, no schedule is running, and its waiting for the first event to happen.
The first event will start the bucket, and get the scheduler running, which will collect all events in the given
interval. When that interval is reached, the bucket is pushed to the callback and a new schedule is started. When a
bucket is empty after its interval, the scheduler is stopped, and the bucket is only listening for the next event to
happen, basically back in its initial state.
In addition, the buckets collect information about the `arg1` argument of the events that fire, and pass those as a
table to your callback. This functionality was mostly designed for the [`UNIT_*`](https://warcraft.wiki.gg/wiki/Events)
events.
The table will have the different values of `arg1` as keys, and the number of occurrences as their value, e.g.
```lua
{ ["player"] = 2, ["target"] = 1, ["party1"] = 1 }
```
AceBucket-3.0 requires [AceEvent-3.0](/api/ace-event) and [AceTimer-3.0](/api/ace-timer) to be available.
## Example
```lua
MyAddon = LibStub("AceAddon-3.0"):NewAddon("BucketExample", "AceBucket-3.0")
function MyAddon:OnEnable()
-- Register a bucket that listens to all the HP related events,
-- and fires once per second
self:RegisterBucketEvent({"UNIT_HEALTH", "UNIT_MAXHEALTH"}, 1, "UpdateHealth")
end
function MyAddon:UpdateHealth(units)
if units.player then
print("Your HP changed!")
end
end
```
## API Reference
````apimethod
name: AceBucket:Embed
kind: method
params:
- { name = "target", type = "table", desc = "Target object to embed AceBucket in." }
returns: { type = "table", desc = "The `target` object that was embedded." }
---
Copies AceBucket's methods onto `target` so you can call them on it directly. See [The `:Embed` method](/api/ace-addon#the-embed-method).
````
````apimethod
name: AceBucket:RegisterBucketEvent
returns: { type = "string", desc = "The handle of the bucket (for unregistering)." }
params:
- { name = "event", type = "string|table", desc = "The event to listen for, or a table of events." }
- { name = "interval", type = "number", desc = "The Bucket interval (burst interval), in seconds." }
- { name = "callback", type = "function|methodname", optional = true, desc = "The callback function, either as a function reference, or a string pointing to a method of the addon object. May be omitted only when `event` is a single string, in which case the event name is used as the method name." }
---
Register a Bucket for an event (or a set of events).
The first matching event starts the bucket and schedules a timer for `interval` seconds (via [AceTimer-3.0](/api/ace-timer)). All events that fire during the interval are collected, and when the interval elapses the `callback` is fired once with a table mapping each distinct `arg1` value to its number of occurrences (a `nil` `arg1` is stored under the key `"nil"`). If the bucket collected events, a new interval is scheduled; if it was empty, the timer is stopped and the bucket waits for the next event. Requires [AceEvent-3.0](/api/ace-event) and AceTimer-3.0 to be loaded.
---
```lua
MyAddon:RegisterBucketEvent("BAG_UPDATE", 0.2, "UpdateBags")
function MyAddon:UpdateBags()
-- do stuff
end
```
````
````apimethod
name: AceBucket:RegisterBucketMessage
returns: { type = "string", desc = "The handle of the bucket (for unregistering)." }
params:
- { name = "message", type = "string|table", desc = "The message to listen for, or a table of messages." }
- { name = "interval", type = "number", desc = "The Bucket interval (burst interval), in seconds." }
- { name = "callback", type = "function|methodname", optional = true, desc = "The callback function, either as a function reference, or a string pointing to a method of the addon object. May be omitted only when `message` is a single string, in which case the message name is used as the method name." }
---
Register a Bucket for an [AceEvent-3.0](/api/ace-event) addon message (or a set of messages).
Behaves identically to [`RegisterBucketEvent`](#registerbucketevent), except it listens for AceEvent-3.0 inter-addon messages instead of game events. Bursts of messages within `interval` seconds are coalesced and delivered to `callback` as a single table keyed by the distinct `arg1` values with their occurrence counts.
---
```lua
MyAddon:RegisterBucketMessage("SomeAddon_InformationMessage", 0.2, "ProcessData")
function MyAddon:ProcessData()
-- do stuff
end
```
````
````apimethod
name: AceBucket:UnregisterBucket
params:
- { name = "handle", type = "string", desc = "The handle of the bucket as returned by [`RegisterBucketEvent`](#registerbucketevent) or [`RegisterBucketMessage`](#registerbucketmessage)." }
---
Unregister any events and messages from the bucket and clear any remaining data.
Unregisters all events/messages the bucket was listening to, clears any data collected but not yet delivered, cancels the pending interval timer (if one is running), and recycles the internal bucket object for reuse.
---
```lua
function MyAddon:OnEnable()
self.bucket = self:RegisterBucketEvent("BAG_UPDATE", 0.2, "UpdateBags")
end
function MyAddon:StopWatching()
self:UnregisterBucket(self.bucket)
end
```
````
````apimethod
name: AceBucket:UnregisterAllBuckets
---
Unregister all buckets of the current addon object (or custom `self`). Iterates the registered buckets and calls [`UnregisterBucket`](#unregisterbucket) on each one whose owner is this object; buckets belonging to other objects are left untouched. This is called automatically when an embedding addon is disabled.
````
---
# AceHook-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-hook
# AceHook-3.0
AceHook-3.0 offers safe Hooking/Unhooking of functions, methods and frame scripts. Using AceHook-3.0 is recommended when
you need to unhook your hooks again, so the hook chain isn't broken when you manually restore the original function.
## Usage
Embedding as a mixin is best, so hooks are cleaned up automatically if the user disables your addon:
```lua
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceHook-3.0")
```
### Standard (pre-) hooks
A standard hook runs before the original and automatically calls the original afterward. Specify a function name, or an
object + method name:
```lua
MyAddon:Hook("APIFunctionName")
MyAddon:Hook(TargetObject, "TargetMethod")
```
By default the call is routed to a same-named method on your addon. Provide a custom handler if you prefer:
```lua
MyAddon:Hook("APIFunctionName", handlerFunc)
MyAddon:Hook("APIFunctionName", "handlerMethod")
```
To hook a secure function despite the tainting risk, pass `true` as the final argument:
```lua
MyAddon:Hook("APISecureFunctionName", handlerFunc, true)
```
### Raw hooks
A raw hook completely replaces the original: you must call it yourself (via `self.hooks`) if you want it to run:
```lua
MyAddon:RawHook("APIFunctionName")
function MyAddon:APIFunctionName(...)
-- call the original through self.hooks
self.hooks["APIFunctionName"](...)
end
```
### Secure (post-) hooks
Secure hooks run *after* the original; return values are ignored. Use these for protected Blizzard UI elements to avoid
taint:
```lua
MyAddon:SecureHook("APISecureFunctionName")
```
### Hooking scripts
Hook frame scripts with the `*Script` variants:
```lua
MyAddon:HookScript(TargetFrame, "ScriptName")
MyAddon:RawHookScript(TargetFrame, "ScriptName")
MyAddon:SecureHookScript(TargetFrame, "ScriptName")
```
### Checking for an existing hook
```lua
local hookexists, hookhandler = MyAddon:IsHooked("APIFunctionName")
```
## API Reference
````apimethod
name: AceHook:Embed
kind: method
params:
- { name = "target", type = "table", desc = "Target object to embed AceHook in." }
returns: { type = "table", desc = "The `target` object that was embedded." }
---
Copies AceHook's methods onto `target` so you can call them on it directly. See [The `:Embed` method](/api/ace-addon#the-embed-method).
````
````apimethod
name: AceHook:Hook
params:
- { name = "object", type = "table", optional = true, desc = "The object to hook a method from." }
- { name = "method", type = "string", desc = "The name of the method (if `object` is given), or the name of the function to hook." }
- { name = "handler", type = "function|methodname", optional = true, desc = "The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)." }
- { name = "hookSecure", type = "boolean", optional = true, desc = "If true, AceHook will allow hooking of secure functions." }
---
Hook a function or a method on an object.
The hook created will be a "safe hook", that means that your handler will be called before the hooked function ("Pre-Hook"), and you don't have to call the original function yourself, however you cannot stop the execution of the function, or modify any of the arguments/return values.
This type of hook is typically used if you need to know if some function got called, and don't want to modify it.
---
```lua
function MyAddon:OnEnable()
-- Hook ActionButton_UpdateHotkeys, overwriting the secure status
self:Hook("ActionButton_UpdateHotkeys", true)
end
function MyAddon:ActionButton_UpdateHotkeys(button, type)
print(button:GetName() .. " is updating its HotKey")
end
```
````
````apimethod
name: AceHook:RawHook
params:
- { name = "object", type = "table", optional = true, desc = "The object to hook a method from." }
- { name = "method", type = "string", desc = "The name of the method (if `object` is given), or the name of the function to hook." }
- { name = "handler", type = "function|methodname", optional = true, desc = "The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)." }
- { name = "hookSecure", type = "boolean", optional = true, desc = "If true, AceHook will allow hooking of secure functions." }
---
RawHook a function or a method on an object.
The hook created will be a "raw hook", that means that your handler will completely replace the original function, and your handler has to call the original function (or not, depending on your intentions).
The original function will be stored in `self.hooks[object][method]` or `self.hooks[functionName]` respectively.
This type of hook can be used for all purposes, and is usually the most common case when you need to modify arguments or want to control execution of the original function.
---
```lua
function MyAddon:OnEnable()
-- Hook ActionButton_UpdateHotkeys, overwriting the secure status
self:RawHook("ActionButton_UpdateHotkeys", true)
end
function MyAddon:ActionButton_UpdateHotkeys(button, type)
if button:GetName() == "MyButton" then
-- do stuff here
else
self.hooks.ActionButton_UpdateHotkeys(button, type)
end
end
```
````
````apimethod
name: AceHook:SecureHook
params:
- { name = "object", type = "table", optional = true, desc = "The object to hook a method from." }
- { name = "method", type = "string", desc = "The name of the method (if `object` is given), or the name of the function to hook." }
- { name = "handler", type = "function|methodname", optional = true, desc = "The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)." }
---
SecureHook a function or a method on an object.
This function is a wrapper around the [`hooksecurefunc`](https://warcraft.wiki.gg/wiki/API_hooksecurefunc) function in the WoW API. Using AceHook extends the functionality of secure hooks, and adds the ability to unhook once the hook isn't required anymore, or the addon is being disabled.
Secure Hooks should be used if the secure-status of the function is vital to its function, and taint would block execution. Secure Hooks are always called after the original function was called ("Post Hook"), and you cannot modify the arguments, return values or control the execution.
---
```lua
function MyAddon:OnEnable()
-- run our handler after the original UseAction fires
self:SecureHook("UseAction", "OnUseAction")
end
function MyAddon:OnUseAction(slot)
print("Action slot used: " .. slot)
end
```
````
````apimethod
name: AceHook:HookScript
params:
- { name = "frame", type = "table", desc = "The Frame to hook the script on." }
- { name = "script", type = "string", desc = "The script to hook." }
- { name = "handler", type = "function|methodname", optional = true, desc = "The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)." }
---
Hook a script handler on a frame.
The hook created will be a "safe hook", that means that your handler will be called before the hooked script ("Pre-Hook"), and you don't have to call the original function yourself, however you cannot stop the execution of the function, or modify any of the arguments/return values.
This is the frame script equivalent of the [`:Hook`](#hook) safe-hook. It would typically be used to be notified when a certain event happens to a frame.
---
```lua
function MyAddon:OnEnable()
-- Hook the OnShow of FriendsFrame
self:HookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
end
function MyAddon:FriendsFrameOnShow(frame)
print("The FriendsFrame was shown!")
end
```
````
````apimethod
name: AceHook:RawHookScript
params:
- { name = "frame", type = "table", desc = "The Frame to hook the script on." }
- { name = "script", type = "string", desc = "The script to hook." }
- { name = "handler", type = "function|methodname", optional = true, desc = "The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)." }
---
RawHook a script handler on a frame.
The hook created will be a "raw hook", that means that your handler will completely replace the original script, and your handler has to call the original script (or not, depending on your intentions).
The original script will be stored in `self.hooks[frame][script]`.
This type of hook can be used for all purposes, and is usually the most common case when you need to modify arguments or want to control execution of the original script.
---
```lua
function MyAddon:OnEnable()
-- Hook the OnShow of FriendsFrame
self:RawHookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
end
function MyAddon:FriendsFrameOnShow(frame)
-- Call the original function
self.hooks[frame].OnShow(frame)
-- Do our processing
-- .. stuff
end
```
````
````apimethod
name: AceHook:SecureHookScript
params:
- { name = "frame", type = "table", desc = "The Frame to hook the script on." }
- { name = "script", type = "string", desc = "The script to hook." }
- { name = "handler", type = "function|methodname", optional = true, desc = "The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)." }
---
SecureHook a script handler on a frame.
This function is a wrapper around the [`frame:HookScript`](https://warcraft.wiki.gg/wiki/API_ScriptObject_HookScript) function in the WoW API. Using AceHook extends the functionality of secure hooks, and adds the ability to unhook once the hook isn't required anymore, or the addon is being disabled.
Secure Hooks should be used if the secure-status of the function is vital to its function, and taint would block execution. Secure Hooks are always called after the original function was called ("Post Hook"), and you cannot modify the arguments, return values or control the execution.
---
```lua
function MyAddon:OnEnable()
-- run after the FriendsFrame's OnShow script
self:SecureHookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
end
function MyAddon:FriendsFrameOnShow(frame)
print("The FriendsFrame was shown!")
end
```
````
````apimethod
name: AceHook:Unhook
returns: { type = "boolean", desc = "`true` if a hook was removed, `false` if there was no active hook to remove." }
params:
- { name = "obj", type = "table", optional = true, desc = "The object or frame to unhook from." }
- { name = "method", type = "string", desc = "The name of the method, function or script to unhook from." }
---
Unhook from the specified function, method or script.
````
````apimethod
name: AceHook:UnhookAll
---
Unhook all existing hooks for this addon.
---
```lua
function MyAddon:OnDisable()
self:UnhookAll()
end
```
````
````apimethod
name: AceHook:IsHooked
returns:
- { type = "isHooked", desc = "Boolean: `true` if the function/method/script is hooked, otherwise `false`." }
- { type = "handler", desc = "Function|methodname: the registered handler if hooked, otherwise `nil`." }
params:
- { name = "obj", type = "table", optional = true, desc = "The object or frame to check." }
- { name = "method", type = "string", desc = "The name of the method, function or script to check." }
---
Check if the specific function, method or script is already hooked.
````
---
# AceTimer-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-timer
# AceTimer-3.0
AceTimer-3.0 provides a central facility for registering timers.
AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient data structure that allows
easy dispatching and fast rescheduling. Timers can be registered or canceled at any time, even from within a running
timer, without conflict or large overhead.
AceTimer is currently limited to firing timers at a frequency of 0.01s as this is what the WoW timer API restricts us
to.
All `:Schedule` functions will return a handle to the current timer, which you will need to store if you need to cancel
the timer you just registered.
## API Reference
````apimethod
name: AceTimer:Embed
kind: method
params:
- { name = "target", type = "table", desc = "Target object to embed AceTimer in." }
returns: { type = "table", desc = "The `target` object that was embedded." }
---
Copies AceTimer's methods onto `target` so you can call them on it directly. See [The `:Embed` method](/api/ace-addon#the-embed-method).
````
````apimethod
name: AceTimer:ScheduleTimer
returns: { type = "string", desc = "The timer handle, used to cancel the timer with [`:CancelTimer`](#canceltimer)." }
params:
- { name = "func", type = "function|methodname", desc = "Callback function for the timer pulse (funcref or method name)." }
- { name = "delay", type = "number", desc = "Delay for the timer, in seconds." }
- { name = "...", type = "any", desc = "An optional, unlimited amount of arguments to pass to the callback function." }
---
Schedule a new one-shot timer.
The timer will fire once in `delay` seconds, unless canceled before.
---
```lua
function MyAddon:OnEnable()
self:ScheduleTimer("TimerFeedback", 5)
end
function MyAddon:TimerFeedback()
print("5 seconds passed")
end
```
````
````apimethod
name: AceTimer:ScheduleRepeatingTimer
returns: { type = "string", desc = "The timer handle, used to cancel the timer with [`:CancelTimer`](#canceltimer)." }
params:
- { name = "func", type = "function|methodname", desc = "Callback function for the timer pulse (funcref or method name)." }
- { name = "delay", type = "number", desc = "Delay for the timer, in seconds." }
- { name = "...", type = "any", desc = "An optional, unlimited amount of arguments to pass to the callback function." }
---
Schedule a repeating timer.
The timer will fire every `delay` seconds, until canceled.
---
```lua
function MyAddon:OnEnable()
-- store the handle so the timer can be cancelled later
self.pulseTimer = self:ScheduleRepeatingTimer("Pulse", 5)
end
function MyAddon:Pulse()
-- runs every 5 seconds until cancelled
end
```
````
````apimethod
name: AceTimer:CancelTimer
returns: { type = "boolean", desc = "`true` if the timer was successfully cancelled, `false` if the id was invalid or the timer already fired/was cancelled." }
params:
- { name = "id", type = "string", desc = "The id of the timer, as returned by [`:ScheduleTimer`](#scheduletimer) or [`:ScheduleRepeatingTimer`](#schedulerepeatingtimer)." }
---
Cancels a timer registered by the same addon object as used for [`:ScheduleTimer`](#scheduletimer). Both one-shot and repeating timers can be canceled.
---
```lua
function MyAddon:OnEnable()
self.timer = self:ScheduleRepeatingTimer("Pulse", 1)
end
function MyAddon:StopPulse()
self:CancelTimer(self.timer)
end
```
````
````apimethod
name: AceTimer:CancelAllTimers
---
Cancels all timers registered to the current addon object (`self`).
````
````apimethod
name: AceTimer:TimeLeft
returns: { type = "number", desc = "The time left on the timer." }
params:
- { name = "id", type = "string", desc = "The id of the timer, as returned by [`:ScheduleTimer`](#scheduletimer) or [`:ScheduleRepeatingTimer`](#schedulerepeatingtimer)." }
---
Returns the time left for a timer with the given id, registered by the current addon object (`self`).
This function will return 0 when the id is invalid.
````
---
# AceDB-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-db
# AceDB-3.0
AceDB-3.0 manages the `SavedVariables` of your addon. It offers profile management, smart defaults and namespaces for
modules.
Creating a new Database using the [`:New`](#new) function will return a new `DBObject`. A database will inherit all
functions of the `DBObjectLib` listed here.
If you create a new namespaced child-database ([`:RegisterNamespace`](#registernamespace)), you'll get a `DBObject` as
well, but note that the child-databases cannot individually change their profile, and are linked to their parents
profile - and because of that, the profile related APIs are not available. Only [`:RegisterDefaults`](#registerdefaults)
and [`:ResetProfile`](#resetprofile) are available on child-databases.
## Tutorial
This walk-through covers the core concepts (profiles, smart defaults and namespaces) with examples. For exact method
signatures and parameters, follow the links into the [API reference](#api-reference) below.
### Getting Started
First, declare the `SavedVariables` table in your addon's `.toc` file:
```toc
## SavedVariables: AceDBExampleDB
```
Then create the database object with [`:New`](#new), passing the name of that table.
::: warning
You must create the database **after** the [`ADDON_LOADED`](https://warcraft.wiki.gg/wiki/ADDON_LOADED) event has fired
for your addon (that is, in [`OnInitialize`](/api/ace-addon#oninitialize)); otherwise the table you read will be
replaced when the real `SavedVariables` loads.
:::
```lua
AceDBExample = LibStub("AceAddon-3.0"):NewAddon("AceDBExample")
function AceDBExample:OnInitialize()
self.db = LibStub("AceDB-3.0"):New("AceDBExampleDB")
end
```
### Accessing & Storing Data
A database object exposes its data through several scopes (see [Scopes](#scopes) below). The most commonly used is
`profile`, which lets each character choose which named profile is active.
Reading and writing is just plain table access; you can store strings, numbers, or whole nested tables:
```lua
function AceDBExample:OnEnable()
if self.db.profile.optionA then
self.db.profile.playerName = UnitName("player")
-- You're not limited to `profile`: read and write any scope the same way, and you can mix them freely on one database
self.db.char.money = GetMoney() -- per-character
self.db.global.installed = true -- account-wide
end
end
```
To organize your settings, nest tables however you like; they behave like any other Lua table.
### Defaults
Defaults are defined as a table laid out exactly like you want your database to look. You pass them to [`:New`](#new) as
the second argument (or set them later with [`:RegisterDefaults`](#registerdefaults)). Because one defaults table covers
every scope at once, the top-level keys are the scope names (`profile`, `char`, `global`, ...).
```lua
local defaults = {
profile = {
optionA = true,
optionB = false,
suboptions = {
subOptionA = false,
subOptionB = true,
},
}
}
function AceDBExample:OnInitialize()
self.db = LibStub("AceDB-3.0"):New("AceDBExampleDB", defaults)
end
```
Defaults are served transparently when a key has not been set, and they are never written to the `SavedVariables` file,
so users only persist values they have actually changed.
#### Smart Defaults
There are two "magic" keys you can use inside a defaults table.
The first is `['*']`, which provides a default for **any key that was not explicitly defined**:
```lua
local defaults = {
profile = {
modules = {
['*'] = {
enabled = true,
visible = true,
},
moduleB = {
enabled = false,
visible = true,
},
}
}
}
```
With these defaults, reading `self.db.profile.modules.moduleA.enabled` returns `true`: `moduleA` was never declared, so
it inherits the `['*']` table. Keys that *are* explicitly defined (like `moduleB`) do **not** inherit anything from
`['*']`.
The second magic key is `['**']`. It works like `['*']`, except it is **also inherited by the sibling keys in the same
table**:
```lua
local defaults = {
profile = {
modules = {
['**'] = {
enabled = true,
visible = true,
},
moduleB = {
enabled = false,
--visible = true,
},
}
}
}
```
Here `visible` is commented out of `moduleB`, yet `self.db.profile.modules.moduleB.visible` still returns `true`,
because the explicitly-defined `moduleB` inherits the missing field from `['**']`.
::: tip
The difference is subtle but important: `['*']` only fills in *undefined* sibling keys, while `['**']` is also merged
into *defined* siblings. Use `['**']` when you want every entry to share a base set of fields.
:::
A `['*']` value can also be a plain value rather than a table; for example `['*'] = false` for a table that tracks which
modules are enabled, with an explicit `true` for the ones that are on.
### Reacting to Profile Changes
When the active profile changes, the values behind `self.db.profile` change too, so anything you derived from those
settings (frame positions, visibility, options panels) needs to be refreshed. AceDB tells you this happened through
callbacks, fired via [CallbackHandler-1.0](/api/callback-handler).
Three callbacks all signal "the active profile changed": the user switched profiles, copied a profile into the active
one, or reset it. Register the same handler for all three:
```lua
function MyAddon:OnInitialize()
self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig")
self.db.RegisterCallback(self, "OnProfileCopied", "RefreshConfig")
self.db.RegisterCallback(self, "OnProfileReset", "RefreshConfig")
end
function MyAddon:RefreshConfig()
-- re-read self.db.profile and reapply your settings here
end
```
::: tip
Every addon that uses profiles should handle these three callbacks for a smooth, consistent transition whenever the
active profile changes.
:::
For the complete list of callbacks and their arguments, see the [Callbacks](#callbacks) section below.
## Scopes
Data can be saved in different scopes, depending on its intended usage. The following scopes are available:
- `char`: Character-specific data. Every character has its own database.
- `realm`: Realm-specific data. All of the players characters on the same realm share this database.
- `class`: Class-specific data. All of the players characters of the same class share this database.
- `race`: Race-specific data. All of the players characters of the same race share this database.
- `faction`: Faction-specific data. All of the players characters of the same faction share this database.
- `factionrealm`: Faction and realm specific data. All of the players characters on the same realm and of the same
faction share this database.
- `locale`: Locale specific data, based on the locale of the players game client.
- `global`: Global Data. All characters on the same account share this database.
- `profile`: Profile-specific data, and the most commonly used scope. All characters using the same profile share this
database; the user can choose the active profile and manage the profiles of all of their characters.
Each of these is a **live view into the saved table for the relevant key**. You read and write them like ordinary Lua
tables and AceDB persists the correct slice automatically.
Profiles work a little differently, because the user can switch which one is active:
- **`db.profile`** is the table of the **currently active profile**: the one whose name
[`:GetCurrentProfile`](#getcurrentprofile) returns. This is what your addon reads and writes for ordinary settings (
`db.profile.fontSize = 12`).
- Which profile is active is tracked **per character**: AceDB keeps a `character → profile name` map in the
SavedVariables, so every character remembers its own choice. A character with no stored choice falls back to the
default profile: the `defaultProfile` you passed to [`:New`](#new) (`"Default"` if you passed `true`), or a
character-specific profile if you passed nothing.
- **`db.profiles`** is the table of **all** profiles, keyed by profile name (every profile that exists in the database,
shared across the account). [`:GetProfiles`](#getprofiles) lists their names; [`:SetProfile`](#setprofile) switches
the active one (creating it if the name is new), which re-points `db.profile` at that profile's table and stores the
choice for the current character. [`:CopyProfile`](#copyprofile), [`:DeleteProfile`](#deleteprofile) and
[`:ResetProfile`](#resetprofile) manage them. Changing the profile fires the [profile callbacks](#callbacks) so your
addon can re-apply settings.
So in a typical addon, `self.db.profile` is "the user's current settings", `self.db.profiles` is "every saved settings
set", and the active selection is remembered separately for each character.
## API Reference
````apimethod
name: AceDB:New
params:
- { name = "tbl", type = "string|table", desc = "The name of the variable, or table to use for the database." }
- { name = "defaults", type = "table", optional = true, desc = "A table of database defaults." }
- { name = "defaultProfile", type = "string|boolean", optional = true, desc = "The name of the default profile. If not set, each character defaults to its own profile named `\"CharacterName - RealmName\"` (for example, `\"Thrall - Silvermoon\"`). Pass `true` to instead default to a single shared profile named `\"Default\"`." }
returns: { type = "table", desc = "The new database object." }
---
Creates a new database object that can be used to handle database settings and profiles.
By default, an empty DB is created, using a character specific profile.
You can override the default profile used by passing any profile name as the third argument, or by passing `true` as the third argument to use a globally shared profile called "Default".
Note that there is no token replacement in the default profile name, passing a defaultProfile as "char" will use a profile named "char", and not a character-specific profile.
---
```lua
-- Create an empty DB using a character-specific default profile.
self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
-- ...or with a defaults table and a shared "Default" profile:
local defaults = { profile = { enabled = true } }
self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
```
````
````apimethod
name: DBObjectLib:CopyProfile
params:
- { name = "name", type = "string", desc = "The name of the profile to be copied into the current profile." }
- { name = "silent", type = "boolean", optional = true, desc = "If `true`, do not raise an error when the profile does not exist." }
---
Copies a named profile into the current profile, overwriting any conflicting settings.
````
````apimethod
name: DBObjectLib:DeleteProfile
params:
- { name = "name", type = "string", desc = "The name of the profile to be deleted." }
- { name = "silent", type = "boolean", optional = true, desc = "If `true`, do not raise an error when the profile does not exist." }
---
Deletes a named profile.
This profile must not be the active profile.
````
````apimethod
name: DBObjectLib:GetCurrentProfile
returns: { type = "string", desc = "The current profile name used by the database." }
---
Returns the current profile name used by the database.
````
````apimethod
name: DBObjectLib:GetNamespace
params:
- { name = "name", type = "string", desc = "The name of the namespace." }
- { name = "silent", type = "boolean", optional = true, desc = "If `true`, the namespace is optional; silently return `nil` if it is not found." }
returns: { type = "table", desc = "The namespace object if found." }
---
Returns an already existing namespace from the database object.
````
````apimethod
name: DBObjectLib:GetProfiles
params:
- { name = "tbl", type = "table", optional = true, desc = "A table to store the profile names in." }
returns:
- { name = "profiles", type = "table", desc = "The table of profile names." }
- { name = "count", type = "number", desc = "The number of profiles in the table." }
---
Returns a table with the names of the existing profiles in the database.
You can optionally supply a table to re-use for this purpose.
---
```lua
local profiles, count = self.db:GetProfiles()
```
````
````apimethod
name: DBObjectLib:RegisterDefaults
params:
- { name = "defaults", type = "table", desc = "A table of defaults for this database." }
---
Sets the defaults table for the given database object by clearing any that are currently set, and then setting the new defaults.
````
````apimethod
name: DBObjectLib:RegisterNamespace
params:
- { name = "name", type = "string", desc = "The name of the new namespace." }
- { name = "defaults", type = "table", optional = true, desc = "A table of values to use as defaults." }
returns: { type = "table", desc = "The new namespace database object." }
---
Creates a new database namespace, directly tied to the database.
This is a full scale database in its own rights other than the fact that it cannot control its profile individually.
---
```lua
local module = self.db:RegisterNamespace("MyModule", { profile = { enabled = true } })
```
````
````apimethod
name: DBObjectLib:ResetDB
params:
- { name = "defaultProfile", type = "string|boolean", optional = true, desc = "The profile name to use as the default. May also be `true` for a shared global profile called \"Default\"." }
returns: { type = "table", desc = "The database object." }
---
Resets the entire database, using the string defaultProfile as the new default profile.
````
````apimethod
name: DBObjectLib:ResetProfile
params:
- { name = "noChildren", type = "boolean", optional = true, desc = "If set to `true`, the reset will not be populated to the child namespaces of this DB object." }
- { name = "noCallbacks", type = "boolean", optional = true, desc = "If set to `true`, won't fire the [`OnProfileReset`](#onprofilereset) callback." }
---
Resets the current profile to the default values (if specified).
````
````apimethod
name: DBObjectLib:SetProfile
params:
- { name = "name", type = "string", desc = "The name of the profile to set as the current profile." }
---
Changes the profile of the database and all of it's namespaces to the supplied named profile.
````
## Callbacks
AceDB fires a set of callbacks through [CallbackHandler-1.0](/api/callback-handler), notifying you of all
important changes to the database. The CallbackHandler API is embedded directly
on the database object, so you register a callback with:
```lua
db.RegisterCallback(target, "EventName", "method")
```
where `target` is the object to call back on (commonly `self`), `"EventName"` is
one of the callbacks below, and `"method"` is the name of the method to invoke on
`target` (it may be omitted to call a method of the same name as the event).
`db.UnregisterCallback(target, "EventName")` and
`db.UnregisterAllCallbacks(target)` are also available.
All callbacks receive the database object as their first argument; most provide
additional information in further arguments.
````apimethod
name: OnNewProfile
kind: callback
params:
- { name = "db", type = "table", desc = "The database object the callback fires on." }
- { name = "profile", type = "string", desc = "The key of the new profile." }
---
Fires when a new profile is created. Commonly used to apply custom defaults that
cannot be handled through AceDB's defaults table.
````
````apimethod
name: OnProfileChanged
kind: callback
params:
- { name = "db", type = "table", desc = "The database object the callback fires on." }
- { name = "newProfile", type = "string", desc = "The key of the now-active profile." }
---
Fires after the active profile has been changed (including as part of a database
reset).
````
````apimethod
name: OnProfileDeleted
kind: callback
params:
- { name = "db", type = "table", desc = "The database object the callback fires on." }
- { name = "profile", type = "string", desc = "The key of the deleted profile." }
---
Fires after a profile has been deleted.
````
````apimethod
name: OnProfileCopied
kind: callback
params:
- { name = "db", type = "table", desc = "The database object the callback fires on." }
- { name = "sourceProfile", type = "string", desc = "The key of the profile that was copied from." }
---
Fires after a profile has been copied into the current active profile.
````
````apimethod
name: OnProfileReset
kind: callback
params:
- { name = "db", type = "table", desc = "The database object the callback fires on." }
---
Fires after the current profile has been reset to its default values.
````
````apimethod
name: OnDatabaseReset
kind: callback
params:
- { name = "db", type = "table", desc = "The database object the callback fires on." }
---
Fires after the whole database has been reset. Note that [`OnProfileChanged`](#onprofilechanged) is
fired immediately afterwards as well.
````
````apimethod
name: OnProfileShutdown
kind: callback
params:
- { name = "db", type = "table", desc = "The database object the callback fires on." }
---
Fires before the active profile is changed, allowing you to save any pending
state to the outgoing profile.
````
````apimethod
name: OnDatabaseShutdown
kind: callback
params:
- { name = "db", type = "table", desc = "The database object the callback fires on." }
---
Fires on logout ([`PLAYER_LOGOUT`](https://warcraft.wiki.gg/wiki/PLAYER_LOGOUT)), just before the database is cleaned of all
AceDB metadata and defaults are stripped from the `SavedVariables`.
````
---
# AceDBOptions-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-db-options
# AceDBOptions-3.0
AceDBOptions-3.0 provides a universal AceConfig options screen for managing [AceDB-3.0](/api/ace-db) profiles.
## Usage
[`:GetOptionsTable`](#getoptionstable) returns a ready-made profile-management group in the
standard [AceConfig-3.0 options table](/api/ace-config-options) format. You slot it into your own options table as one
subgroup, then register the whole table with [AceConfig-3.0](/api/ace-config) as usual:
```lua
local options = {
type = "group",
name = "My Addon",
args = {
-- your own options go here...
-- profile management, handled for you:
profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db),
},
}
LibStub("AceConfig-3.0"):RegisterOptionsTable("MyAddon", options)
```
`self.db` is your AceDB object, so call this once the database exists (e.g. in `OnInitialize`); the only requirement is
that the group is in your options table before you register it. The profile list it shows is queried live each time the
panel opens, so it always reflects the current profiles. The returned group handles switching, copying, resetting and
deleting profiles, so you don't write any of that UI yourself.
::: warning
The generated options table is shared between all addons that use it; do not modify it.
:::
## API Reference
````apimethod
name: AceDBOptions:GetOptionsTable
params:
- { name = "db", type = "table", desc = "The database object to create the options table for." }
- { name = "noDefaultProfiles", type = "boolean", optional = true, desc = "If `true`, the commonly used default profile suggestions (\"char - realm\", \"realm\", \"class\", \"Default\") are not offered in the profile list." }
returns: { type = "table", desc = "The options table to be used in AceConfig-3.0." }
---
Get/Create a option table that you can use in your addon to control the profiles of [AceDB-3.0](/api/ace-db).
---
```lua
-- Assuming `options` is your top-level options table and `self.db` is your database:
options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
```
````
---
# AceConfig-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-config
# AceConfig-3.0
Provides an API to register an options table with the config registry, optionally associating it with a slash command.
## Usage
Describe your options as a declarative table (see the [options table reference](/api/ace-config-options) for the full
format), then register and display them in `OnInitialize`. `get`/`set` can be plain functions or method names resolved
on the `handler` object:
```lua
local myMessageVar = ""
local options = {
name = "MyAddon",
handler = MyAddon, -- "GetMyMessage"/"SetMyMessage" resolve to methods on this object
type = "group",
args = {
msg = {
type = "input",
name = "My Message",
desc = "The message for my addon",
get = "GetMyMessage",
set = "SetMyMessage",
},
},
}
function MyAddon:GetMyMessage(info)
return myMessageVar
end
function MyAddon:SetMyMessage(info, input)
myMessageVar = input
end
function MyAddon:OnInitialize()
-- Pass slash commands as the third arg; omit for GUI-only config.
LibStub("AceConfig-3.0"):RegisterOptionsTable("MyAddon", options, "myaddon")
LibStub("AceConfigDialog-3.0"):AddToBlizOptions("MyAddon", "My Addon")
end
function MyAddon:OpenOptions()
-- Example function; bound to an "Open Options" button.
LibStub("AceConfigDialog-3.0"):Open("MyAddon")
end
```
## API Reference
````apimethod
name: AceConfig:RegisterOptionsTable
params:
- { name = "appName", type = "string", desc = "The application name for the config table." }
- { name = "options", type = "table|function", desc = "The option table (or a function to generate one on demand). See [Options Tables](/api/ace-config-options) for the format." }
- { name = "slashcmd", type = "string|table", optional = true, desc = "A slash command (without leading `/` — AceConsole prepends it) to register for the option table, or a table of slash commands." }
---
Register an option table with the AceConfig registry.
---
```lua
local AceConfig = LibStub("AceConfig-3.0")
AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"myaddon", "ma"})
```
````
---
# AceConfigCmd-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-config-cmd
# AceConfigCmd-3.0
AceConfigCmd-3.0 handles access to an options table through the "command line" interface via the ChatFrames.
## API Reference
````apimethod
name: AceConfigCmd:CreateChatCommand
params:
- { name = "slashcmd", type = "string", desc = "The slash command WITHOUT leading slash (only used for error output)." }
- { name = "appName", type = "string", desc = "The application name as given to `:RegisterOptionsTable()`." }
---
Utility function to create a slash command handler.
Also registers tab completion with AceTab.
````
````apimethod
name: AceConfigCmd:GetChatCommandOptions
params:
- { name = "slashcmd", type = "string", desc = "The slash command WITHOUT leading slash (only used for error output)." }
returns:
- { type = "table", desc = "The options table associated with the slash command (or `nil` if the slash command was not registered)." }
---
Utility function that returns the options table that belongs to a slashcommand.
Designed to be used for the AceTab interface.
````
````apimethod
name: AceConfigCmd:HandleCommand
params:
- { name = "slashcmd", type = "string", desc = "The slash command WITHOUT leading slash (only used for error output)." }
- { name = "appName", type = "string", desc = "The application name as given to `:RegisterOptionsTable()`." }
- { name = "input", type = "string", desc = "The commandline input (as given by the [WoW handler](https://warcraft.wiki.gg/wiki/World_of_Warcraft_API), i.e. without the command itself)." }
---
Handle the chat command.
This is usually called from a chat command handler to parse the `input` as operations on an aceoptions table. AceConfigCmd uses this function internally when a slash command is registered with [`:CreateChatCommand`](#createchatcommand).
---
```lua
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0")
-- Use AceConsole-3.0 to register a Chat Command
MyAddon:RegisterChatCommand("mychat", "ChatCommand")
-- Show the GUI if no input is supplied, otherwise handle the chat input.
function MyAddon:ChatCommand(input)
-- Assuming "MyOptions" is the appName of a valid options table
if not input or input:trim() == "" then
LibStub("AceConfigDialog-3.0"):Open("MyOptions")
else
LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input)
end
end
```
::: tip Dot Call vs. Colon Call
`HandleCommand`'s first parameter is the `self` the command runs against. The dot call passes `MyAddon` explicitly as that `self`, so the options table's `get`/`set`/`handler` resolve in your addon's context. Calling `:HandleCommand(...)` would bind `self` to the AceConfigCmd library instead.
:::
````
---
# AceConfigDialog-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-config-dialog
# AceConfigDialog-3.0
AceConfigDialog-3.0 generates [AceGUI-3.0](/acegui/) based windows based on option tables.
## API Reference
````apimethod
name: AceConfigDialog:AddToBlizOptions
params:
- { name = "appName", type = "string", desc = "The application name as given to [`:RegisterOptionsTable`](/api/ace-config#registeroptionstable)." }
- { name = "name", type = "string", optional = true, desc = "A descriptive name to display in the options tree (defaults to appName)." }
- { name = "parent", type = "string", optional = true, desc = "The parent to use in the interface options tree." }
- { name = "...", type = "any", desc = "The path in the options table to feed into the interface options panel." }
returns:
- { type = "frame", desc = "The reference to the frame registered into the Interface Options." }
- { type = "any", desc = "The category ID to pass to `Settings.OpenToCategory`." }
---
Add an option table into the [Blizzard Interface Options panel](https://warcraft.wiki.gg/wiki/FrameXML_functions).
You can optionally supply a descriptive `name` to use and a `parent` frame to use, as well as a path in the options table. If no `name` is specified, the `appName` will be used instead.
If you specify a proper `parent` (by name), the interface options will generate a tree layout. Note that only one level of children is supported, so the `parent` always has to be a head-level node.
This function returns a reference to the container frame registered with the Interface Options, as well as the registered ID. You can use the ID to open the options with the API function [`Settings.OpenToCategory`](https://warcraft.wiki.gg/wiki/API_Settings.OpenToCategory).
---
```lua
local frame, categoryID = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("MyAddon")
```
````
````apimethod
name: AceConfigDialog:Close
params:
- { name = "appName", type = "string", desc = "The application name as given to [`:RegisterOptionsTable`](/api/ace-config#registeroptionstable)." }
---
Close a specific options window.
````
````apimethod
name: AceConfigDialog:CloseAll
---
Close all open options windows.
````
````apimethod
name: AceConfigDialog:Open
params:
- { name = "appName", type = "string", desc = "The application name as given to [`:RegisterOptionsTable`](/api/ace-config#registeroptionstable)." }
- { name = "container", type = "table", optional = true, desc = "An optional container frame to feed the options into." }
- { name = "...", type = "any", desc = "The path to open after creating the options window (see [`:SelectGroup`](#selectgroup) for details)." }
---
Open an option window at the specified path (if any).
This function can optionally feed the group into a pre-created `container` instead of creating a new container frame.
````
````apimethod
name: AceConfigDialog:SelectGroup
params:
- { name = "appName", type = "string", desc = "The application name as given to [`:RegisterOptionsTable`](/api/ace-config#registeroptionstable)." }
- { name = "...", type = "any", desc = "The path to the key that should be selected." }
---
Selects the specified path in the options window.
The path specified has to match the keys of the groups in the table.
---
```lua
LibStub("AceConfigDialog-3.0"):SelectGroup("MyAddon", "display", "colors")
```
````
````apimethod
name: AceConfigDialog:SetDefaultSize
params:
- { name = "appName", type = "string", desc = "The application name as given to [`:RegisterOptionsTable`](/api/ace-config#registeroptionstable)." }
- { name = "width", type = "number", desc = "The default width." }
- { name = "height", type = "number", desc = "The default height." }
---
Sets the default size of the options window for a specific application.
````
````apimethod
name: AceConfigDialog:GetStatusTable
params:
- { name = "appName", type = "string", desc = "The application name as given to [`:RegisterOptionsTable`](/api/ace-config#registeroptionstable)." }
- { name = "path", type = "table", optional = true, desc = "The path of group keys identifying a node in the options tree; omit for the root." }
returns: { type = "table", desc = "The status table for that node, created on first access." }
---
Get the table AceConfigDialog uses to persist the open window's UI state (such as the selected group or tab) for `appName` at the given `path`. Read it to inspect the dialog, or seed it to control the initial state.
````
---
# AceConfigRegistry-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-config-registry
# AceConfigRegistry-3.0
AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules. Options tables can be
registered as raw tables, OR as function refs that return a table. Such functions receive three arguments: `uiType`,
`uiName`, `appName`.
Valid `uiType` values: `"cmd"`, `"dropdown"`, `"dialog"`. This is verified by the library at call time. The `uiName`
field is expected to contain the full name of the calling addon, including version, e.g. `"FooBar-1.0"`. This is
verified by the library at call time. The `appName` field is the options table name as given at registration time.
[`:IterateOptionsTables()`](#iterateoptionstables) (and [`:GetOptionsTable()`](#getoptionstable) if only given one
argument) return a function reference that the requesting config handling addon must call with valid `uiType`, `uiName`.
## API Reference
````apimethod
name: AceConfigRegistry:GetOptionsTable
params:
- { name = "appName", type = "string", desc = "The application name as given to [`:RegisterOptionsTable()`](#registeroptionstable)." }
- { name = "uiType", type = "string", optional = true, desc = "The type of UI to get the table for, one of `\"cmd\"`, `\"dropdown\"`, `\"dialog\"`." }
- { name = "uiName", type = "string", optional = true, desc = "The name of the library/addon querying for the table, e.g. `\"MyLib-1.0\"`." }
returns:
- { type = "table|function", desc = "If only `appName` is given, a function is returned which you can call with (`uiType`, `uiName`) to get the table. If `uiType` & `uiName` are given, the table is returned. `nil` if no options table has been registered under `appName`." }
---
Query the registry for a specific options table.
If only `appName` is given, a function is returned which you can call with (`uiType`, `uiName`) to get the table. If `uiType` & `uiName` are given, the table is returned.
Returns `nil` if no options table has been registered under `appName`.
````
````apimethod
name: AceConfigRegistry:IterateOptionsTables
returns:
- { type = "function", desc = "An iterator (`pairs`) over `[\"appName\"] = funcref` pairs." }
---
Returns an iterator of `["appName"] = funcref` pairs.
---
```lua
for appName, getTable in LibStub("AceConfigRegistry-3.0"):IterateOptionsTables() do
-- getTable("dialog", "MyAddon-1.0") returns the options table
end
```
````
````apimethod
name: AceConfigRegistry:NotifyChange
params:
- { name = "appName", type = "string", desc = "The application name as given to [`:RegisterOptionsTable()`](#registeroptionstable)." }
---
Fires a `"ConfigTableChange"` callback for those listening in on it, allowing config GUIs to refresh.
You should call this function if your options table changed from any outside event, like a game event or a timer.
````
````apimethod
name: AceConfigRegistry:RegisterOptionsTable
params:
- { name = "appName", type = "string", desc = "The application name as given to `:RegisterOptionsTable()`." }
- { name = "options", type = "table|function", desc = "The options table, OR a function reference that generates it on demand. See the top of the page for info on arguments passed to such functions." }
- { name = "skipValidation", type = "boolean", optional = true, desc = "Skip options table validation (primarily useful for extremely huge options, with a noticeable slowdown)." }
---
Register an options table with the config registry.
````
````apimethod
name: AceConfigRegistry:ValidateOptionsTable
params:
- { name = "options", type = "table", desc = "The table to be validated." }
- { name = "name", type = "string", desc = "The name of the table to be validated (shown in any error message)." }
- { name = "errlvl", type = "number", optional = true, default = "0", desc = "A non-negative integer added to the Lua `error()` level used to report validation failures; it controls which stack frame the error is blamed on. `0` (the default) points the error at the function that called `:ValidateOptionsTable`; raise it by `1` for each additional wrapper frame you want the error to skip past so it blames your caller instead." }
---
Validates basic structure and integrity of an options table.
Does NOT verify that `get`/`set` etc actually exist, since they can be defined at any depth.
````
---
# Options Tables
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-config-options
# AceConfig-3.0 Options Tables
An options table is a standardized, declarative description of an addon's options and commands. Instead of building UI
widgets or parsing slash commands yourself, you describe *what* options exist as a plain Lua table, and AceConfig turns
that description into a dialog window, a dropdown menu, and a [command-line interface](/api/ace-config-cmd) (slash
commands).
This page documents the table format. To register an options table and display it as a GUI or slash command,
see [AceConfig-3.0](/api/ace-config).
A minimal example:
```lua
myOptionsTable = {
type = "group",
args = {
enable = {
name = "Enable",
desc = "Enables / disables the addon",
type = "toggle",
set = function(info, val) MyAddon.enabled = val end,
get = function(info) return MyAddon.enabled end,
},
moreoptions = {
name = "More Options",
type = "group",
args = {
-- more options go here
},
},
},
}
```
## The Basics
Every option table has to start with a head **group** node. It can have a `name` and an `icon`, but only the
`type = "group"` and the `args` table are required.
You can nest groups as deep as you need them to be, and include options on any level. Of course, not everything makes
sense from a UI design perspective.
Nearly all parameters can be **inherited** through the table tree. For example, you can define one `get` handler on a
group, and all member nodes (and member nodes of sub-groups) will use it unless overridden.
Currently inherited are: `set`, `get`, `func`, `confirm`, `validate`, `disabled` and `hidden`.
To declare that an inherited value is NOT to be used even though a parent has it, set it to `false`.
The keys used in the option tables can contain all printable characters. If you use spaces in the keys and intend to use
your option table with a command-line interface like [AceConfigCmd-3.0](/api/ace-config-cmd), make sure your keys do not
collide: [AceConfigCmd-3.0](/api/ace-config-cmd) maps spaces to underscores, so `"foo bar"` and `"foo_bar"` would
collide.
Most parameters can also be a function reference, which is called when the value is requested. Every function called by
AceConfig receives an `info` table as its first parameter, describing the current position in the tree, the type of UI
displaying the options, and the options table itself. See [Callback Arguments](#callback-arguments).
## Common Parameters
The following parameters apply to all types of nodes and groups, and control the general layout of the options.
| Parameter | Type | Description |
|--------------------|-----------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | `string` `function` | Display name for the option. |
| `desc` | `string` `function` | Description for the option (or `nil` for a self-describing name). |
| `descStyle` | `string` | `"inline"` to show the description below the option in a GUI rather than as a tooltip. Currently only supported by AceGUI "Toggle". |
| `tooltipHyperlink` | `string` `function` | A hyperlink embedded in the option's tooltip. |
| `validate` | `methodname` `function` `false` | Validate the input/value before setting it. Return a string (error message) to indicate an error. |
| `confirm` | `methodname` `function` `boolean` | Prompt for confirmation before changing a value. `true` displays "name - desc" (or `confirmText`); a function may return a prompt string, `true`, or `false` to skip confirmation. |
| `confirmText` | `string` | Prompt text shown when `confirm` is `true`, overriding the default "name - desc". |
| `order` | `number` `methodname` `function` | Relative position of item (default = 100, `0` = first, `-1` = last). |
| `disabled` | `methodname` `function` `boolean` | Disabled but visible. |
| `hidden` | `methodname` `function` `boolean` | Hidden (but still usable if you can reach it, e.g. via commandline). |
| `guiHidden` | `boolean` | Hide this from graphical UIs (dialog, dropdown). |
| `dialogHidden` | `boolean` | Hide this from dialog UIs. |
| `dropdownHidden` | `boolean` | Hide this from dropdown UIs. |
| `cmdHidden` | `boolean` | Hide this from the [command line](/api/ace-config-cmd) (the slash-command interface). |
| `icon` | `string` `number` `function` | Icon texture for the option: a file path (string) or a fileDataID (number). Pass a function to compute it dynamically. |
| `iconCoords` | `table` `methodname` `function` | Arguments to pass to [`SetTexCoord`](https://warcraft.wiki.gg/wiki/API_Texture_SetTexCoord), e.g. `{0.1, 0.9, 0.1, 0.9}`. |
| `handler` | `table` | Object on which getter/setter functions are called if they are declared as strings (methodnames) rather than function references. |
| `type` | `string` | The option type: `"execute"`, `"input"`, `"group"`, etc. See [Item Types](#item-types). |
| `width` | `string` `number` | GUI hint for how wide the option should be (optional support). Default is `nil` (not set). Values: `"double"`/`"half"` to enlarge/shrink; `"full"` for the full window width; `"normal"` for the implementation's default width (useful to override widgets that default to `"full"`); or a number as a multiplier of the default width (e.g. `0.5` = `"half"`, `2.0` = `"double"`). |
| `relWidth` | `number` | Relative width, as a fraction of the available space. |
::: tip Note
For conditional show/hide or enable/disable, use `hidden` and `disabled`: set either to a function (or methodname) and
it is called each time the option's state is checked. The UI-specific variants (`guiHidden`, `dialogHidden`,
`dropdownHidden`, `cmdHidden`) are booleans only, so put any dynamic logic in `hidden`/`disabled`.
:::
## Item Types
### execute
Runs `func`. In a GUI this is a button; if `image` is set, it displays a clickable image instead of a default button.
| Field | Type | Description |
|---------------|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `func` | `function` `methodname` | Called as `func(info)` when executed. |
| `image` | `string` `number` `function` | Path to image texture; if a function, it may optionally return the image width and height as the 2nd and 3rd values, used instead of `imageWidth`/`imageHeight`. |
| `imageCoords` | `table` `methodname` `function` | Arguments to pass to [`SetTexCoord`](https://warcraft.wiki.gg/wiki/API_Texture_SetTexCoord), e.g. `{0.1, 0.9, 0.1, 0.9}`. |
| `imageWidth` | `number` | Width of the displayed image. |
| `imageHeight` | `number` | Height of the displayed image. |
### input
A simple text input, with an optional validation pattern or function.
| Field | Type | Description |
|-------------|-------------------------|------------------------------------------------------------------------------------------------|
| `get` | `function` `methodname` | Called as `get(info)` → current string value. |
| `set` | `function` `methodname` | Called as `set(info, value)` — `value` is the new string. |
| `multiline` | `boolean` `integer` | If `true`, shown as a multiline editbox in dialog implementations (integer = number of lines). |
| `pattern` | `string` | Optional validation pattern. (Use `validate` for more advanced checks.) |
| `usage` | `string` | Usage string, displayed if the pattern mismatches and in console help messages. |
For checks a `pattern` can't express, use a `validate` function (a [common parameter](#common-parameters)). Return an
error string to reject the value, or `true` to accept it:
```lua
maxTargets = {
type = "input",
name = "Max targets",
usage = "a number between 1 and 40",
get = function(info) return tostring(MyAddon.db.profile.maxTargets) end,
set = function(info, value) MyAddon.db.profile.maxTargets = tonumber(value) end,
validate = function(info, value)
local n = tonumber(value)
if not n or n < 1 or n > 40 then
return "Max targets must be a number between 1 and 40."
end
return true
end,
}
```
### toggle
A simple checkbox.
| Field | Type | Description |
|---------------|---------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `get` | `function` `methodname` | Called as `get(info)` → `true`, `false`, or `nil`. |
| `set` | `function` `methodname` | Called as `set(info, value)` — `value` is `true`, `false`, or `nil`. |
| `tristate` | `boolean` | Make it a tri-state checkbox. Values cycle through unchecked (`false`), checked (`true`), greyed (`nil`), in that order. |
| `image` | `string` `number` `function` | Optional image texture displayed next to the checkbox in a dialog UI. |
| `imageCoords` | `table` `methodname` `function` | Arguments to pass to [`SetTexCoord`](https://warcraft.wiki.gg/wiki/API_Texture_SetTexCoord) for `image`, e.g. `{0.1, 0.9, 0.1, 0.9}`. |
### range
Configures a numeric value in a specific range. In a GUI, a slider.
| Field | Type | Description |
|-------------|-------------------------|-----------------------------------------------------------------------------------------------------------|
| `min` | `number` | Minimum value. |
| `max` | `number` | Maximum value. |
| `softMin` | `number` | "Soft" minimum, used by the UI as a convenient limit while still allowing manual input up to `min`/`max`. |
| `softMax` | `number` | "Soft" maximum, used by the UI as a convenient limit while still allowing manual input up to `min`/`max`. |
| `step` | `number` | Step value used to validate numeric input (default = no stepping limit). |
| `bigStep` | `number` | A more generally-useful step size. Support in UIs is optional. |
| `get` | `function` `methodname` | Called as `get(info)` → current number. |
| `set` | `function` `methodname` | Called as `set(info, value)` — `value` is the new number. |
| `isPercent` | `boolean` | Represent e.g. `1.0` as `100%` (default `false`). |
::: warning Note
The `step` checking only works if you specify valid `min` and `max` values. Even when using `softMin`/`softMax` `min`
and `max` are still required for `step` to function. If no `min` or `max` are specified, the manual input of the range
control will accept any and all values.
:::
### select
Only one value can be selected. In a dropdown UI this is likely a radio group; in a dialog, likely a combobox.
| Field | Type | Description |
|---------------|-------------------------|------------------------------------------------------------------------------------------|
| `values` | `table` `function` | `[key]=value` pair table; the key is passed to `set`, the value is the string displayed. |
| `sorting` | `table` `function` | Optional array-style table of the keys of `values`, defining their display order. |
| `get` | `function` `methodname` | Called as `get(info)` → the active key from `values`. |
| `set` | `function` `methodname` | Called as `set(info, key)` — `key` is the selected entry from `values`. |
| `style` | `string` | `"dropdown"` or `"radio"` (optional support in implementations). |
| `itemControl` | `string` | Name of a custom AceGUI item widget to use for the dropdown entries (dialog UI only). |
### multiselect
Multiple `toggle` elements condensed into a group of checkboxes (or something else that makes sense in the interface).
| Field | Type | Description |
|------------|-------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `values` | `table` `function` | `[key]=value` pair table; the key is passed to `set`, the value is the string displayed. |
| `get` | `function` `methodname` | Called as `get(info, key)` once per key in `values` → `true` or `false`. |
| `set` | `function` `methodname` | Called as `set(info, key, value)` — `key` is the entry toggled, `value` is the new state. |
| `style` | `string` | Optional UI style hint. |
| `tristate` | `boolean` | Make the checkmarks tri-state. Values cycle through unchecked (`false`), checked (`true`), greyed (`nil`), in that order. |
Unlike most types, `get` and `set` operate **per key**: AceConfig calls `get` once for every key in `values` (passing
that key), and calls `set` with the key and its new state.
```lua
track = {
type = "multiselect",
name = "Track mob types",
values = {
elite = "Elite mobs",
rare = "Rare mobs",
boss = "Bosses",
},
-- called once per key; return whether that key is enabled
get = function(info, key) return MyAddon.db.profile.track[key] end,
-- called with the toggled key and its new on/off state
set = function(info, key, state) MyAddon.db.profile.track[key] = state end,
}
```
### color
Opens a color picker (in a GUI, possibly via a button).
| Field | Type | Description |
|------------|-----------------------------------|----------------------------------------------------|
| `get` | `function` `methodname` | Called as `get(info)` → `r, g, b[, a]` (each 0–1). |
| `set` | `function` `methodname` | Called as `set(info, r, g, b[, a])` — each 0–1. |
| `hasAlpha` | `boolean` `methodname` `function` | Indicate if alpha is adjustable (default `false`). |
Getter/setter functions use 4 arguments/returns: `r, g, b, a`. If `hasAlpha` is `false`/`nil`, alpha is always set as
`1.0`.
```lua
barColor = {
type = "color",
name = "Bar color",
hasAlpha = true,
-- return four numbers: red, green, blue, alpha (each 0-1)
get = function(info)
local c = MyAddon.db.profile.barColor
return c.r, c.g, c.b, c.a
end,
-- receives the same four values back
set = function(info, r, g, b, a)
local c = MyAddon.db.profile.barColor
c.r, c.g, c.b, c.a = r, g, b, a
end,
}
```
### keybinding
| Field | Type | Description |
|-------|-------------------------|---------------------------------------------------------------|
| `get` | `function` `methodname` | Called as `get(info)` → current keybind string. |
| `set` | `function` `methodname` | Called as `set(info, key)` — `key` is the new binding string. |
### header
A heading. In commandline and dropdown UIs it shows as a heading; in a dialog UI it additionally provides a break in the
layout.
| Field | Type | Description |
|--------|----------|-------------------------------------|
| `name` | `string` | The text to display in the heading. |
### description
A paragraph of text appearing alongside other options, optionally with an image in front of it.
| Field | Type | Description |
|---------------|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | `string` | The text to display. |
| `fontSize` | `string` `function` | Size of the text: `"large"`, `"medium"` or `"small"` (default `"small"`). |
| `image` | `string` `number` `function` | Path to image texture; if a function, it may optionally return width and height as the 2nd and 3rd values, used instead of `imageWidth`/`imageHeight`. |
| `imageCoords` | `table` `methodname` `function` | Arguments to pass to [`SetTexCoord`](https://warcraft.wiki.gg/wiki/API_Texture_SetTexCoord), e.g. `{0.1, 0.9, 0.1, 0.9}`. |
| `imageWidth` | `number` | Width of the displayed image. |
| `imageHeight` | `number` | Height of the displayed image. |
### group
The first table in an AceOptions table is implicitly a group. Add more levels by nesting tables with `type = "group"`
under an `args` table.
| Field | Type | Description |
|------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `args` | `table` | Subtable with more items/groups in it. |
| `plugins` | `table` | Named subtables, each containing more args. This lets modules and libraries add content to an addon's options table (see example below). |
| `childGroups` | `string` | How child groups are displayed: `"tree"` (the default) as child nodes in a tree control, `"tab"` as tabs, or `"select"` as a dropdown list. Only dialog-driven UIs are assumed to behave differently for all types. |
| `inline` | `boolean` | Show as a bordered box in a dialog UI, or at the parent's level with a separate heading in commandline and dropdown UIs. |
| `cmdInline` | `boolean` | As `inline`, only obeyed by commandline. |
| `guiInline` | `boolean` | As `inline`, only obeyed by graphical UIs. |
| `dropdownInline` | `boolean` | As `inline`, only obeyed by dropdown UIs. |
| `dialogInline` | `boolean` | As `inline`, only obeyed by dialog UIs. |
The `plugins` field lets modules and libraries inject their own args into an addon's options table:
```lua
plugins["myPlugin"] = {
option1 = {...}, option2 = {...}, group1 = {...},
}
plugins["otherPlugin"] = {...}
```
## Callback Handling
For each `set`/`get`/`func`/`validate`/`confirm` callback attempted, the tree is ALWAYS traversed toward the root until
such a directive is found. Similarly, if callbacks are given as strings (methodnames), the tree is traversed to find a
`handler` argument.
To declare that an inherited value is NOT to be used even though a parent has it, set it to `false`. This is primarily
useful for `validate` and `confirm`, but is allowed for all inherited values including `handler`.
This inheritance lets you define `handler`, `get` and `set` **once** on the root group and have every option use them.
When the callbacks are strings, they are looked up as methods on the `handler` object (called as
`handler:Method(info, ...)`). Because `info[#info]` is the leaf option's key, a single getter/setter pair can serve the
whole table:
```lua
local options = {
type = "group",
handler = MyAddon, -- string callbacks resolve to methods on this object
get = "GetValue", -- inherited by every child unless overridden
set = "SetValue",
args = {
enabled = { type = "toggle", name = "Enabled", order = 1 },
scale = { type = "range", name = "Scale", min = 0.5, max = 2, step = 0.1, order = 2 },
sound = {
type = "toggle", name = "Play sound", order = 3,
set = "SetSound", -- override the inherited setter for this one option
},
},
}
-- One pair of methods services every option, keyed by info[#info]:
function MyAddon:GetValue(info)
return self.db.profile[info[#info]]
end
function MyAddon:SetValue(info, value)
self.db.profile[info[#info]] = value
end
function MyAddon:SetSound(info, value)
self.db.profile.sound = value
self:UpdateSoundState() -- extra work only this option needs
end
```
## Callback Arguments
All callbacks receive a standardized set of arguments:
```lua
(info, value[, value2, ...])
```
In detail, the `info` table contains:
- An `options` member pointing at the root of the options table.
- An `appName` member: the application name the options table was registered under. The same value is also stored at
position `0`. (When invoked from a slash command, `info[0]` is the slash command instead, without the leading slash.)
- The name of the first group traversed into at position `1`.
- The node name at position `n` (may be `1` if at the root level).
- Hint: use `info[#info]` to get the leaf node name, `info[#info-1]` for the parent, and so on.
- An `arg` member, if set in the node.
- A `handler` member: the handler object for the current option.
- A `type` member: the type of the current option.
- An `option` member pointing at the current option.
- `uiType` and `uiName` members: the same values passed when retrieving the options table
from [AceConfigRegistry-3.0](/api/ace-config-registry).
The callback may not assume ownership of the `info` table; the config parser is assumed to reuse it. It may also contain
more members, but these are outside the spec and may change at any time; do not rely on undocumented `info` members.
Callbacks of the form `handler:"methodname"` are of course passed the handler object as the first (`self`) argument.
Example:
```lua
local function mySetterFunc(info, value)
db[info[#info]] = value -- we use the db names in our settings
print("The " .. info[#info] .. " was set to: " .. tostring(value))
end
```
## Custom Controls
You can register your own AceGUI-3.0 widget and tell [AceConfigDialog-3.0](/api/ace-config-dialog) to use it for an
option, via the `dialogControl` attribute (the `control` attribute works too). It is supported for the simple control
types, but not for groups. For `select`, a custom control only applies to the default dropdown style; `style = "radio"`
builds its own checkbox group and ignores `dialogControl`.
```lua
-- LibSharedMedia-3.0 and AceGUI-3.0-SharedMediaWidgets are third-party
-- libraries, not part of Ace3. They are shown here only to illustrate a
-- real custom control.
local media = LibStub("LibSharedMedia-3.0")
self.options = {
type = "group",
args = {
texture = {
type = "select",
name = "Texture",
desc = "Set the statusbar texture.",
values = media:HashTable("statusbar"),
dialogControl = "LSM30_Statusbar", -- a custom AceGUI widget from SharedMediaWidgets
},
},
}
```
### What AceConfigDialog expects of a custom widget
AceConfigDialog creates the widget with `AceGUI:Create(dialogControl)`. If that fails (the type isn't registered) it
logs an error and falls back to the built-in widget for the option type, so your control must be a properly registered
AceGUI-3.0 widget.
On **every** control, AceConfigDialog:
- calls `:SetDisabled(disabled)` if that method exists;
- sets its width with `:SetWidth(pixels)` or `:SetRelativeWidth(fraction)`, or honours `widget.width = "fill"`;
- calls `:SetCustomData(arg)` if the method exists and the option has an `arg`;
- registers `OnEnter` / `OnLeave` callbacks (for the option tooltip) and `OnRelease` (for cleanup), so your widget must
fire `OnEnter` / `OnLeave`.
Beyond that, the methods called and the callback AceConfigDialog listens for depend on the option type. Your widget
needs to implement the ones for the type(s) it replaces, and fire the listed callback with the new value(s) as
arguments (that callback argument is exactly what gets passed to the option's `set`).
| Option type | Built-in fallback | Methods AceConfigDialog calls | Callback it listens for |
|---------------|--------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|
| `execute` | [Button](/acegui/widgets/button), or [Icon](/acegui/widgets/icon) when `image` is set | [`SetText`](/acegui/widgets/button#settext) (Button) or [`SetLabel`](/acegui/widgets/icon#setlabel) (Icon); [`SetImage`](/acegui/widgets/icon#setimage), [`SetImageSize`](/acegui/widgets/icon#setimagesize) | [`OnClick`](/acegui/widgets/button#onclick) |
| `input` | [EditBox](/acegui/widgets/editbox), or [MultiLineEditBox](/acegui/widgets/multilineeditbox) when `multiline` | [`SetLabel`](/acegui/widgets/editbox#setlabel), [`SetText`](/acegui/widgets/editbox#settext), [`SetNumLines`](/acegui/widgets/multilineeditbox#setnumlines) (multiline) | [`OnEnterPressed`](/acegui/widgets/editbox#onenterpressed) |
| `toggle` | [CheckBox](/acegui/widgets/checkbox) | [`SetLabel`](/acegui/widgets/checkbox#setlabel), [`SetValue`](/acegui/widgets/checkbox#setvalue), [`SetTriState`](/acegui/widgets/checkbox#settristate), [`SetDescription`](/acegui/widgets/checkbox#setdescription), [`SetImage`](/acegui/widgets/checkbox#setimage) | [`OnValueChanged`](/acegui/widgets/checkbox#onvaluechanged) |
| `range` | [Slider](/acegui/widgets/slider) | [`SetLabel`](/acegui/widgets/slider#setlabel), [`SetSliderValues`](/acegui/widgets/slider#setslidervalues), [`SetIsPercent`](/acegui/widgets/slider#setispercent), [`SetValue`](/acegui/widgets/slider#setvalue) | [`OnValueChanged`](/acegui/widgets/slider#onvaluechanged), [`OnMouseUp`](/acegui/widgets/slider#onmouseup) |
| `select` | [Dropdown](/acegui/widgets/dropdown) | [`SetLabel`](/acegui/widgets/dropdown#setlabel), [`SetList`](/acegui/widgets/dropdown#setlist), [`SetValue`](/acegui/widgets/dropdown#setvalue) | [`OnValueChanged`](/acegui/widgets/dropdown#onvaluechanged) |
| `multiselect` | a [CheckBox](/acegui/widgets/checkbox) group (see below) | [`SetMultiselect`](/acegui/widgets/dropdown#setmultiselect), [`SetLabel`](/acegui/widgets/dropdown#setlabel), [`SetList`](/acegui/widgets/dropdown#setlist), `SetDisabled`, [`SetItemValue`](/acegui/widgets/dropdown#setitemvalue) | [`OnValueChanged`](/acegui/widgets/dropdown#onvaluechanged), [`OnClosed`](/acegui/widgets/dropdown#onclosed) |
| `color` | [ColorPicker](/acegui/widgets/colorpicker) | [`SetLabel`](/acegui/widgets/colorpicker#setlabel), [`SetHasAlpha`](/acegui/widgets/colorpicker#sethasalpha), [`SetColor`](/acegui/widgets/colorpicker#setcolor) | [`OnValueChanged`](/acegui/widgets/colorpicker#onvaluechanged), [`OnValueConfirmed`](/acegui/widgets/colorpicker#onvalueconfirmed) |
| `keybinding` | [Keybinding](/acegui/widgets/keybinding) | [`SetLabel`](/acegui/widgets/keybinding#setlabel), [`SetKey`](/acegui/widgets/keybinding#setkey) | [`OnKeyChanged`](/acegui/widgets/keybinding#onkeychanged) |
| `header` | [Heading](/acegui/widgets/heading) | [`SetText`](/acegui/widgets/heading#settext) | (none) |
| `description` | [Label](/acegui/widgets/label) | [`SetText`](/acegui/widgets/label#settext), [`SetFontObject`](/acegui/widgets/label#setfontobject), [`SetImage`](/acegui/widgets/label#setimage), [`SetImageSize`](/acegui/widgets/label#setimagesize) | (none) |
For `multiselect`, the built-in fallback is not a single widget: AceConfigDialog builds a group
of [CheckBox](/acegui/widgets/checkbox) widgets inside an [InlineGroup](/acegui/containers/inlinegroup). The methods in
the table are the contract for a *custom* `dialogControl`, which mirrors a
multiselect-capable [Dropdown](/acegui/widgets/dropdown) ([`SetMultiselect`](/acegui/widgets/dropdown#setmultiselect),
[`SetItemValue`](/acegui/widgets/dropdown#setitemvalue)).
---
# AceComm-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-comm
# AceComm-3.0
AceComm-3.0 sends addon-channel messages of any length, splitting and reassembling them automatically. All sends are
routed through the bundled [`ChatThrottleLib`](https://wowpedia.fandom.com/wiki/ChatThrottleLib) to prevent server
disconnects.
## Usage
### Sending messages to other clients
Send data with [`:SendCommMessage`](#sendcommmessage). Provide a `prefix` tag, the `text` to send, and a `distribution`
channel:
```lua
MyAddon:SendCommMessage("MyPrefix", "the data to send", "RAID")
MyAddon:SendCommMessage("MyPrefix", "more data to send", "WHISPER", "charname")
```
::: tip
The valid distributions (`"PARTY"`, `"RAID"`, `"GUILD"`, `"WHISPER"`, …) are defined by the game's
[`C_ChatInfo.SendAddonMessage`](https://warcraft.wiki.gg/wiki/API_C_ChatInfo.SendAddonMessage) API and vary by client
version.
:::
### Receiving messages
Register the prefix you want to listen for. The default handler is `OnCommReceived`:
```lua
MyAddon:RegisterComm("prefix")
MyAddon:RegisterComm("prefix2", "MySecondCommHandler")
function MyAddon:OnCommReceived(prefix, message, distribution, sender)
-- process the incoming message
end
```
## API Reference
````apimethod
name: AceComm:Embed
returns: { type = "table", desc = "The target object, now embedded with the AceComm methods." }
params:
- { name = "target", type = "table", desc = "The object to embed AceComm-3.0 into." }
---
Copies AceComm's methods onto `target` so you can call them on it directly. See [The `:Embed` method](/api/ace-addon#the-embed-method).
````
````apimethod
name: AceComm:RegisterComm
returns: { type = "table", desc = "The registration object returned by [CallbackHandler](/api/callback-handler) (used internally to track the callback)." }
params:
- { name = "prefix", type = "string", desc = "A string of printable characters (\\032–\\255) identifying the message type, typically the addon or event name. Max 16 characters." }
- { name = "method", type = "function|string", default = "\"OnCommReceived\"", desc = "Callback to call on message reception: function reference, or method name to call on `self`. The callback receives `prefix`, `message`, `distribution` and `sender`." }
---
Register for addon messages on the given prefix. The prefix is also registered via [`C_ChatInfo.RegisterAddonMessagePrefix`](https://warcraft.wiki.gg/wiki/API_C_ChatInfo.RegisterAddonMessagePrefix) so the game delivers [`CHAT_MSG_ADDON`](https://warcraft.wiki.gg/wiki/CHAT_MSG_ADDON) events for it. Multipart messages are reassembled before the callback fires.
---
```lua
self:RegisterComm("MyPrefix")
function MyAddon:OnCommReceived(prefix, message, distribution, sender)
-- process the incoming message
end
```
````
````apimethod
name: AceComm:SendCommMessage
params:
- { name = "prefix", type = "string", desc = "A string of printable characters (\\032–\\255) identifying the message type, typically the addon or event name." }
- { name = "text", type = "string", desc = "Text to send. NUL bytes (\\000) are not allowed." }
- { name = "distribution", type = "string", desc = "Addon channel, e.g. `\"RAID\"`, `\"GUILD\"`, etc; see [`C_ChatInfo.SendAddonMessage`](https://warcraft.wiki.gg/wiki/API_C_ChatInfo.SendAddonMessage) API." }
- { name = "target", type = "string|number", optional = true, desc = "Destination for some distributions (e.g. the recipient name for `\"WHISPER\"`)." }
- { name = "prio", type = "string", default = "\"NORMAL\"", desc = "ChatThrottleLib priority, `\"BULK\"`, `\"NORMAL\"` or `\"ALERT\"`. The same priority is used for every chunk of a multipart message to guarantee in-order delivery." }
- { name = "callbackFn", type = "function", optional = true, desc = "Callback function called as each chunk is sent. Receives 3 args: the user-supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send." }
- { name = "callbackArg", type = "any", optional = true, desc = "First arg to the callback function. `nil` if not specified." }
---
Send a message over an addon channel.
Messages up to 255 bytes are sent as a single addon message; longer text is split into tagged chunks and reassembled on the receiving end. A leading control byte (`\001`–`\009`) in the text is transparently escaped. `prefix`, `text`, and `distribution` are required; wrong types or an invalid `prio` raise a usage error.
````
````apimethod
name: AceComm:UnregisterComm
params:
- { name = "prefix", type = "string", desc = "The prefix to stop listening for." }
---
Unregister a comm callback previously registered with [`:RegisterComm`](#registercomm) for the given prefix. This method is generated by CallbackHandler.
````
````apimethod
name: AceComm:UnregisterAllComm
---
Unregister all comm callbacks registered by this addon object (or custom `self`). This method is generated by CallbackHandler and is also called automatically when an embedded AceComm is disabled.
````
---
# AceSerializer-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-serializer
# AceSerializer-3.0
AceSerializer-3.0 can serialize any variable (except functions or userdata) into a string format that can be sent over
the addon communication channel.
AceSerializer was designed to keep all data intact, especially very large numbers or floating point numbers, and table
structures. The only caveat currently is, that multiple references to the same table will be send individually.
## Usage
Mix it in when creating your addon object:
```lua
MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceSerializer-3.0")
```
Serialize any values into a string:
```lua
local MyVal1 = 23
local MyVal2 = "some text"
local MyVal3 = { "foo", 42, "bar" }
local serializedData = MyAddon:Serialize(MyVal1, MyVal2, MyVal3)
```
Deserialize. The first return is a success boolean; on success the original values follow, on failure an error message:
```lua
local success, v1, v2, v3 = MyAddon:Deserialize(serializedData)
if not success then
-- handle error (v1 is the error message)
end
```
Combine with [AceComm-3.0](/api/ace-comm) to send structured data between clients.
## API Reference
````apimethod
name: AceSerializer:Embed
params:
- { name = "target", type = "table", desc = "The target object to embed AceSerializer into." }
returns: { type = "table", desc = "The target object." }
---
Copies AceSerializer's methods onto `target` so you can call them on it directly. See [The `:Embed` method](/api/ace-addon#the-embed-method).
````
````apimethod
name: AceSerializer:Serialize
params:
- { name = "...", type = "any", desc = "List of values to serialize (strings, numbers, booleans, `nil`s, tables)." }
returns: { type = "string", desc = "The data in its serialized form." }
---
Serialize the data passed into the function.
Takes a list of values (strings, numbers, booleans, `nil`s, tables) and returns it in serialized form (a string). May throw errors on invalid data types.
````
````apimethod
name: AceSerializer:Deserialize
params:
- { name = "str", type = "string", desc = "The serialized data (from [`:Serialize`](#serialize))." }
returns:
- { name = "success", type = "boolean", desc = "`true` on success, `false` on failure." }
- { name = "...", type = "any", desc = "On success, the deserialized list of values; on failure, the error message (string)." }
---
Deserializes the data into its original values.
Accepts serialized data, ignoring all control characters and whitespace.
---
```lua
local ok, value = self:Deserialize(payload)
if ok then
-- use value
end
```
````
---
# AceLocale-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-locale
# AceLocale-3.0
AceLocale-3.0 manages localization in addons, allowing for multiple locale to be registered with fallback to the base
locale for untranslated strings.
## Usage
### Registering translations
Create one Lua file per locale and list it in the `.toc` **before** your main code (see
the [Getting Started](/getting-started) load-order note). Fetch a locale table at the top:
```lua
-- enUS.lua (default locale)
local L = LibStub("AceLocale-3.0"):NewLocale("MyAddon", "enUS", true)
if L then
L["HELLO"] = "Hello!"
L["CONFIG_DESC"] = "Opens the configuration window"
end
```
The third argument marks the default locale (usually `true` for `enUS`, `false` elsewhere). [`:NewLocale`](#newlocale)
returns `nil` if that locale isn't needed for the current client, so guard with `if L then`.
#### Default locale: explicit values vs. the `true` shorthand
In the **default** locale you can declare each entry two ways:
**Explicit English value (recommended).** Use a stable identifier as the key and put the English wording in the value:
```lua
-- enUS.lua (default locale)
local L = LibStub("AceLocale-3.0"):NewLocale("MyAddon", "enUS", true)
L["HELLO"] = "Hello!"
```
`L["HELLO"]` returns `"Hello!"`. Because the displayed text lives only in the value, you can fix the English wording (
`"Hello!"` → `"Hi!"`) without changing the key, so no other locale file and no code referencing `L["HELLO"]` breaks.
**`true` shorthand.** Assigning `true` tells AceLocale to use the key *itself* as the value, so you write the English
text once, as the key:
```lua
-- enUS.lua (default locale)
local L = LibStub("AceLocale-3.0"):NewLocale("MyAddon", "enUS", true)
L["Hello!"] = true
```
`L["Hello!"]` returns `"Hello!"`. This is only valid in the default locale (it's how AceLocale avoids you typing the
string twice). The cost: the key *is* the English text, so every other locale must key off `"Hello!"` and your code must
call `L["Hello!"]`. Correcting the English wording changes the key, breaking every lookup and translation that
referenced the old text.
::: tip
Both are valid; prefer **constant keys with explicit values** for anything you may reword later. The `true` shorthand is
convenient for short, stable strings where the English text is unlikely to change.
:::
### Using translations
In your main file, fetch the active locale table:
```lua
local L = LibStub("AceLocale-3.0"):GetLocale("MyAddon", true)
function MyAddon:MyFunction()
self:Print(L["HELLO"])
end
```
The second argument silences the error if locale info is missing.
### Variable substitution
Use functions for strings that mix in variables, so word order can differ per language:
```lua
-- enUS:
L["ADDED_DKP"] = function(amount, player)
return "Added " .. amount .. " DKP for player " .. player .. "."
end
-- usage:
self:Print(L["ADDED_DKP"](dkpValue, playerName))
```
## API Reference
````apimethod
name: AceLocale:NewLocale
returns: { type = "table|nil", desc = "Locale table to add localizations to, or nil if the current game locale is not required." }
params:
- { name = "application", type = "string", desc = "Unique name of addon / module." }
- { name = "locale", type = "string", desc = "Name of the locale to register, e.g. \"enUS\", \"deDE\", etc." }
- { name = "isDefault", type = "boolean", optional = true, desc = "If this is the default locale being registered (your addon is written in this language, generally enUS)." }
- { name = "silent", type = "boolean|string", optional = true, desc = "If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to \"raw\", nils will be returned for unknown keys (no metatable used)." }
---
Register a new locale (or extend an existing one) for the specified application.
`:NewLocale` will return a table you can fill your locale into, or `nil` if the locale isn't needed for the player's game locale.
---
```lua
-- enUS.lua (default locale)
local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
L["HELLO"] = "Hello!"
L["GOODBYE"] = "Goodbye!"
```
Stable constant keys (`HELLO`) with the wording in the value let you fix the English text without changing the key. Other locales translate the same keys:
```lua
-- deDE.lua
local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
if not L then return end
L["HELLO"] = "Hallo!"
L["GOODBYE"] = "Auf Wiedersehen!"
```
````
````apimethod
name: AceLocale:GetLocale
returns: { type = "table|nil", desc = "The locale table for the current language, or nil if silent is true and no locale is registered for the application." }
params:
- { name = "application", type = "string", desc = "Unique name of addon / module." }
- { name = "silent", type = "boolean", default = "false", desc = "If true, the locale is optional; silently return nil if it's not found." }
---
Returns localizations for the current locale (or default locale if translations are missing).
Errors if nothing is registered for the application (indicating a developer misconfiguration, not a missing translation), unless `silent` is set.
````
---
# AceTab-3.0
URL: https://wowace-docs.nickdnk.workers.dev/api/ace-tab
# AceTab-3.0
AceTab-3.0 provides support for tab-completion in chat edit boxes. It lets you register sets of completions that fire
when the user presses Tab in a monitored EditBox, optionally gated behind a "prematch" precondition string, with support
for cycling through multiple matches, usage statements, and post-processing of matched words.
## API Reference
````apimethod
name: AceTab:RegisterTabCompletion
params:
- { name = "descriptor", type = "string", desc = "Unique identifier for this tab completion set." }
- { name = "prematches", type = "string|table|nil", desc = "The string match(es) AFTER which this tab completion applies; AceTab ignores tabs not preceded by the string(s). If nil (or an empty string), the set is treated as a fallback that only applies when no more-specific completion has a match." }
- { name = "wordlist", type = "function|table", desc = "A table of candidate completion strings, or a function that is passed a table to fill with candidate strings. The function also receives the full editbox text, the start position of the word being completed, and the uncompleted partial word as its second, third, and fourth arguments (for pre-filtering or conditional formatting)." }
- { name = "usagefunc", type = "function|boolean", optional = true, desc = "Usage statement function. Defaults to printing the wordlist, one entry per line. A boolean true squelches usage output." }
- { name = "listenframes", type = "string|table", optional = true, desc = "The EditFrame(s) to monitor, given as frame references or frame names. Defaults to the chat frame edit boxes (ChatFrame1EditBox … ChatFrameNEditBox)." }
- { name = "postfunc", type = "function", optional = true, desc = "Post-processing function applied to each match after it has been identified, producing the displayed/inserted form of the match." }
- { name = "pmoverwrite", type = "boolean|number", optional = true, desc = "Offsets the beginning of the inserted completion to overwrite part of the prematch. Boolean true overwrites the entire prematch string; a number overwrites that many characters before the cursor. Useful when the prematch is an indicator character you don't want to keep." }
---
Register a tab completion set.
Once registered, pressing Tab in any monitored EditBox will attempt to complete the word before the cursor against the provided wordlist (subject to the `prematches` precondition, if any). If multiple completions match, the entered text is replaced with the greatest common substring of all matches, and repeated Tab presses cycle through the individual matches.
```lua
local AceTab = LibStub("AceTab-3.0")
local greetings = { "hello", "howdy", "hey", "heya" }
-- Complete words that follow "greet " typed in a chat edit box.
AceTab:RegisterTabCompletion("MyGreetings", "greet ", greetings)
```
---
```lua
-- Using a wordlist function for dynamic candidates.
AceTab:RegisterTabCompletion("MyPlayers", "to ", function(candidates, fulltext, wordStart, partial)
for name in pairs(myRosterTable) do
candidates[#candidates + 1] = name
end
end)
```
````
````apimethod
name: AceTab:IsTabCompletionRegistered
returns: { type = "table|nil", desc = "The stored registry entry for the descriptor (a truthy value) if registered, otherwise nil." }
params:
- { name = "descriptor", type = "string", desc = "The unique identifier used at registration." }
---
Check whether a tab completion set has been registered under the given descriptor.
````
````apimethod
name: AceTab:UnregisterTabCompletion
params:
- { name = "descriptor", type = "string", desc = "The unique identifier used at registration." }
---
Remove a previously registered tab completion set. Clears the descriptor's registry entry along with its internal prematch-overwrite, fallback, and non-fallback bookkeeping.
````
````apimethod
name: AceTab:OnTabPressed
kind: callback
returns: { type = "boolean|nil", desc = "True to let the default/original Tab handling proceed (e.g. when there is no text or a completion could not be applied); otherwise nothing, indicating AceTab handled the key." }
params:
- { name = "editbox", type = "table", desc = "The EditBox in which Tab was pressed. (Named `this` in the source, after the legacy WoW convention for the frame in a script handler.)" }
---
Internal handler invoked when Tab is pressed in a monitored EditBox; it builds matches, performs insertion, and drives match cycling. AceTab hooks this onto the relevant frame scripts automatically when you register a completion, so addons normally do not call it directly.
````
---
# CallbackHandler-1.0
URL: https://wowace-docs.nickdnk.workers.dev/api/callback-handler
# CallbackHandler-1.0
CallbackHandler-1.0 is the small dispatch engine that powers the "callback" and "message" systems across the Ace
suite: [AceEvent-3.0](/api/ace-event), [AceComm-3.0](/api/ace-comm), [AceBucket-3.0](/api/ace-bucket),
[AceDB-3.0](/api/ace-db#callbacks)'s profile callbacks, and [AceConfigRegistry-3.0](/api/ace-config-registry) all build
on it. You rarely call it directly, but understanding it explains how those callbacks behave.
It has two sides: **addon authors** register handlers on a library that exposes CallbackHandler methods, and **library
authors** create a registry to fire events into.
## For addon authors
When a library is "powered by CallbackHandler", it exposes registration methods, by convention
[`RegisterCallback`](#registercallback), [`UnregisterCallback`](#unregistercallback), and
[`UnregisterAllCallbacks`](#unregisterallcallbacks). These are **called with a dot** and an explicit first argument
(your object, or a string addon id) that identifies you as the owner of the registration:
```lua
-- e.g. AceDB exposes these on the db object
self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig")
function MyAddon:RefreshConfig(event, ...)
-- event == "OnProfileChanged", followed by any args the library fired
end
```
::: tip Why the dot, and the explicit `self`
[`RegisterCallback`](#registercallback) is not called with `:`; you pass your `self` (or an `"addonId"` string)
explicitly as the first argument. CallbackHandler uses it both as the `self` for method-style handlers and as the key to
unregister you later. Calling it as `lib:RegisterCallback(...)` (passing the library as `self`) is an error.
:::
How your handler is invoked:
- **`method` as a string** → called as `self[method](self, event, ...)`.
- **`method` as a function** → called as `method(event, ...)`.
- If you supplied an **`arg`**, it is inserted *before* the event name: `self[method](self, arg, event, ...)` /
`method(arg, event, ...)`.
The first value your handler receives is always the **event name** (handy for sharing one handler across several
events); the firing library's own arguments follow.
````apimethod
name: obj.RegisterCallback
params:
- { name = "self", type = "table|string", desc = "Your object (used as the handler's `self` and as the unregister key), or an `\"addonId\"` string when registering a plain function." }
- { name = "eventname", type = "string", desc = "The event/message to listen for." }
- { name = "method", type = "string|function", optional = true, desc = "A method name on `self`, or a function reference. Defaults to `eventname` (i.e. a method named after the event)." }
- { name = "arg", type = "any", optional = true, desc = "Optional value passed to the handler *before* the event name." }
---
Register a handler for an event on a CallbackHandler-powered object. Called with a dot and an explicit `self`/addon id (see above).
````
````apimethod
name: obj.UnregisterCallback
params:
- { name = "self", type = "table|string", desc = "The same object/addon id used to register." }
- { name = "eventname", type = "string", desc = "The event to stop listening for." }
---
Remove a previously registered handler for `eventname`.
````
````apimethod
name: obj.UnregisterAllCallbacks
params:
- { name = "self", type = "table|string", desc = "The object/addon id whose registrations should all be removed." }
---
Remove every callback registered by the given owner. A library may choose not to publish this method.
````
## For library authors
Embed the registration API into your library and get back a **registry** to fire events through.
````apimethod
name: CallbackHandler:New
returns: { type = "table", desc = "The registry object (with [`:Fire`](#fire), and optional `OnUsed`/`OnUnused` hooks you can set)." }
params:
- { name = "target", type = "table", desc = "The object to embed the public registration methods into." }
- { name = "RegisterName", type = "string", default = "RegisterCallback", desc = "Name of the register method to publish." }
- { name = "UnregisterName", type = "string", default = "UnregisterCallback", desc = "Name of the unregister method to publish." }
- { name = "UnregisterAllName", type = "string|boolean", default = "UnregisterAllCallbacks", desc = "Name of the unregister-all method, or `false` to not publish it." }
---
Create a callback registry and embed `RegisterName`/`UnregisterName`/`UnregisterAllName` onto `target`.
---
```lua
local CallbackHandler = LibStub("CallbackHandler-1.0")
local MyLib = {}
MyLib.callbacks = CallbackHandler:New(MyLib)
-- MyLib.RegisterCallback / UnregisterCallback / UnregisterAllCallbacks now exist
```
````
````apimethod
name: registry:Fire
params:
- { name = "eventname", type = "string", desc = "The event/message to dispatch." }
- { name = "...", type = "any", desc = "Arguments forwarded to every registered handler (after the event name)." }
---
Fire an event into the registry, invoking every handler registered for `eventname`.
Registering or unregistering from *inside* a handler is safe: CallbackHandler queues the change and applies it once the current dispatch finishes.
---
```lua
function MyLib:DoThing()
self.callbacks:Fire("OnThingDone", "some", "data")
end
-- a listener's handler receives: (event, "some", "data")
```
````
### Lazy activation hooks
The registry exposes two optional hooks you can assign. They let a library do expensive setup only while something is
actually listening; this is how AceEvent only registers a game event with the client while at least one handler wants
it:
- **`registry.OnUsed(registry, target, eventname)`**: called when `eventname` gets its **first** handler.
- **`registry.OnUnused(registry, target, eventname)`**: called when `eventname` loses its **last** handler.
```lua
function MyLib.callbacks:OnUsed(target, eventname)
-- start producing eventname (e.g. hook a frame, register a game event)
end
function MyLib.callbacks:OnUnused(target, eventname)
-- stop producing eventname
end
```
---
# Common Widget API
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widget-api
# Common Widget API
Every [AceGUI-3.0](/acegui/) widget inherits a common set of methods from `WidgetBase`. Containers inherit an additional
set from `WidgetContainerBase` (which itself extends `WidgetBase`).
The per-widget pages in this section document **only the methods and callbacks specific to that widget**; the methods
below are available on *every* widget and are not repeated there.
## Widget Methods
Available on every widget and container.
````apimethod
name: widget:SetWidth
params:
- { name = "width", type = "number", desc = "The width in pixels." }
---
Set the widget's width in pixels. Fires the widget's internal [`OnWidthSet`](#onwidthset) hook if it defines one.
````
````apimethod
name: widget:SetHeight
params:
- { name = "height", type = "number", desc = "The height in pixels." }
---
Set the widget's height in pixels. Fires the widget's internal [`OnHeightSet`](#onheightset) hook if it defines one.
````
````apimethod
name: widget:SetRelativeWidth
params:
- { name = "width", type = "number", desc = "Fraction of the parent's width; must be greater than `0` and at most `1`." }
---
Set the width as a fraction of the parent container's width. `width` must be greater than `0` and at most `1` (e.g. `0.5` for half width). Errors on an invalid value.
````
````apimethod
name: widget:SetFullWidth
params:
- { name = "isFull", type = "boolean", desc = "Truthy to fill the full row width; falsy to clear." }
---
When `isFull` is truthy, the widget fills the full width of its container row. Pass a falsy value to clear it.
````
````apimethod
name: widget:IsFullWidth
returns: { type = "boolean", desc = "`true` if the widget is set to full width." }
---
Returns `true` if the widget is set to full width.
````
````apimethod
name: widget:SetFullHeight
params:
- { name = "isFull", type = "boolean", desc = "Truthy to fill the full available height; falsy to clear." }
---
When `isFull` is truthy, the widget fills the full available height. Pass a falsy value to clear it.
````
````apimethod
name: widget:IsFullHeight
returns: { type = "boolean", desc = "`true` if the widget is set to full height." }
---
Returns `true` if the widget is set to full height.
````
````apimethod
name: widget:SetPoint
params:
- { name = "...", type = "any", desc = "Anchoring arguments forwarded to the frame's `SetPoint`." }
---
Passes through to the underlying frame's [`SetPoint`](https://warcraft.wiki.gg/wiki/API_ScriptRegionResizing_SetPoint). Manual anchoring is generally unnecessary; let the container's layout position the widget.
````
````apimethod
name: widget:ClearAllPoints
---
Passes through to the underlying frame's [`ClearAllPoints`](https://warcraft.wiki.gg/wiki/API_ScriptRegionResizing_ClearAllPoints).
````
````apimethod
name: widget:GetPoint
params:
- { name = "...", type = "any", desc = "Arguments forwarded to the frame's `GetPoint`." }
---
Passes through to the underlying frame's [`GetPoint`](https://warcraft.wiki.gg/wiki/API_ScriptRegionResizing_GetPoint).
````
````apimethod
name: widget:GetNumPoints
returns: { type = "number", desc = "The number of anchor points on the underlying frame." }
---
Passes through to the underlying frame's [`GetNumPoints`](https://warcraft.wiki.gg/wiki/API_ScriptRegionResizing_GetNumPoints).
````
````apimethod
name: widget:SetCallback
params:
- { name = "name", type = "string", desc = "The callback/event name (e.g. \"OnClick\")." }
- { name = "func", type = "function", desc = "Handler; called as (widget, event, ...). Non-functions are ignored." }
---
Register a callback handler for one of the widget's events. `func` is called with the widget as its first argument and the callback name as its second, followed by any event-specific arguments. Passing a non-function is ignored.
---
```lua
button:SetCallback("OnClick", function(widget, event) print("clicked") end)
```
````
````apimethod
name: widget:Fire
returns: { type = "any", desc = "The handler's return value, if it ran successfully." }
params:
- { name = "name", type = "string", desc = "The callback/event name to fire." }
- { name = "...", type = "any", desc = "Extra arguments passed along to the handler." }
---
Fire a registered callback by name, passing along any extra arguments. The handler is invoked with the widget and the event name prepended to the arguments. If the handler ran successfully, its return value is returned. Used internally by widgets; you normally consume callbacks via [`SetCallback`](#setcallback) rather than calling `Fire` yourself.
````
````apimethod
name: widget:SetUserData
params:
- { name = "key", type = "any", desc = "The key under which to store the value." }
- { name = "value", type = "any", desc = "The value to store." }
---
Store arbitrary data on the widget under `key`. Useful for associating application state with a widget instance.
````
````apimethod
name: widget:GetUserData
returns: { type = "any", desc = "The previously stored value, or `nil`." }
params:
- { name = "key", type = "any", desc = "The key to look up." }
---
Retrieve a value previously stored with [`SetUserData`](#setuserdata).
````
````apimethod
name: widget:GetUserDataTable
returns: { type = "table", desc = "The widget's full user-data table." }
---
Returns the widget's full user-data table.
````
````apimethod
name: widget:SetParent
params:
- { name = "parent", type = "table", desc = "The widget whose content frame becomes the new parent." }
---
Reparents the widget to another widget's content frame. Containers call this for you in [`AddChild`](#addchild).
````
````apimethod
name: widget:IsVisible
returns: { type = "boolean", desc = "The underlying frame's visibility." }
---
Returns the underlying frame's visibility (via [`IsVisible`](https://warcraft.wiki.gg/wiki/API_ScriptRegion_IsVisible)).
````
````apimethod
name: widget:IsShown
returns: { type = "boolean", desc = "The underlying frame's shown state." }
---
Returns the underlying frame's shown state (via [`IsShown`](https://warcraft.wiki.gg/wiki/API_ScriptRegion_IsShown)).
````
````apimethod
name: widget:Release
---
Releases the widget back to the widget pool (shortcut for `AceGUI:Release(widget)`).
````
````apimethod
name: widget:IsReleasing
returns: { type = "boolean", desc = "`true` if the widget is currently being released." }
---
Returns `true` if the widget is currently being released.
````
## Container Methods
Available on every container widget in addition to the widget methods above.
````apimethod
name: container:AddChild
params:
- { name = "child", type = "table", desc = "The child widget to add." }
- { name = "beforeWidget", type = "table", optional = true, desc = "An existing sibling to insert the child before." }
---
Add a child widget to the container and lay it out. If `beforeWidget` is supplied, the child is inserted before that existing sibling instead of appended.
````
````apimethod
name: container:AddChildren
params:
- { name = "...", type = "table", desc = "One or more child widgets to add." }
---
Add multiple child widgets at once, then perform a single layout pass.
````
````apimethod
name: container:ReleaseChildren
---
Release all child widgets back to the pool and clear the container's child list. Commonly called before redrawing a group's contents.
````
````apimethod
name: container:SetLayout
params:
- { name = "layout", type = "string", desc = "The registered layout name: `\"List\"`, `\"Flow\"`, `\"Fill\"` or `\"Table\"`." }
---
Set the layout function used to arrange children, by registered name: `"List"`, `"Flow"`, `"Fill"` or `"Table"`.
````
````apimethod
name: container:DoLayout
---
Lay out the container's children. Called automatically by [`AddChild`](#addchild)/[`AddChildren`](#addchildren); call it manually after changing children outside those methods.
````
````apimethod
name: container:PerformLayout
---
Runs the layout function immediately (unless layout is paused). [`DoLayout`](#dolayout) is the usual entry point.
````
````apimethod
name: container:PauseLayout
---
Suspend automatic layout. Useful when adding many children in a loop to avoid a layout pass per child.
````
````apimethod
name: container:ResumeLayout
---
Resume automatic layout after [`PauseLayout`](#pauselayout). Follow with [`DoLayout`](#dolayout) to apply.
---
```lua
container:PauseLayout()
for _, item in ipairs(items) do
local w = AceGUI:Create("Label")
w:SetText(item)
container:AddChild(w)
end
container:ResumeLayout()
container:DoLayout()
```
````
````apimethod
name: container:SetAutoAdjustHeight
params:
- { name = "adjust", type = "boolean", desc = "Truthy (the default) to auto-resize height to fit content; `false` to keep a fixed height." }
---
When `adjust` is truthy (the default), the container automatically resizes its height to fit its content. Pass `false` to keep a fixed height.
````
## Internal hooks
These are optional members a **widget implementation** may define; AceGUI calls them for you. Addon authors don't call
or register them (consume widgets through their public methods); they matter when you build a custom widget.
[`OnAcquire`](#onacquire) and [`OnRelease`](#onrelease) are driven by the [widget pool](/acegui/#frame-pooling);
[`OnWidthSet`](#onwidthset) / [`OnHeightSet`](#onheightset) by sizing; and [`LayoutFinished`](#layoutfinished) by the
layout pass.
````apimethod
name: widget:OnAcquire
kind: callback
---
Called by [`AceGUI:Create`](/acegui/#create) when the widget is handed out (whether freshly created or reused from the pool) to reset it to its default state (size, text, value, …). This is why a recycled widget never carries over data from its previous user.
````
````apimethod
name: widget:OnRelease
kind: callback
---
Called by [`AceGUI:Release`](/acegui/#release) before the widget returns to the pool. Clears the widget's data and hides it.
````
````apimethod
name: widget:OnWidthSet
kind: callback
params:
- { name = "width", type = "number", desc = "The new width in pixels." }
---
Called by [`SetWidth`](#setwidth) after the frame is resized, if the widget defines it. A widget implementation uses this to re-lay-out its contents for the new width. Use this rather than the frame's own `OnSizeChanged`; AceGUI already manages that.
````
````apimethod
name: widget:OnHeightSet
kind: callback
params:
- { name = "height", type = "number", desc = "The new height in pixels." }
---
Called by [`SetHeight`](#setheight) after the frame is resized, if the widget defines it. A widget implementation uses this to re-lay-out its contents for the new height. Use this rather than the frame's own `OnSizeChanged`; AceGUI already manages that.
````
````apimethod
name: widget:LayoutFinished
kind: callback
params:
- { name = "width", type = "number", desc = "Width of the area used by the laid-out controls, or `nil` if the layout used the existing size." }
- { name = "height", type = "number", desc = "Height of the area used by the laid-out controls, or `nil` if the layout used the existing size." }
---
Called on a container after a layout pass finishes. A container implementation uses this to size itself to its content; auto-growing groups add their content height here.
````
---
# Button
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/button
# Button
A graphical push button built on Blizzard's
[`UIPanelButtonTemplate`](https://warcraft.wiki.gg/wiki/UIPanelButtonTemplate).
Create with `AceGUI:Create("Button")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `Button`
## Methods
````apimethod
name: widget:SetText
params:
- { name = "text", type = "string", optional = true, desc = "The label to display. Passing `nil` clears the text." }
---
Sets the button's caption. If auto-width is enabled, the button is resized to fit the text (string width + 30px padding).
````
````apimethod
name: widget:SetAutoWidth
params:
- { name = "autoWidth", type = "boolean", desc = "`true` to size the button to its text, `false` to keep the fixed width." }
---
Toggles automatic width sizing. When enabled, the button immediately resizes to its current text width plus 30px, and every subsequent [`SetText`](#settext) re-fits the width.
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the button. A disabled button cannot be clicked and is greyed out by the template.
````
## Defaults
On acquire the button resets to: height 24, width 200, not disabled, auto-width off, and empty text.
## Callbacks
````apimethod
name: OnClick
kind: callback
params:
- { name = "...", type = "any", desc = "The native button click args forwarded from the frame's `OnClick` (e.g. the mouse `button` and `down` state)." }
---
Fired when the button is clicked. Before firing, AceGUI clears focus and plays the menu-option click sound. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the button. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the button. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local btn = AceGUI:Create("Button")
btn:SetText("Apply")
btn:SetAutoWidth(true)
btn:SetCallback("OnClick", function(widget)
print("Apply clicked")
end)
```
---
# CheckBox
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/checkbox
# CheckBox
A checkbox or radio button control with an optional label, description, and image. Supports a tri-state mode.
Create with `AceGUI:Create("CheckBox")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `CheckBox`
## Methods
````apimethod
name: widget:SetValue
params:
- { name = "value", type = "boolean", optional = true, desc = "`true` (checked), `false` (unchecked), or `nil` (only meaningful in tri-state mode)." }
---
Sets the checked state and updates the check texture. In tri-state mode, a `nil` value shows a desaturated check to represent the "unknown/mixed" state; `false` hides the check; any truthy value shows the normal check.
````
````apimethod
name: widget:GetValue
returns: { type = "boolean", desc = "The current checked state (`true`, `false`, or `nil` for the tri-state unknown value)." }
---
Returns the current checked state.
````
````apimethod
name: widget:ToggleChecked
---
Cycles the value. In normal mode it flips between `true`/`false`. In tri-state mode it cycles in the order `true` → `nil` → `false` → `true`.
````
````apimethod
name: widget:SetTriState
params:
- { name = "enabled", type = "boolean", desc = "`true` to allow the third (`nil`) state." }
---
Enables or disables tri-state behavior, then re-applies the current value so the display updates.
````
````apimethod
name: widget:SetType
params:
- { name = "type", type = "string", optional = true, desc = "`\"radio\"` for radio-button textures (16px), or anything else / `nil` for the default checkbox textures (24px)." }
---
Switches the visual style between a checkbox and a radio button.
````
````apimethod
name: widget:SetLabel
params:
- { name = "label", type = "string", optional = true, desc = "The label string." }
---
Sets the text shown next to the box.
````
````apimethod
name: widget:SetDescription
params:
- { name = "desc", type = "string", optional = true, desc = "The description text, or `nil`/`\"\"` to remove it." }
---
Sets an optional supplementary description line beneath the label. Passing a value creates the description font string (if needed) and grows the widget height to fit it; passing `nil`/`""` removes it and resets the height to 24.
````
````apimethod
name: widget:SetImage
params:
- { name = "path", type = "string|number", optional = true, desc = "Texture path or file ID. `nil` clears the image." }
- { name = "...", type = "number", desc = "Optional tex-coords. Pass 4 values (for [`SetTexCoord(left, right, top, bottom)`](https://warcraft.wiki.gg/wiki/API_Texture_SetTexCoord)) or 8 values for the full corner form; otherwise the full texture (`0, 1, 0, 1`) is used." }
---
Sets an optional icon texture shown before the label and realigns the label accordingly.
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the control. When disabled the label/description are greyed and the check is desaturated. When enabled, the check is desaturated only in tri-state mode with a `nil` value.
````
````apimethod
name: widget:OnWidthSet
params:
- { name = "width", type = "number", desc = "The new width." }
---
Internal layout hook called when the width changes; re-wraps the description text and recomputes the height. Not normally called directly.
````
## Defaults
On acquire the control resets to: checkbox type (not radio), value `false`, tri-state off, width 200, no image, not
disabled, and no description.
## Callbacks
````apimethod
name: OnValueChanged
kind: callback
params:
- { name = "checked", type = "boolean", optional = true, desc = "The new value (`true`, `false`, or `nil` in tri-state)." }
---
Fired when the user clicks the box (mouse up) and the value is toggled. A check-on/check-off sound is played first. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the control. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the control. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local cb = AceGUI:Create("CheckBox")
cb:SetLabel("Enable feature")
cb:SetDescription("Turns the feature on or off for this character.")
cb:SetValue(db.enabled)
cb:SetCallback("OnValueChanged", function(widget, event, checked)
db.enabled = checked
end)
```
---
# ColorPicker
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/colorpicker
# ColorPicker
A color swatch with an optional label that opens Blizzard's
[`ColorPickerFrame`](https://warcraft.wiki.gg/wiki/ColorPickerFrame) when clicked, with optional alpha (opacity)
support.
Create with `AceGUI:Create("ColorPicker")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `ColorPicker`
## Methods
````apimethod
name: widget:SetColor
params:
- { name = "r", type = "number", desc = "Red component in the `0`–`1` range." }
- { name = "g", type = "number", desc = "Green component in the `0`–`1` range." }
- { name = "b", type = "number", desc = "Blue component in the `0`–`1` range." }
- { name = "a", type = "number", default = "1", desc = "Alpha in the `0`–`1` range." }
---
Stores the current color and tints the swatch texture to match.
````
````apimethod
name: widget:SetHasAlpha
params:
- { name = "HasAlpha", type = "boolean", desc = "`true` to allow editing the alpha channel." }
---
Controls whether the color picker exposes the opacity slider. When alpha is disabled, the widget forces alpha to `1` in its callbacks.
````
````apimethod
name: widget:SetLabel
params:
- { name = "text", type = "string", optional = true, desc = "The label string, or `nil` to clear." }
---
Sets the text shown to the right of the swatch.
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the swatch. A disabled swatch will not open the color picker and its label is greyed.
````
## Defaults
On acquire the widget resets to: height 24, width 200, alpha disabled, color black opaque (`0, 0, 0, 1`), not disabled,
and no label.
## Callbacks
````apimethod
name: OnValueChanged
kind: callback
params:
- { name = "r", type = "number", desc = "Red component in the `0`–`1` range." }
- { name = "g", type = "number", desc = "Green component in the `0`–`1` range." }
- { name = "b", type = "number", desc = "Blue component in the `0`–`1` range." }
- { name = "a", type = "number", desc = "Alpha in the `0`–`1` range." }
---
Fired live while the `ColorPickerFrame` is open and the color is changed (and not equal to the previous value). Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnValueConfirmed
kind: callback
params:
- { name = "r", type = "number", desc = "Red component in the `0`–`1` range." }
- { name = "g", type = "number", desc = "Green component in the `0`–`1` range." }
- { name = "b", type = "number", desc = "Blue component in the `0`–`1` range." }
- { name = "a", type = "number", desc = "Alpha in the `0`–`1` range." }
---
Fired once after the color picker is closed (on the final alpha callback), to signal the user committed a value, including via cancel which restores the original color. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the swatch. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the swatch. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local cp = AceGUI:Create("ColorPicker")
cp:SetLabel("Bar color")
cp:SetHasAlpha(true)
cp:SetColor(db.r, db.g, db.b, db.a)
cp:SetCallback("OnValueConfirmed", function(widget, event, r, g, b, a)
db.r, db.g, db.b, db.a = r, g, b, a
end)
```
---
# Dropdown
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/dropdown
# Dropdown
A dropdown menu built on [`UIDropDownMenuTemplate`](https://warcraft.wiki.gg/wiki/UIDropDownMenuTemplate) with an
optional label. It opens a scrollable pullout of selectable items and supports both single-select and multi-select (
checkbox) modes.
Create with `AceGUI:Create("Dropdown")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `Dropdown`
> The pullout and its individual entries (`Dropdown-Pullout`, `Dropdown-Item-Toggle`, `Dropdown-Item-Execute`, etc.) are
> internal helper widgets created automatically. You normally only interact with the `Dropdown` widget's own methods
> below.
## Methods
````apimethod
name: widget:SetList
params:
- { name = "list", type = "table", optional = true, desc = "A `value → text` table. Passing `nil` empties the list." }
- { name = "order", type = "table", optional = true, desc = "Array of keys giving the display order. If omitted, keys are sorted automatically (numeric keys/strings numerically, everything else as strings)." }
- { name = "itemType", type = "string", default = "\"Dropdown-Item-Toggle\"", desc = "Widget type for each entry. An invalid type raises an error." }
---
Replaces the menu contents from a table. Clears any existing items (and the auto-added close button) and rebuilds the pullout.
````
````apimethod
name: widget:AddItem
params:
- { name = "value", type = "any", desc = "The item's value/key." }
- { name = "text", type = "string", desc = "The displayed text." }
- { name = "itemType", type = "string", default = "\"Dropdown-Item-Toggle\"", desc = "Item widget type." }
---
Adds a single entry to the existing list (also stored in the list table).
````
````apimethod
name: widget:SetValue
params:
- { name = "value", type = "any", desc = "The key to select." }
---
Selects a value: sets the displayed text from the list entry for that value and stores it as the current value. (Single-select use.)
````
````apimethod
name: widget:GetValue
returns: { type = "any", desc = "The currently selected value." }
---
Returns the currently selected value.
````
````apimethod
name: widget:SetText
params:
- { name = "text", type = "string", optional = true, desc = "The string to display, or `nil` for empty." }
---
Sets the text shown in the closed dropdown directly, without changing the selected value.
````
````apimethod
name: widget:SetLabel
params:
- { name = "text", type = "string", optional = true, desc = "The label string, or `nil`/`\"\"` to hide it." }
---
Sets an optional label above the dropdown. With a label the widget height becomes 40; without it, 26.
````
````apimethod
name: widget:SetMultiselect
params:
- { name = "multi", type = "boolean", desc = "`true` for multi-select (checkbox) mode, `false` for single-select." }
---
Switches between single-select and multi-select (checkbox) mode. In multi-select mode the closed text shows the comma-joined list of checked entries and a `"Close"` button is appended to the pullout.
````
````apimethod
name: widget:GetMultiselect
returns: { type = "boolean", desc = "Whether multi-select mode is enabled." }
---
Returns whether multi-select mode is enabled.
````
````apimethod
name: widget:SetItemValue
params:
- { name = "item", type = "any", desc = "The value/key identifying the entry." }
- { name = "value", type = "boolean", desc = "The checked state to apply." }
---
In multi-select mode, sets the checked state of a specific entry and refreshes the displayed multi-text. No-op when not in multi-select mode.
````
````apimethod
name: widget:SetItemDisabled
params:
- { name = "item", type = "any", desc = "The value/key identifying the entry." }
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables a specific entry in the pullout.
````
````apimethod
name: widget:SetPulloutWidth
params:
- { name = "width", type = "number", optional = true, desc = "Pixel width, or `nil` to auto-match the dropdown's own width." }
---
Overrides the width of the opened pullout. When `nil`, the pullout matches the dropdown's own width.
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the dropdown. A disabled dropdown greys its text/label and cannot be opened.
````
````apimethod
name: widget:ClearFocus
---
Closes the pullout if it is open.
````
## Defaults
On acquire the widget resets to: height 44, width 200, no label, auto pullout width, and an empty list. On release it
closes and releases its pullout and clears text, value, disabled, and multiselect state.
## Callbacks
````apimethod
name: OnValueChanged
kind: callback
params:
- { name = "value", type = "any", desc = "The selected/toggled entry's value." }
- { name = "checked", type = "boolean", optional = true, desc = "The entry's new checked state. Multi-select only; omitted in single-select mode." }
---
Fired when the user selects/toggles an entry. In single-select mode the handler receives just the newly selected `value` and the pullout then closes. In multi-select mode it also receives the toggled entry's `checked` state. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnOpened
kind: callback
---
Fired when the pullout opens. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnClosed
kind: callback
---
Fired when the pullout closes. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the dropdown (also locks the button highlight). Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the dropdown. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local dd = AceGUI:Create("Dropdown")
dd:SetLabel("Choose a class")
dd:SetList({
WARRIOR = "Warrior",
MAGE = "Mage",
PRIEST = "Priest",
}, { "WARRIOR", "MAGE", "PRIEST" })
dd:SetValue(db.class)
dd:SetCallback("OnValueChanged", function(widget, event, value)
db.class = value
end)
```
---
# EditBox
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/editbox
# EditBox
A single-line text input built on [`InputBoxTemplate`](https://warcraft.wiki.gg/wiki/Widget_API), with an optional label
and an accept button (`"OK"`). Supports drag-and-drop of items, spells, macros, and chat-link insertion.
Create with `AceGUI:Create("EditBox")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `EditBox`
## Methods
````apimethod
name: widget:SetText
params:
- { name = "text", type = "string", optional = true, desc = "The string to display, or `nil` for empty." }
---
Sets the contents of the edit box, resets the cursor to the start, and hides the accept button. Also updates the internally tracked "last text" so the change does not refire [`OnTextChanged`](#ontextchanged).
````
````apimethod
name: widget:GetText
returns: { type = "string", desc = "The current text in the edit box." }
---
Returns the current text in the edit box.
````
````apimethod
name: widget:SetLabel
params:
- { name = "text", type = "string", optional = true, desc = "The label string, or `nil`/`\"\"` to hide the label." }
---
Sets an optional label above the input. When a label is present the widget grows to height 44; when cleared it shrinks to height 26 and the input moves to the top.
````
````apimethod
name: widget:DisableButton
params:
- { name = "disabled", type = "boolean", desc = "`true` to suppress the accept button." }
---
Controls whether the inline `"OK"` accept button is shown when the text is edited. When disabled the button stays hidden.
````
````apimethod
name: widget:SetMaxLetters
params:
- { name = "num", type = "number", optional = true, desc = "Maximum letters; `0` (or `nil`) means no limit." }
---
Sets the maximum number of characters the user can enter.
````
````apimethod
name: widget:SetFocus
---
Gives keyboard focus to the edit box. If the frame is not yet shown, focus is applied the next time it shows.
````
````apimethod
name: widget:ClearFocus
---
Removes keyboard focus from the edit box and cancels any pending focus-on-show.
````
````apimethod
name: widget:HighlightText
params:
- { name = "from", type = "number", desc = "Start position of the selection." }
- { name = "to", type = "number", desc = "End position of the selection." }
---
Highlights a range of the text.
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the input. A disabled box ignores the mouse, drops focus, and greys the text and label.
````
## Defaults
On acquire the widget resets to: width 200, not disabled, no label, empty text, accept button enabled, and no max-letter
limit. On release it clears focus.
## Callbacks
````apimethod
name: OnEnterPressed
kind: callback
params:
- { name = "text", type = "string", desc = "The current value (or the dragged-in name)." }
---
Fired when the user presses Enter, clicks the accept (`"OK"`) button, or drops an item/spell/macro onto the box. If your handler returns a truthy value, the change is treated as cancelled: the accept sound is not played and the accept button stays visible. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnTextChanged
kind: callback
params:
- { name = "text", type = "string", desc = "The new value." }
---
Fired whenever the text changes and differs from the previous value. Shows the accept button. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the input. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the input. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local eb = AceGUI:Create("EditBox")
eb:SetLabel("Player name")
eb:SetMaxLetters(12)
eb:SetCallback("OnEnterPressed", function(widget, event, text)
db.name = text
print("Saved name:", text)
end)
```
---
# Heading
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/heading
# Heading
A horizontal divider with optional centered title text, used to separate sections of a layout.
Create with `AceGUI:Create("Heading")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `Heading`
## Methods
````apimethod
name: widget:SetText
params:
- { name = "text", type = "string", optional = true, desc = "The heading text, or `nil`/`\"\"` for a plain divider line." }
---
Sets the heading's centered title. When text is present, the divider line is split into a left and right segment around the label. When the text is empty or `nil`, the right segment is hidden and the left line spans the full width.
````
## Defaults
On acquire the heading resets to: empty text, full width, and height 18.
## Callbacks
This widget fires no callbacks.
## Example
```lua
local heading = AceGUI:Create("Heading")
heading:SetText("Display Options")
container:AddChild(heading)
```
---
# Icon
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/icon
# Icon
A clickable icon button that displays a texture with an optional caption beneath it.
Create with `AceGUI:Create("Icon")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `Icon`
## Methods
````apimethod
name: widget:SetLabel
params:
- { name = "text", type = "string", optional = true, desc = "The caption to display, or `nil`/`\"\"` to hide it." }
---
Sets the caption shown below the icon. Passing a non-empty string shows the label and sizes the widget to the image height plus 25px; passing `nil` or an empty string hides the label and sizes to the image height plus 10px.
````
````apimethod
name: widget:SetImage
params:
- { name = "path", type = "string|number", optional = true, desc = "Texture path or file ID. `nil` clears the image." }
- { name = "...", type = "number", desc = "Optional texture coordinates: either 4 (`left, right, top, bottom`) or 8 values. Any other count falls back to the full texture." }
---
Sets the icon texture. If texture coordinates are supplied as the trailing arguments, they are applied; otherwise the full texture (`0, 1, 0, 1`) is used.
````
````apimethod
name: widget:SetImageSize
params:
- { name = "width", type = "number", desc = "Texture width in pixels." }
- { name = "height", type = "number", desc = "Texture height in pixels." }
---
Sets the displayed size of the icon texture and adjusts the widget height accordingly (image height plus 25px when a label is shown, plus 10px otherwise).
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the icon. When disabled, the button stops responding and the label and image are greyed out.
````
## Defaults
On acquire the icon resets to: width 110, height 110, no label, no image, image size 64×64, and not disabled.
::: tip Deprecated
`SetText` is a deprecated alias for [`SetLabel`](#setlabel) and prints a warning. Use [`SetLabel`](#setlabel) instead.
:::
## Callbacks
````apimethod
name: OnClick
kind: callback
params:
- { name = "button", type = "string", desc = "The mouse button that was pressed (e.g. `\"LeftButton\"`)." }
---
Fired when the icon is clicked; AceGUI clears focus afterward. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the icon. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the icon. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local icon = AceGUI:Create("Icon")
icon:SetImage("Interface\\Icons\\INV_Misc_QuestionMark")
icon:SetImageSize(48, 48)
icon:SetLabel("Help")
icon:SetCallback("OnClick", function(widget, event, button)
print("Clicked with", button)
end)
```
---
# InteractiveLabel
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/interactivelabel
# InteractiveLabel
A [Label](/acegui/widgets/label) that responds to mouse interaction, adding a highlight texture and click/hover
callbacks.
Create with `AceGUI:Create("InteractiveLabel")`. It inherits the [Common Widget API](/acegui/widget-api). It is built on
top of the `Label` widget and supports all of [Label's methods](/acegui/widgets/label#methods) (`SetText`, `SetImage`,
`SetColor`, `SetFontObject`, etc.) in addition to the methods below.
**Widget type:** `InteractiveLabel`
## Methods
````apimethod
name: widget:SetHighlight
params:
- { name = "...", type = "any", desc = "Arguments forwarded to the highlight texture's [`SetTexture`](https://warcraft.wiki.gg/wiki/API_Texture_SetTexture) (e.g. a texture path or file ID); pass nothing to clear the highlight." }
---
Sets the texture shown when the label is hovered.
````
````apimethod
name: widget:SetHighlightTexCoord
params:
- { name = "...", type = "number", desc = "Either 4 (`left, right, top, bottom`) or 8 coordinate values. Any other count falls back to the full texture (`0, 1, 0, 1`)." }
---
Sets the texture coordinates of the highlight texture.
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables interaction. When disabled, the frame stops accepting mouse input and the text is greyed out.
````
## Defaults
On acquire the interactive label runs the inherited Label acquire (resetting text, image, color, font, and
justification), then clears the highlight texture and tex-coords and sets the widget enabled.
## Callbacks
In addition to any callbacks inherited from Label, the following are fired:
````apimethod
name: OnClick
kind: callback
params:
- { name = "button", type = "string", desc = "The mouse button that was pressed (e.g. `\"LeftButton\"`)." }
---
Fired when the label is clicked (on mouse down); AceGUI clears focus afterward. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the label. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the label. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local label = AceGUI:Create("InteractiveLabel")
label:SetText("Click me")
label:SetHighlight("Interface\\QuestFrame\\UI-QuestTitleHighlight")
label:SetCallback("OnClick", function(widget, event, button)
print("Clicked with", button)
end)
```
---
# Keybinding
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/keybinding
# Keybinding
A button for capturing a key combination, used to set keybindings in a config UI. Clicking it enters a capture mode that
records the next key, mouse button, or gamepad input.
Create with `AceGUI:Create("Keybinding")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `Keybinding`
## Methods
````apimethod
name: widget:SetKey
params:
- { name = "key", type = "string", optional = true, desc = "The binding string (e.g. `\"SHIFT-F\"`), or `\"\"`/`nil` to show as unbound." }
---
Sets the displayed binding. An empty/`nil` key shows the localized [`NOT_BOUND`](https://warcraft.wiki.gg/wiki/FrameXML_functions) text in the normal font; a non-empty key is shown highlighted.
````
````apimethod
name: widget:GetKey
returns: { type = "string", desc = "The current binding string, or `nil` if the button shows the unbound (`NOT_BOUND`) text." }
---
Returns the current binding string, or `nil` if the button shows the unbound (`NOT_BOUND`) text.
````
````apimethod
name: widget:SetLabel
params:
- { name = "label", type = "string", optional = true, desc = "The label text, or `\"\"`/`nil` for no label." }
---
Sets the descriptive label above the button. A non-empty label sets the widget height to 44 and an align offset of 30; an empty label sets height 24 with no offset.
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the button. When disabled, the button cannot be clicked and the label is greyed out.
````
## Defaults
On acquire the widget resets to: width 200, empty label, empty key, not waiting for a key, hidden prompt message, not
disabled, and keyboard/mouse-wheel/gamepad capture turned off until the button is clicked.
## Behavior
Clicking the button with the left or right mouse button toggles capture mode (a prompt frame appears). While capturing,
the next key/mouse-button/wheel/gamepad input is recorded as the binding (combining `SHIFT-`, `CTRL-`, `ALT-`
modifiers). Pressing `ESCAPE` clears the binding. Certain keys (`BUTTON1`, `BUTTON2`, `UNKNOWN`, and the bare modifier
keys) are ignored.
## Callbacks
````apimethod
name: OnKeyChanged
kind: callback
params:
- { name = "key", type = "string", desc = "The new binding string (`\"\"` if cleared with ESCAPE)." }
---
Fired after a new binding is captured (unless the widget is disabled), after the key has already been applied via [`SetKey`](#setkey). Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the button. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the button. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local kb = AceGUI:Create("Keybinding")
kb:SetLabel("Open menu")
kb:SetKey("SHIFT-M")
kb:SetCallback("OnKeyChanged", function(widget, event, key)
print("New binding:", key)
end)
```
---
# Label
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/label
# Label
Displays text and optionally an icon, sizing its height dynamically to fit the content.
Create with `AceGUI:Create("Label")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `Label`
## Methods
````apimethod
name: widget:SetText
params:
- { name = "text", type = "string", optional = true, desc = "The text to display. Passing `nil` clears it; zero-height labels are forced to 1px so they can serve as spacers." }
---
Sets the label's text and re-lays out the text/image anchors.
````
````apimethod
name: widget:SetColor
params:
- { name = "r", type = "number", optional = true, desc = "Red component in the range `0`–`1`. Defaults to white (`1, 1, 1`) if any component is missing." }
- { name = "g", type = "number", optional = true, desc = "Green component in the range `0`–`1`." }
- { name = "b", type = "number", optional = true, desc = "Blue component in the range `0`–`1`." }
---
Sets the vertex color of the label text. If any component is missing, the color defaults to white (`1, 1, 1`).
````
````apimethod
name: widget:SetImage
params:
- { name = "path", type = "string|number", optional = true, desc = "Texture path or file ID, or `nil` to remove the image." }
- { name = "...", type = "number", desc = "Optional texture coordinates: either 4 (`left, right, top, bottom`) or 8 values. Any other count falls back to the full texture." }
---
Sets an optional image displayed alongside the text. When set, the image appears on the left if there is at least 200px of room for the text; otherwise it is centered on top. Passing a nil or invalid texture hides the image.
````
````apimethod
name: widget:SetImageSize
params:
- { name = "width", type = "number", desc = "Image width in pixels." }
- { name = "height", type = "number", desc = "Image height in pixels." }
---
Sets the displayed size of the image and re-lays out the widget.
````
````apimethod
name: widget:SetFont
params:
- { name = "font", type = "string", desc = "Font file path." }
- { name = "height", type = "number", desc = "Font height in pixels." }
- { name = "flags", type = "string", desc = "Font flags string (e.g. `\"OUTLINE\"`)." }
---
Sets the label font using an internal, lazily-created font object.
````
````apimethod
name: widget:SetFontObject
params:
- { name = "font", type = "table", optional = true, desc = "A font object, or `nil` for the default ([`GameFontHighlightSmall`](https://warcraft.wiki.gg/wiki/Widget_API))." }
---
Sets the label's font from an existing font object. Defaults to [`GameFontHighlightSmall`](https://warcraft.wiki.gg/wiki/Widget_API) when `nil`.
````
````apimethod
name: widget:SetJustifyH
params:
- { name = "justifyH", type = "string", desc = "`\"LEFT\"`, `\"CENTER\"`, or `\"RIGHT\"`." }
---
Sets horizontal text justification.
````
````apimethod
name: widget:SetJustifyV
params:
- { name = "justifyV", type = "string", desc = "`\"TOP\"`, `\"MIDDLE\"`, or `\"BOTTOM\"`." }
---
Sets vertical text justification.
````
````apimethod
name: widget:OnWidthSet
params:
- { name = "width", type = "number", desc = "The new width." }
---
Layout hook called by AceGUI when the width changes; re-anchors the text and image. Not normally called directly.
````
## Defaults
On acquire the label resets to: width 200, empty text, no image, image size 16×16, white color, default font object,
horizontal justify `LEFT`, and vertical justify `TOP`. Height is always derived from the text and image.
## Callbacks
This widget fires no widget-specific callbacks.
## Example
```lua
local label = AceGUI:Create("Label")
label:SetText("Status: ready")
label:SetColor(0, 1, 0)
label:SetImage("Interface\\Icons\\INV_Misc_QuestionMark")
label:SetImageSize(20, 20)
```
---
# MultiLineEditBox
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/multilineeditbox
# MultiLineEditBox
A scrollable, multi-line text input with an optional label and an `"Accept"` button. Supports inserting chat links and
dragging spells/items into the box.
Create with `AceGUI:Create("MultiLineEditBox")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `MultiLineEditBox`
## Methods
````apimethod
name: widget:SetText
params:
- { name = "text", type = "string", optional = true, desc = "The text to place in the box." }
---
Sets the contents of the edit box. Setting text programmatically clears the highlight, resets the cursor, and disables the Accept button.
````
````apimethod
name: widget:GetText
returns: { type = "string", desc = "The current contents of the edit box." }
---
Returns the current contents of the edit box.
````
````apimethod
name: widget:SetLabel
params:
- { name = "text", type = "string", optional = true, desc = "The label text, or `\"\"`/`nil` to hide it." }
---
Sets the label shown above the box. A non-empty label is shown (reserving 10px of header height); an empty/`nil` label is hidden. Triggers a re-layout.
````
````apimethod
name: widget:SetNumLines
params:
- { name = "value", type = "number", default = "4", desc = "Number of visible lines; values below 4 are clamped to 4." }
---
Sets the visible height of the box in lines (minimum 4). Triggers a re-layout.
````
````apimethod
name: widget:SetMaxLetters
params:
- { name = "num", type = "number", default = "0", desc = "Maximum character count; `0` (the default) means no limit." }
---
Limits the number of characters the box accepts.
````
````apimethod
name: widget:DisableButton
params:
- { name = "disabled", type = "boolean", desc = "`true` hides the button, `false` shows it." }
---
Shows or hides the Accept button. Triggers a re-layout (the box is taller when the button is hidden).
````
````apimethod
name: widget:SetFocus
---
Gives keyboard focus to the edit box. If the frame is not yet shown, focus is applied on its next [`OnShow`](https://warcraft.wiki.gg/wiki/UIHANDLER_OnShow).
````
````apimethod
name: widget:ClearFocus
---
Removes keyboard focus from the edit box and cancels any pending focus-on-show.
````
````apimethod
name: widget:HighlightText
params:
- { name = "from", type = "number", desc = "Start character index." }
- { name = "to", type = "number", desc = "End character index." }
---
Highlights a range of characters in the edit box.
````
````apimethod
name: widget:GetCursorPosition
returns: { type = "number", desc = "The current cursor position in the edit box." }
---
Returns the current cursor position in the edit box.
````
````apimethod
name: widget:SetCursorPosition
params:
- { name = "...", type = "number", desc = "Arguments forwarded to the edit box's `SetCursorPosition` (the cursor index)." }
---
Sets the cursor position in the edit box.
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the editbox. When disabled it drops focus, ignores the mouse, greys the text and label, and disables the accept button.
````
## Defaults
On acquire the widget resets to: empty text, not disabled, width 200, Accept button shown, 4 visible lines, not "
entered", and no character limit. On release it clears focus.
## Callbacks
````apimethod
name: OnEnterPressed
kind: callback
params:
- { name = "text", type = "string", desc = "The full box contents." }
---
Fired when the Accept button is clicked (focus is cleared first). If no handler returns a truthy value, the Accept button is disabled afterward. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnTextChanged
kind: callback
params:
- { name = "text", type = "string", desc = "The current contents." }
---
Fired on user input (not programmatic [`SetText`](#settext)); also enables the Accept button. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEditFocusGained
kind: callback
---
Fired when the edit box gains keyboard focus. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEditFocusLost
kind: callback
---
Fired when the edit box loses keyboard focus. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the edit box or scroll area (once, until it leaves). Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the edit box or scroll area. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local edit = AceGUI:Create("MultiLineEditBox")
edit:SetLabel("Notes")
edit:SetNumLines(8)
edit:SetText("Type your notes here...")
edit:SetCallback("OnEnterPressed", function(widget, event, text)
print("Saved:", text)
end)
```
---
# Slider
URL: https://wowace-docs.nickdnk.workers.dev/acegui/widgets/slider
# Slider
A graphical horizontal slider for selecting a numeric value within a range, with an editable value box and low/high
range labels.
Create with `AceGUI:Create("Slider")`. It inherits the [Common Widget API](/acegui/widget-api).
**Widget type:** `Slider`
## Methods
````apimethod
name: widget:SetValue
params:
- { name = "value", type = "number", desc = "The number to set as the current value (does not fire [`OnValueChanged`](#onvaluechanged))." }
---
Sets the current value of the slider, moving the thumb and updating the value editbox. This sets the value directly and does not fire [`OnValueChanged`](#onvaluechanged).
````
````apimethod
name: widget:GetValue
returns: { type = "number", desc = "The slider's current value." }
---
Returns the slider's current value.
````
````apimethod
name: widget:SetSliderValues
params:
- { name = "min", type = "number", default = "0", desc = "Minimum value." }
- { name = "max", type = "number", default = "100", desc = "Maximum value." }
- { name = "step", type = "number", default = "1", desc = "Increment between selectable values. When `> 0`, values chosen by dragging are snapped to the nearest step." }
---
Configures the slider's range and step increment, updates the low/high range labels, and re-applies the current value to the new range.
````
````apimethod
name: widget:SetLabel
params:
- { name = "text", type = "string", optional = true, desc = "The label text." }
---
Sets the descriptive label shown above the slider.
````
````apimethod
name: widget:SetIsPercent
params:
- { name = "value", type = "boolean", optional = true, desc = "Truthy to display as a percentage, `nil`/`false` for a plain number." }
---
Toggles percent display mode. When enabled, the value box and range labels are formatted as percentages (the stored value is multiplied by 100 for display and divided by 100 when typed).
````
````apimethod
name: widget:SetDisabled
params:
- { name = "disabled", type = "boolean", desc = "`true` to disable, `false` to enable." }
---
Enables or disables the slider. When disabled, the slider and value editbox stop accepting mouse input and are greyed out.
````
## Defaults
On acquire the slider resets to: width 200, height 44, not disabled, percent mode off, range `0`–`100` with step `1`,
value `0`, and mouse wheel scrolling disabled (it is enabled once the frame is clicked).
## Callbacks
````apimethod
name: OnValueChanged
kind: callback
params:
- { name = "value", type = "number", desc = "The new value, after step snapping." }
---
Fired when the value changes via dragging or the mouse wheel (after step snapping), provided the new value differs from the current one and the widget is not disabled. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnMouseUp
kind: callback
params:
- { name = "value", type = "number", desc = "The committed value." }
---
Fired when the user releases the mouse on the slider, and also when a value is committed by pressing Enter in the value editbox. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnEnter
kind: callback
---
Fired when the mouse enters the slider. Subscribe with `widget:SetCallback`.
````
````apimethod
name: OnLeave
kind: callback
---
Fired when the mouse leaves the slider. Subscribe with `widget:SetCallback`.
````
## Example
```lua
local slider = AceGUI:Create("Slider")
slider:SetLabel("Opacity")
slider:SetSliderValues(0, 1, 0.05)
slider:SetIsPercent(true)
slider:SetValue(0.75)
slider:SetCallback("OnValueChanged", function(widget, event, value)
print("Opacity set to", value)
end)
```
---
# Frame
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/frame
# Frame
A movable, resizable top-level window with a title bar, a status bar, and a Close button.
Create with `AceGUI:Create("Frame")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api) (`AddChild`, `SetLayout`, `ReleaseChildren`, etc.).
**Widget type:** `Frame`
## Methods
````apimethod
name: container:SetTitle
params:
- { name = "title", type = "string", desc = "The title string. Passing `nil`/no argument clears it." }
---
Set the text shown in the frame's title bar. The title-bar background texture is resized to fit the text (text width + 10).
````
````apimethod
name: container:SetStatusText
params:
- { name = "text", type = "string", desc = "The status string. Passing `nil`/no argument clears it." }
---
Set the text shown in the status bar along the bottom-left of the frame.
````
````apimethod
name: container:SetStatusTable
params:
- { name = "status", type = "table", desc = "An external table (asserted to be of type `table`) used to store and restore position and size." }
---
Supply an external table in which the frame stores and restores its position and size (`width`, `height`, `top`, `left`). When set, the frame immediately applies any values present in the table. Use this to persist window geometry between sessions.
````
````apimethod
name: container:ApplyStatus
---
Apply the current status table (external, or the internal `localstatus`) to the frame: sets its width (default `700`) and height (default `500`) and positions it. If `top` and `left` are present it anchors to those coordinates, otherwise it centers the frame.
````
````apimethod
name: container:EnableResize
params:
- { name = "state", type = "boolean", desc = "Truthy shows the resize grips; falsy hides them." }
---
Show or hide the three resize grips (bottom-right, bottom, right edges), enabling or disabling user resizing.
````
````apimethod
name: container:Show
---
Show the underlying frame.
````
````apimethod
name: container:Hide
---
Hide the underlying frame. (Hiding fires [`OnClose`](#onclose); see Callbacks.)
````
## Callbacks
````apimethod
name: OnShow
kind: callback
---
Fired when the frame is shown.
````
````apimethod
name: OnClose
kind: callback
---
Fired when the frame is hidden, including when the user clicks the built-in Close button, which calls [`Hide()`](#hide).
````
````apimethod
name: OnEnterStatusBar
kind: callback
---
Fired when the mouse enters the status-bar region.
````
````apimethod
name: OnLeaveStatusBar
kind: callback
---
Fired when the mouse leaves the status-bar region.
````
## Layout notes
Like all containers, the frame defaults to the `"List"` layout; switch with `SetLayout` (commonly `"Flow"`). The content
region is inset from the frame edges (34 px horizontally, 57 px vertically) to leave room for the title bar, status bar,
and Close button. The frame is movable by dragging the title bar and resizable via the grips; minimum size is 400×200.
## Example
```lua
local frame = AceGUI:Create("Frame")
frame:SetTitle("My Addon")
frame:SetStatusText("Ready")
frame:SetLayout("Flow")
frame:SetCallback("OnClose", function(widget) AceGUI:Release(widget) end)
local label = AceGUI:Create("Label")
label:SetText("Hello from a Frame container!")
label:SetFullWidth(true)
frame:AddChild(label)
```
---
# Window
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/window
# Window
A movable, resizable top-level window with a title bar and a Close button; a lighter-weight alternative to `Frame`,
without a status bar.
Create with `AceGUI:Create("Window")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api) (`AddChild`, `SetLayout`, `ReleaseChildren`, etc.).
**Widget type:** `Window`
## Methods
````apimethod
name: container:SetTitle
params:
- { name = "title", type = "string", desc = "The title string." }
---
Set the text shown in the window's title bar.
````
````apimethod
name: container:SetStatusText
params:
- { name = "text", type = "string", desc = "Ignored." }
---
No-op. Window has no status bar; the method exists for API compatibility with `Frame` but does nothing (the body is commented out in source).
````
````apimethod
name: container:SetStatusTable
params:
- { name = "status", type = "table", desc = "An external table (asserted to be of type `table`) used to store and restore position and size." }
---
Supply an external table in which the window stores and restores its position and size (`width`, `height`, `top`, `left`). Applies the table immediately. Use this to persist window geometry between sessions.
````
````apimethod
name: container:ApplyStatus
---
Apply the current status table (external, or the internal `localstatus`): sets width (default `700`) and height (default `500`) and positions the window. If `top` and `left` are present it anchors to those coordinates, otherwise it centers the window.
````
````apimethod
name: container:EnableResize
params:
- { name = "state", type = "boolean", desc = "Truthy shows the resize grips; falsy hides them." }
---
Show or hide the three resize grips (bottom-right, bottom, right edges), enabling or disabling user resizing.
````
````apimethod
name: container:Show
---
Show the underlying frame.
````
````apimethod
name: container:Hide
---
Hide the underlying frame. (Hiding fires [`OnClose`](#onclose); see Callbacks.)
````
## Callbacks
````apimethod
name: OnShow
kind: callback
---
Fired when the window is shown.
````
````apimethod
name: OnClose
kind: callback
---
Fired when the window is hidden, including when the user clicks the built-in Close button, which calls [`Hide()`](#hide).
````
## Layout notes
Like all containers, the window defaults to the `"List"` layout; switch with `SetLayout` (commonly `"Flow"`). The
content region is inset from the window edges (34 px horizontally, 57 px vertically). The window is movable by dragging
the title bar and resizable via the grips; minimum size is 240×240, default size 700×500.
## Example
```lua
local window = AceGUI:Create("Window")
window:SetTitle("My Window")
window:SetLayout("List")
window:SetCallback("OnClose", function(widget) AceGUI:Release(widget) end)
local label = AceGUI:Create("Label")
label:SetText("Content inside a Window container.")
label:SetFullWidth(true)
window:AddChild(label)
```
---
# SimpleGroup
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/simplegroup
# SimpleGroup
A plain container that just groups widgets, with no decoration of its own.
Create with `AceGUI:Create("SimpleGroup")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api) (`AddChild`, `SetLayout`, `ReleaseChildren`, etc.).
**Widget type:** `SimpleGroup`
## Methods
SimpleGroup adds no methods of its own; use the common container methods.
The content region fills the group's frame exactly (no insets, no border, no title). On acquire, the group defaults to
300×100. When its layout finishes, the group automatically sizes its height to match the content height unless
`self.noAutoHeight` is set to a truthy value.
## Callbacks
This container fires no callbacks of its own.
## Layout notes
Like all containers, the group defaults to the `"List"` layout; switch with `SetLayout` (commonly `"Flow"`). Because the
content region exactly matches the frame, SimpleGroup is the lightest way to nest a sub-layout inside another container.
Height automatically grows to fit content unless `noAutoHeight` is set.
## Example
```lua
local group = AceGUI:Create("SimpleGroup")
group:SetFullWidth(true)
group:SetLayout("Flow")
local label = AceGUI:Create("Label")
label:SetText("Grouped content")
label:SetFullWidth(true)
group:AddChild(label)
```
---
# InlineGroup
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/inlinegroup
# InlineGroup
A container that draws a visible box with an optional title around its children.
Create with `AceGUI:Create("InlineGroup")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api) (`AddChild`, `SetLayout`, `ReleaseChildren`, etc.).
**Widget type:** `InlineGroup`
## Methods
````apimethod
name: container:SetTitle
params:
- { name = "title", type = "string", desc = "The title string." }
---
Set the caption text shown above the box's border. On acquire the title is set to an empty string.
````
The group draws a bordered, shaded "box" (a `PaneBackdrop`) with the title rendered above it. On acquire, it defaults to
300×100. The content region is inset 10 px on each side within the border; the border itself is offset to leave 17 px at
the top for the title. When its layout finishes, the group automatically sizes its height to the content height plus 40
px (to account for the title and border) unless `self.noAutoHeight` is set to a truthy value.
## Callbacks
This container fires no callbacks of its own.
## Layout notes
Like all containers, the group defaults to the `"List"` layout; switch with `SetLayout` (commonly `"Flow"`). Use
InlineGroup when you want a labeled, visually-bounded section inside a larger container. Height automatically grows to
fit content (+40 px) unless `noAutoHeight` is set.
## Example
```lua
local group = AceGUI:Create("InlineGroup")
group:SetTitle("Options")
group:SetFullWidth(true)
group:SetLayout("Flow")
local check = AceGUI:Create("CheckBox")
check:SetLabel("Enable feature")
group:AddChild(check)
```
---
# ScrollFrame
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/scrollframe
# ScrollFrame
A container that scrolls its content vertically and does not grow in height.
Create with `AceGUI:Create("ScrollFrame")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api) (`AddChild`, `SetLayout`, `ReleaseChildren`, etc.).
**Widget type:** `ScrollFrame`
## Methods
````apimethod
name: container:SetScroll
params:
- { name = "value", type = "number", desc = "Scroll position from `0` (top) to `1000` (bottom)." }
---
Scroll the content to a position. `value` runs from `0` (top) to `1000` (bottom); the method converts it to a pixel offset based on the difference between content height and visible height. If the content fits entirely, the offset is forced to `0`. Stores `offset` and `scrollvalue` in the status table.
````
````apimethod
name: container:MoveScroll
params:
- { name = "value", type = "number", desc = "Mouse-wheel delta; sign determines scroll direction." }
---
Scroll incrementally, as triggered by the mouse wheel. Only acts when the scroll bar is shown. The sign of `value` chooses direction; the step is scaled relative to the overflow amount and clamped to the `0`–`1000` range.
````
````apimethod
name: container:FixScroll
---
Recompute whether the scroll bar is needed and synchronize all components. If the content fits (within a 2 px margin), it hides the scroll bar, restores the content width, and re-lays out; otherwise, it shows the scroll bar, reserves 20 px of width for it, re-lays out, and updates the bar value to match the current offset. Guarded by an internal `updateLock` to prevent re-entrancy. Called automatically on size changes and after layout.
````
````apimethod
name: container:SetStatusTable
params:
- { name = "status", type = "table", desc = "An external table (asserted to be of type `table`) in which the scroll state is stored (`scrollvalue`, `offset`)." }
---
Supply an external table in which the scroll state is stored (`scrollvalue`, `offset`). Initializes `scrollvalue` to `0` if absent. Use this to persist scroll position.
````
## Callbacks
This container fires no callbacks of its own.
## Layout notes
Like all containers, the ScrollFrame defaults to the `"List"` layout; switch with `SetLayout` (commonly `"Flow"`).
Unlike auto-growing groups, ScrollFrame keeps a fixed visible size and scrolls its content vertically; the content
height comes from the layout (`LayoutFinished`) while the frame's own height remains unchanged. A vertical scroll bar
appears only when content overflows, automatically reserving 20 px of width when shown. Mouse-wheel scrolling is
enabled. Give the ScrollFrame a fixed or full height (for example, via a parent layout) so there is a defined viewport
to scroll within.
## Example
```lua
local scroll = AceGUI:Create("ScrollFrame")
scroll:SetFullWidth(true)
scroll:SetFullHeight(true)
scroll:SetLayout("List")
for i = 1, 50 do
local label = AceGUI:Create("Label")
label:SetText("Row " .. i)
label:SetFullWidth(true)
scroll:AddChild(label)
end
```
---
# TabGroup
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/tabgroup
# TabGroup
A container that switches between groups of widgets using tabs along the top.
Create with `AceGUI:Create("TabGroup")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api).
**Widget type:** `TabGroup`
## Methods
````apimethod
name: container:SetTabs
params:
- { name = "tabs", type = "table", desc = "Array of tab descriptor tables. Each entry recognizes `value` (the value passed to [`SelectTab`](#selecttab) / reported by [`OnGroupSelected`](#ongroupselected) when this tab is clicked, required to identify the tab), `text` (the label shown on the tab), and `disabled` (if truthy, the tab is drawn greyed out and cannot be clicked)." }
---
Set the list of tabs to display along the top and rebuild the tab strip. Each call replaces the previous tab list.
````
````apimethod
name: container:SelectTab
params:
- { name = "value", type = "string", desc = "The `value` of the tab to select." }
---
Mark the tab whose `value` matches as selected (and deselect all others). If a matching tab is found, fires [`OnGroupSelected`](#ongroupselected) with that value. The handler is responsible for releasing the previous children and adding the new group's widgets.
````
````apimethod
name: container:SetTitle
params:
- { name = "text", type = "string", desc = "Title string, or `nil`/`\"\"` for none." }
---
Set the title text drawn above the tab strip. Passing `nil` or `""` clears it and tightens the layout. Rebuilds the tabs.
````
````apimethod
name: container:SetStatusTable
params:
- { name = "status", type = "table", desc = "A table you own and keep alive (asserted to be of type `table`)." }
---
Supply an external table in which the container stores its state (currently the `selected` tab value). Use this to persist the selected tab across acquire/release.
````
````apimethod
name: container:BuildTabs
---
Recompute the tab strip layout (sizes, rows, anchoring). Called internally by [`SetTabs`](#settabs)/[`SetTitle`](#settitle)/resize; rarely needs to be called directly.
````
> The container also defines `CreateTab`, `OnWidthSet`, `OnHeightSet`, and `LayoutFinished` as internal layout helpers.
## Callbacks
````apimethod
name: OnGroupSelected
kind: callback
params:
- { name = "value", type = "string", desc = "The selected tab's `value`." }
---
Fired by [`SelectTab`](#selecttab) (including the tab's own click handler) when a tab matching the given value is selected.
````
````apimethod
name: OnTabEnter
kind: callback
params:
- { name = "value", type = "string", desc = "The tab's value." }
- { name = "tabFrame", type = "Button", desc = "The underlying tab Button." }
---
Fired when the mouse enters a tab button.
````
````apimethod
name: OnTabLeave
kind: callback
params:
- { name = "value", type = "string", desc = "The tab's value." }
- { name = "tabFrame", type = "Button", desc = "The underlying tab Button." }
---
Fired when the mouse leaves a tab button.
````
## Example
```lua
local AceGUI = LibStub("AceGUI-3.0")
local tab = AceGUI:Create("TabGroup")
tab:SetTitle("Settings")
tab:SetLayout("Flow")
tab:SetFullWidth(true)
tab:SetTabs({
{ value = "general", text = "General" },
{ value = "audio", text = "Audio" },
{ value = "about", text = "About", disabled = true },
})
tab:SetCallback("OnGroupSelected", function(container, event, group)
container:ReleaseChildren()
if group == "general" then
local cb = AceGUI:Create("CheckBox")
cb:SetLabel("Enable addon")
container:AddChild(cb)
elseif group == "audio" then
local lbl = AceGUI:Create("Label")
lbl:SetText("Audio options go here")
container:AddChild(lbl)
end
end)
-- select an initial tab (this fires OnGroupSelected)
tab:SelectTab("general")
```
---
# TreeGroup
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/treegroup
# TreeGroup
A container that switches between groups of widgets using a tree control.
Create with `AceGUI:Create("TreeGroup")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api).
**Widget type:** `TreeGroup`
## Methods
````apimethod
name: container:SetTree
params:
- { name = "tree", type = "table", desc = "Array of node tables (may contain nested `children`). Asserted to be a table when non-nil. See [Tree node format](#tree-node-format)." }
- { name = "filter", type = "boolean", optional = true, desc = "When truthy, branches and leaves whose `visible` is `false` are hidden, and branches are only shown if they contain at least one visible descendant." }
---
Set the tree to display and refresh it. See [Tree node format](#tree-node-format) for the structure of `tree`.
````
````apimethod
name: container:SelectByPath
params:
- { name = "...", type = "string", desc = "The sequence of node `value`s from the top level to the target node (e.g. `\"parentValue\", \"childValue\"`)." }
---
Select a node by its path of `value`s from the root down, expanding every ancestor group along the way and scrolling the selection into view. Fires [`OnGroupSelected`](#ongroupselected).
````
````apimethod
name: container:SelectByValue
params:
- { name = "uniquevalue", type = "string", desc = "The unique value string, e.g. `\"parentValue\\001childValue\"`." }
---
Select a node by its full unique value (the path components joined by `\001`). Splits on `\001` to derive the path, expands ancestors, scrolls into view, and fires [`OnGroupSelected`](#ongroupselected).
````
````apimethod
name: container:Select
params:
- { name = "uniquevalue", type = "string", desc = "The unique value to mark as selected." }
- { name = "...", type = "string", desc = "The path components used to expand ancestor groups." }
---
Lower-level selection method used by [`SelectByPath`](#selectbypath)/[`SelectByValue`](#selectbyvalue). Disables filtering, expands every group along the path, sets the selection, refreshes (scrolling to the selection), and fires [`OnGroupSelected`](#ongroupselected).
````
````apimethod
name: container:SetSelected
params:
- { name = "value", type = "string", desc = "The unique value of the node to select." }
---
Set the selected node to `value` (the node's unique value). Only fires [`OnGroupSelected`](#ongroupselected) if the selection actually changed. Does not expand ancestors or scroll.
````
````apimethod
name: container:SetStatusTable
params:
- { name = "status", type = "table", desc = "A table you own and keep alive (asserted to be of type `table`)." }
---
Supply an external table for persisting tree state. The container stores/reads `groups` (expanded-state map keyed by unique value), `scrollvalue`, `treewidth`, `treesizable`, and `selected`. Missing keys are initialized. After setting, applies the stored tree width and refreshes.
````
````apimethod
name: container:SetTreeWidth
params:
- { name = "treewidth", type = "number|boolean", optional = true, desc = "Width in pixels (default 175), or a boolean to set only `resizable`." }
- { name = "resizable", type = "boolean", optional = true, desc = "When true, the drag handle is enabled." }
---
Set the width of the tree pane and whether the user may drag-resize it. `treewidth` may be omitted or boolean: if a boolean is passed as the first argument, it is treated as `resizable` and the width defaults to 175. Stores the values in the status table.
````
````apimethod
name: container:GetTreeWidth
returns: { type = "number", desc = "The current tree-pane width (defaults to 175 if unset)." }
---
Returns the current tree-pane width (defaults to 175 if unset).
````
````apimethod
name: container:EnableButtonTooltips
params:
- { name = "enable", type = "boolean", desc = "Whether the built-in hover tooltip is shown." }
---
Enable or disable the built-in tooltip shown when hovering over a tree button (the tooltip text is the button label). Enabled by default on acquire.
````
````apimethod
name: container:RefreshTree
params:
- { name = "scrollToSelection", type = "boolean", optional = true, desc = "Pass `true` to scroll the selected node into view." }
- { name = "fromOnUpdate", type = "boolean", optional = true, desc = "Internal flag set when called from the first-frame OnUpdate handler." }
---
Rebuild the visible button list from the current tree and status tables. Called automatically after most mutations; call directly if you mutate the tree table in place.
````
> The container also defines `CreateButton`, `BuildLevel`, and `ShowScroll` as internal helpers, plus `OnWidthSet`/
`OnHeightSet`/`LayoutFinished` for layout.
## Callbacks
````apimethod
name: OnGroupSelected
kind: callback
params:
- { name = "uniquevalue", type = "string", desc = "The selected node's unique value (path components joined by `\\001`)." }
---
Fired when the selected node changes (via [`SetSelected`](#setselected), [`Select`](#select), [`SelectByPath`](#selectbypath), [`SelectByValue`](#selectbyvalue), or clicking a button). Release and rebuild the content here.
````
````apimethod
name: OnClick
kind: callback
params:
- { name = "uniquevalue", type = "string", desc = "The clicked node's unique value." }
- { name = "selected", type = "boolean", desc = "The button's selected state at click time." }
---
Fired when a tree button is clicked, before selection is applied.
````
````apimethod
name: OnButtonEnter
kind: callback
params:
- { name = "uniquevalue", type = "string", desc = "The node's unique value." }
- { name = "buttonFrame", type = "Button", desc = "The underlying tree button." }
---
Fired when the mouse enters a tree button.
````
````apimethod
name: OnButtonLeave
kind: callback
params:
- { name = "uniquevalue", type = "string", desc = "The node's unique value." }
- { name = "buttonFrame", type = "Button", desc = "The underlying tree button." }
---
Fired when the mouse leaves a tree button.
````
````apimethod
name: OnTreeResize
kind: callback
params:
- { name = "width", type = "number", desc = "The new tree width in pixels." }
---
Fired after the user finishes drag-resizing the tree pane.
````
## Tree node format
[`SetTree`](#settree) takes an array of node tables. Each node recognizes the following fields (read from the source
`addLine`/`UpdateButton`):
- `value`: the node's identifier within its level. The full path of `value`s (joined by `\001`) forms the node's *
*unique value**, which is what [`OnGroupSelected`](#ongroupselected)/[`OnClick`](#onclick) report and what
[`SelectByValue`](#selectbyvalue) expects. Sibling node values must be unique within their parent.
- `text`: the label shown for the node.
- `icon`: optional texture (path or file ID) drawn left of the text.
- `iconCoords`: optional table of texture coordinates `{left, right, top, bottom}` (passed to
[`SetTexCoord`](https://warcraft.wiki.gg/wiki/API_Texture_SetTexCoord)).
- `disabled`: if truthy, the node is greyed out and not mouse-interactive.
- `children`: optional array of child node tables. A node with `children` is a collapsible branch whose expanded state
is tracked per unique value in the status table.
- `visible`: optional boolean. When the tree is set with a `filter`, nodes with `visible = false` are hidden (and empty
branches are pruned).
## Example
```lua
local AceGUI = LibStub("AceGUI-3.0")
local tree = AceGUI:Create("TreeGroup")
tree:SetFullWidth(true)
tree:SetFullHeight(true)
tree:SetLayout("Flow")
tree:SetTree({
{
value = "combat",
text = "Combat",
children = {
{ value = "melee", text = "Melee" },
{ value = "ranged", text = "Ranged" },
},
},
{
value = "ui",
text = "Interface",
icon = "Interface\\Icons\\INV_Misc_Gear_01",
children = {
{ value = "frames", text = "Frames" },
{ value = "fonts", text = "Fonts", disabled = true },
},
},
})
tree:SetCallback("OnGroupSelected", function(container, event, uniquevalue)
container:ReleaseChildren()
-- uniquevalue is e.g. "combat\001melee"
local lbl = AceGUI:Create("Label")
lbl:SetText("Selected: " .. uniquevalue)
container:AddChild(lbl)
end)
-- expand "combat" and select its "melee" child
tree:SelectByPath("combat", "melee")
```
---
# DropDownGroup
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/dropdowngroup
# DropdownGroup
A container that switches between groups of widgets using a dropdown at the top.
Create with `AceGUI:Create("DropdownGroup")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api).
**Widget type:** `DropdownGroup`
> Note: although this file is named `AceGUIContainer-DropDownGroup.lua`, the registered widget type is `DropdownGroup`
> (lowercase "down"). Use that exact string with `AceGUI:Create`.
## Methods
````apimethod
name: container:SetGroupList
params:
- { name = "list", type = "table", desc = "Table mapping each group's value to its display text (`[value] = text`)." }
- { name = "order", type = "table", optional = true, desc = "Array of values defining the display order of the entries." }
---
Populate the dropdown that selects between groups. The arguments are forwarded directly to the internal Dropdown's `SetList`.
````
````apimethod
name: container:SetGroup
params:
- { name = "group", type = "string", desc = "The value (key from `list`) of the group to select." }
---
Select a group programmatically by setting the dropdown value, recording it in the status table, and firing [`OnGroupSelected`](#ongroupselected).
````
````apimethod
name: container:SetTitle
params:
- { name = "title", type = "string", desc = "Title string, or `\"\"` for none." }
---
Set the title text. With a non-empty title, the dropdown is anchored to the top-right; with an empty title, it is anchored to the top-left.
````
````apimethod
name: container:SetDropdownWidth
params:
- { name = "width", type = "number", desc = "Width in pixels." }
---
Set the width of the dropdown selector (defaults to 200 pixels on acquire).
````
````apimethod
name: container:SetStatusTable
params:
- { name = "status", type = "table", desc = "A table you own and keep alive (asserted to be of type `table`)." }
---
Supply an external table for persisting state (the `selected` group value).
````
> The container also defines `OnWidthSet`, `OnHeightSet`, and `LayoutFinished` for layout.
## Callbacks
````apimethod
name: OnGroupSelected
kind: callback
params:
- { name = "value", type = "string", desc = "The selected group's value." }
---
Fired when a group is selected, either by the user via the dropdown or programmatically through [`SetGroup`](#setgroup). The handler should release and rebuild the content.
````
## Example
```lua
local AceGUI = LibStub("AceGUI-3.0")
local group = AceGUI:Create("DropdownGroup")
group:SetTitle("Profile")
group:SetFullWidth(true)
group:SetLayout("Flow")
group:SetGroupList(
{ default = "Default", raid = "Raid", pvp = "PvP" },
{ "default", "raid", "pvp" } -- explicit order
)
group:SetCallback("OnGroupSelected", function(container, event, key)
container:ReleaseChildren()
local lbl = AceGUI:Create("Label")
lbl:SetText("Editing profile: " .. key)
container:AddChild(lbl)
end)
-- select an initial group (this fires OnGroupSelected)
group:SetGroup("default")
```
---
# BlizOptionsGroup
URL: https://wowace-docs.nickdnk.workers.dev/acegui/containers/blizoptionsgroup
# BlizOptionsGroup
A container that embeds AceGUI options into the Blizzard Interface Options panel.
Create with `AceGUI:Create("BlizOptionsGroup")`. This is a **container**; it inherits
the [Common Widget API and container methods](/acegui/widget-api).
**Widget type:** `BlizOptionsGroup`
This container's frame is parented to the Blizzard Interface Options panel container and exposes the handlers Blizzard
expects, which fire the [`okay`](#okay)/[`cancel`](#cancel)/[`default`](#default)/[`refresh`](#refresh) callbacks below.
It is typically registered with
[`InterfaceOptions_AddCategory`](https://warcraft.wiki.gg/wiki/InterfaceOptions_AddCategory)
or `Settings.RegisterCanvasLayoutCategory` via its `frame`.
On the 10.0+ Settings API the panel's `OnCommit`/`OnDefault`/`OnRefresh` frame handlers are wired to the same `okay`/
`default`/`refresh` functions, so the callbacks you register fire on both old and new clients. You register the
callbacks below, never `OnCommit`/`OnDefault`/`OnRefresh` directly.
## Methods
````apimethod
name: container:SetName
params:
- { name = "name", type = "string", desc = "The category name shown in the options list." }
- { name = "parent", type = "string", optional = true, desc = "Parent category name (for nesting as a sub-panel)." }
---
Set the panel's name and (optional) parent category as used by the Blizzard options registration. These map onto `frame.name` and `frame.parent`.
````
````apimethod
name: container:SetTitle
params:
- { name = "title", type = "string", desc = "Heading string, or `nil`/`\"\"` for none." }
---
Set the large heading shown at the top of the panel. A non-empty title shifts the content area down to make room; an empty or nil title removes the heading and tightens the layout.
````
> The container also defines `OnWidthSet` and `OnHeightSet` for layout.
## Callbacks
````apimethod
name: OnShow
kind: callback
---
Fired when the panel's frame is shown (the user opens this options category).
````
````apimethod
name: OnHide
kind: callback
---
Fired when the panel's frame is hidden.
````
````apimethod
name: okay
kind: callback
---
Fired when Blizzard calls the panel's `okay` handler (settings accepted or Okay button clicked).
````
````apimethod
name: cancel
kind: callback
---
Fired when Blizzard calls the panel's `cancel` handler (changes discarded). Note: the `cancel` handler was removed in the version 10.0 settings system, so it may not fire on modern clients.
````
````apimethod
name: default
kind: callback
---
Fired when Blizzard calls the panel's `default` handler (restore defaults).
````
````apimethod
name: refresh
kind: callback
---
Fired when Blizzard calls the panel's `refresh` handler (the panel needs to re-read current values).
````
## Example
```lua
local AceGUI = LibStub("AceGUI-3.0")
local panel = AceGUI:Create("BlizOptionsGroup")
panel:SetName("My Addon")
panel:SetTitle("My Addon Options")
panel:SetLayout("Flow")
local cb = AceGUI:Create("CheckBox")
cb:SetLabel("Enable feature")
panel:AddChild(cb)
panel:SetCallback("refresh", function(container, event)
cb:SetValue(MyAddonDB.enabled)
end)
panel:SetCallback("okay", function(container, event)
-- settings accepted; persist if needed
end)
-- register the panel's frame with the Blizzard options UI
local category = Settings.RegisterCanvasLayoutCategory(panel.frame, "My Addon")
Settings.RegisterAddOnCategory(category)
```