File Details
48
- R
- May 13, 2026
- 15.22 MB
- 11
- 12.0.7+4
- Classic + 3
File Name
Cairn-48.zip
Supported Versions
- 12.0.7
- 12.0.5
- 5.5.3
- 2.5.5
- 1.15.8
Cairn
48 (2026-05-13)
Full Changelog Previous Releases
- release 48
Cairn-Gui-Widgets-Standard-2.0 MINOR 12 -> 15:- MINOR 13: TabGroup wraps to multi-row on overflow. Auto-grows
strip height + re-anchors content panes; OnSizeChanged repacks
rows live on window resize. - MINOR 14: TreeView widget. Generic expand/collapse hierarchical
list. Single-click toggles expansion + fires Click event. Frame
height auto-grows to fit visible rows. - MINOR 15: TreeView honors node.expandable=true so consumers can
mark a branch expandable without pre-building children, populating
on the Toggle event.
Cairn-Util-1.0 MINOR 32 -> 35: - MINOR 33: String.SafePreview(s, maxLen). pcall-wrapped preview;
returns nil on WoW "secret string" values so callers can render
a placeholder instead of tainting on :gsub. - MINOR 34: Table.SafeKeys(t, sortFn?). pcall-wrapped pairs() that
returns nil on tables protected from addon iteration. - MINOR 35: Table.SafeCount(t). Same protection, count only (no
array build).
All five Cairn TOC flavors registered the new TreeView.lua file.
First consumers: Forge_APIBrowser v2, Forge_Tables v2, Forge_CVars
v2 (in the Forge repo).
- MINOR 13: TabGroup wraps to multi-row on overflow. Auto-grows
- Cairn: safe-introspection helpers + TreeView lazy expansion
Cairn-Util-1.0 MINOR 32 -> 35:- String.SafePreview(s, maxLen): pcall-wrapped preview that returns
nil on WoW "secret string" values (locale entries, protected
globals) so callers can render a placeholder instead of tainting
on :gsub. - Table.SafeKeys(t, sortFn?): pcall-wrapped pairs() that returns
nil on tables protected from addon iteration (Blizzard internal
frames, secure containers). - Table.SafeCount(t): same protection, returns just the count
without allocating the key array.
All three pulled up from inline pcall code in Forge_Tables. The
hazards are general (any inspector tool walking unknown data hits
them); centralizing in Cairn-Util means Forge_Console, future API
introspectors, and anything else avoid re-rolling.
Cairn-Gui-Widgets-Standard-2.0 MINOR 14 -> 15: - TreeView honors node.expandable=true even when children is empty.
Consumer populates children on the Toggle event and calls Refresh,
so walking large trees becomes pay-as-you-go. Hit on Forge_Tables:
eagerly walking _G at depth 2 did 500k+ ops and froze the client.
Lazy expansion via this flag keeps initial build to root keys only.
Tested in-game on interface 120005 via Forge_Tables (separate Forge
commit).
- String.SafePreview(s, maxLen): pcall-wrapped preview that returns
- Cairn-Gui-Widgets-Standard-2.0 MINOR 14: TreeView widget
Generic expand/collapse hierarchical list. Consumer provides
{ id, label, aux, children } nodes; widget renders one row per
visible node with indent + indicator. Collapsed branches contribute
one row regardless of how many descendants they have, so the
widget naturally handles large data sets that overwhelm a flat
list (Forge_APIBrowser has ~3000+ entries).- Single-click toggles expansion on branches and fires "Click" with
the original node, so consumers can still do click-to-select.
"Toggle" event also fires on expand/collapse for programmatic
consumers. - Frame height auto-grows to fit visible rows; wrap in a ScrollFrame
for tall trees. Consumer hooks OnSizeChanged to push the tree
height into ScrollFrame:SetContentHeight. - SetNodes preserves expansion state by id, so consumers that filter
trees by rebuilding don't lose user-expanded branches across
filter changes (ids that survive the filter stay expanded). - Registered in all 5 TOCs (Cairn.toc + Mists/TBC/Vanilla/XPTR flavor
variants).
First consumer: Forge_APIBrowser v2 (separate Forge commit).
- Single-click toggles expansion on branches and fires "Click" with
- Cairn-Gui-Widgets-Standard-2.0 MINOR 13: TabGroup wraps to multi-row on overflow
Previously the tab strip extended past the TabGroup frame's right edge
when total tab width exceeded the strip width (visible on Forge with
18 sub-addons at default window width: "About" clipped past the Forge
window's right edge).- relayoutTabs tracks current x and wraps to a new row when the next
button won't fit. Skips the wrap when x == STRIP_PAD so a single
oversized button still renders (clipped) rather than wrapping
infinitely. - Strip auto-grows in height to fit all rows. Content panes re-anchor
to the new strip bottom via reanchorPanes() so tab content always
starts directly below the (possibly multi-row) strip. - HookScript("OnSizeChanged") on the TabGroup frame re-runs relayout
on resize, so widening the host window repacks tabs into fewer
rows live.
Header doc updated; "no tabs that scroll horizontally - deferred"
removed (multi-row wrap subsumes the use case).
Tested in-game on Forge with 18 tabs across two rows; resizing the
window repacked them as expected.
- relayoutTabs tracks current x and wraps to a new row when the next