Inter-addon frame anchoring system for World of Warcraft.
This library is typically bundled with addons that use it. No manual installation required.
- Copy the
LibAnchorRegistry-1.0folder into your addon'sLibsdirectory - Add to your TOC file:
Libs\LibAnchorRegistry-1.0\LibStub\LibStub.lua Libs\LibAnchorRegistry-1.0\LibAnchorRegistry-1.0.lua - Or use as external dependency in .pkgmeta
local Anchor = LibStub("LibAnchorRegistry-1.0")
-- Register your frame
Anchor:Register("MyAddon", myMainFrame, {
displayName = "My Addon",
category = "misc",
})
-- Anchor to another addon
Anchor:AnchorTo(myFrame, "OtherAddon", "TOP", "BOTTOM", 0, -5)- Simple Registration: Register frames with human-readable names
- Deferred Anchoring: Automatically waits for target frames to load
- Dual-Point Anchoring: Auto-size frames between two anchor points
- Group Layout: Automatically layout multiple frames in rows/columns
- Combat Safe: Queues operations during combat lockdown
- Event System: Subscribe to anchor changes (move, resize, show, hide)
- Fallback Support: Specify fallback anchors when primary target isn't available
local Anchor = LibStub("LibAnchorRegistry-1.0")
-- Register a frame
Anchor:Register("MyCooldownManager", myCDMFrame, {
displayName = "My Cooldown Manager",
category = "cooldowns",
description = "Main cooldown tracking bar",
})-- Simple one-liner
Anchor:AnchorTo(myFrame, "MyCooldownManager", "TOP", "BOTTOM", 0, -5)
-- With full config
Anchor:AnchorTo(myFrame, {
target = "MyCooldownManager",
point = "TOPLEFT",
relativePoint = "BOTTOMLEFT",
offsetX = 0,
offsetY = -10,
fallback = "UIParent",
fallbackPoint = "CENTER",
followVisibility = true,
})-- Health bar fills parent with 2px padding
Anchor:AnchorDual(healthBar, {
target = "MyUnitFrames.Player",
point = "TOPLEFT",
relativePoint = "TOPLEFT",
offsetX = 2,
offsetY = -2,
target2 = "MyUnitFrames.Player",
point2 = "BOTTOMRIGHT",
relativePoint2 = "BOTTOMRIGHT",
offsetX2 = -2,
offsetY2 = 2,
})
-- Shorthand
Anchor:Fill(healthBar, "MyUnitFrames.Player", 2)
-- With per-side padding
Anchor:FillWithPadding(healthBar, "MyUnitFrames.Player", {
left = 2,
right = 2,
top = 2,
bottom = 2,
})local partyFrames = { party1Frame, party2Frame, party3Frame, party4Frame }
local handle = Anchor:AnchorGroup(partyFrames, {
target = "MyCooldownManager",
point = "TOPLEFT",
relativePoint = "BOTTOMLEFT",
offsetY = -10,
direction = "DOWN",
spacing = 2,
wrap = 2, -- Wrap after 2 frames
wrapDirection = "RIGHT",
})
-- Later, party size changes
handle:SetFrames({ party1Frame, party2Frame })-- Watch specific anchor
local sub = Anchor:Subscribe("MyCooldownManager", function(name, event, frame, metadata)
if event == "MOVED" then
print("CDM moved!")
elseif event == "RESIZED" then
print("CDM resized!")
end
end)
-- Watch all anchors
local globalSub = Anchor:SubscribeAll(function(name, event, frame, metadata)
print(name .. " " .. event)
end)
-- Later
sub:Unsubscribe()
globalSub:Unsubscribe()-- Check if anchor exists
if Anchor:Exists("MyCooldownManager") then
-- Get frame and metadata
local frame, metadata = Anchor:Get("MyCooldownManager")
end
-- Get all anchors
local allAnchors = Anchor:GetAll()
-- Get by category
local cooldownAnchors = Anchor:GetByCategory("cooldowns")
-- Search
local results = Anchor:Search("cooldown")
-- Get dropdown data for config UI
local dropdownData = Anchor:GetDropdownData({
categories = { "cooldowns", "unitframes" },
persistent = true,
})Anchor:Register(name, frame, metadata)- Register a frame as an anchor targetAnchor:Unregister(name)- Remove a registered anchorAnchor:UpdateMetadata(name, metadata)- Update metadata for an existing anchor
Anchor:Get(name)- Get frame and metadata for an anchorAnchor:Exists(name)- Check if anchor existsAnchor:GetAll()- Get all registered anchorsAnchor:GetByCategory(category)- Get anchors by categoryAnchor:Search(query)- Search anchors by nameAnchor:GetDropdownData(options)- Get formatted data for dropdowns
Anchor:AnchorTo(frame, target, point, relativePoint, offsetX, offsetY)- Simple anchorAnchor:AnchorTo(frame, config)- Full config anchorAnchor:AnchorDual(frame, config)- Dual-point anchorAnchor:Fill(frame, target, inset)- Fill target with uniform insetAnchor:FillWithPadding(frame, target, padding)- Fill with per-side paddingAnchor:AnchorGroup(frames, config)- Group layout
handle:Update()- Force re-anchorhandle:Release()- Stop managing anchorhandle:SetOffset(x, y)- Update primary offsethandle:SetOffset2(x, y)- Update secondary offset (dual only)handle:GetTarget()- Get primary target framehandle:GetTarget2()- Get secondary target frame (dual only)handle:GetConfig()- Get current confighandle:IsActive()- Check if anchor is activehandle:IsPending()- Check if waiting for target
handle:SetFrames(frames)- Replace frame listhandle:AddFrame(frame)- Add frame to grouphandle:RemoveFrame(frame)- Remove frame from grouphandle:Refresh()- Recalculate layouthandle:GetFrames()- Get current frame list
Anchor:Subscribe(name, callback)- Subscribe to specific anchorAnchor:SubscribeAll(callback)- Subscribe to all anchors
Events: "REGISTERED", "UNREGISTERED", "MOVED", "RESIZED", "SHOWN", "HIDDEN"
Anchor:Debug()- Print debug informationAnchor:SetDebug(enabled)- Enable/disable debug warningsAnchor:GetVersion()- Get library version
Standard categories:
"unitframes"- Player, target, party, raid frames"cooldowns"- Cooldown tracking addons"bars"- Action bars, status bars"misc"- Everything else
- Single main frame:
"AddonName" - Multiple frames:
"AddonName.FrameType"or"AddonName.FrameType.Specific"
Examples:
"BetterCDM""BetterCDM.Bar1""YourUnitFrames.Player""Details.Window1"
GPL-2.0