> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lootroute.volvox.bot/llms.txt
> Use this file to discover all available pages before exploring further.

# GUI builder

> volvox.GuiBuilder — the declarative settings-page DSL built on StdUi.

`volvox.GuiBuilder` (defined in `Interface/GuiBuilder.lua`) builds settings pages declaratively on top of the bundled StdUi toolkit (`LibStub("volvoxStdUi")`).

Key behaviors:

* All element methods **return `self`** for chaining, and `error()` if no current category/tab is selected.
* Every **keyed widget auto-registers its config default** via `volvox.Config:SetDefault(key, default)` at declaration time, and auto-wires load (`Config:Read`) / save (`Config:Write`) at render time.
* All `text` / `tooltip` strings are localized via AceLocale when available.
* Non-header elements are packed **two per row**; headers break rows, span the full width, and act as **section dividers** with `Theme.spacing.sectionGap` extra room above them (except at the top of a page). Widgets that carry a TOP label (editbox, slider, doubleslider, dropdown) reserve `Theme.spacing.labelGap` headroom in their row. Tooltip attachment skips FontString labels because only frame widgets support `SetScript`.
* Each `:Tab()` becomes a **sidebar sub-page** in the settings window: the category's `createLayout()` returns a `{ multiPage = true, name, pages = { { name, layout } } }` descriptor, and `Interface/Default.lua` renders one indented sidebar entry per page under an uppercase group label. There is no nested tab strip. Deferred page-building callbacks capture their element definition per iteration, so each row renders and binds the widget declared for that row.

## Structure

```lua theme={null}
---@return table instance
GuiBuilder:New()

---@param name string
---@param order? number   -- default 100
---@return table self
GuiBuilder:Category(name, order)

---@param name string
---@return table self
GuiBuilder:Tab(name)
```

`Category()` begins a settings category and records it in `volvox.InterfaceCategoryRegistry` so it survives GUI resets. `Tab()` begins a new sub-page in the current category, rendered as an indented sidebar entry in the settings window.

## Example

```lua theme={null}
local gui = volvox.GuiBuilder:New()

gui:Category("MyFeature", 50)
  :Tab("General")
  :Header({ text = "Behavior" })
  :Checkbox({
    text = "Enable widget",
    key = "myfeature.enabled",
    default = false,
    tooltip = "Turns the widget on.",
    onChange = function(self, checked)
      volvox:LogInfo("Widget: " .. tostring(checked))
    end,
  })
  :Slider({
    text = "Threshold",
    key = "myfeature.threshold",
    min = 0, max = 100, step = 5, default = 25,
  })
  :Dropdown({
    text = "Mode",
    key = "myfeature.mode",
    options = {
      { text = "Fast", value = "fast" },
      { text = "Safe", value = "safe" },
    },
    default = "safe",
  })
```

## Widgets

Each widget takes a single `config` table:

| Method                  | Config fields                                                                                                                                | Notes                                                                                  |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `:Button(config)`       | `text`, `width?`, `height?`, `onClick?`                                                                                                      | Defaults: width 150, height 20                                                         |
| `:Checkbox(config)`     | `text`, `key?`, `default?`, `onChange?`, `tooltip?`                                                                                          | Keyed default: `false`. `onChange(self, checked)` fires after save                     |
| `:EditBox(config)`      | `text`, `key?`, `default?`, `width?`, `height?`, `onChange?`, `tooltip?`                                                                     | Keyed default: `""`. Saves on Enter or when focus leaves, then `onChange(self, value)` |
| `:Header(config)`       | `text`                                                                                                                                       | Full-width section header with themed underline                                        |
| `:Slider(config)`       | `text`, `min?`, `max?`, `step?`, `default?`, `key?`, `onChange?`, `tooltip?`                                                                 | Defaults: min 0, max 100, step 1, keyed default 0                                      |
| `:DoubleSlider(config)` | `text1`, `text2`, `min1?`, `max1?`, `min2?`, `max2?`, `step?`, `step1?`, `step2?`, `default1?`, `default2?`, `key?`, `onChange?`, `tooltip?` | Registers two defaults: `key .. ".value1"` and `key .. ".value2"`                      |
| `:Dropdown(config)`     | `text`, `key?`, `options`, `default?`, `onChange?`, `init?`, `multi?`, `width?`, `tooltip?`                                                  | `options` is an array of `{ text, value }`. Width default 200                          |
| `:ColorPicker(config)`  | `text`, `key?`, `default?`, `width?`, `height?`, `onChange?`, `tooltip?`                                                                     | Keyed default: `{ r = 1, g = 1, b = 1, a = 1 }`                                        |
| `:HalfLabel(config)`    | `text`                                                                                                                                       | Half-width label, packed two per row                                                   |
| `:Spacer()`             | —                                                                                                                                            | Empty half-width slot for layout spacing                                               |

## Category restoration

```lua theme={null}
GuiBuilder.RestoreInterfaceCategories()   -- dot call
```

Re-registers every category from `volvox.InterfaceCategoryRegistry` with the interface manager after a GUI reset.

## Color helpers

Also defined on `volvox` in this file:

| Function                                                | Purpose                                                |
| ------------------------------------------------------- | ------------------------------------------------------ |
| `volvox.CreateHeaderWithUnderline(frame, text, color?)` | Header label + 1px 50%-opacity underline container     |
| `volvox.ColorToDrawFormat(color)`                       | Convert WoW 0–1 color (`{r,g,b,a?}`) to 0–255 integers |
| `volvox.DrawFormatToColor(r, g, b, a?)`                 | Convert 0–255 channels back to 0–1                     |
