Files
benilla-octo/crates/benilla-app/assets/ui/UIPanelTemplates.xml
T
SamandClaude Fable 5 047dd3444e the wheel binds, one AddOns screen, text at the true scale
- SetBinding accepts the mouse wheel — the refusal was ours, not the client's — so wheel-bound action buttons press and release like the real thing
- one addon load law: a single arbiter for "can this addon load, and why not", with the out-of-date version gate live
- one AddOns screen — the character-select list, wearing the authored reference layout: roster dropdown, per-character tri-state checkboxes, force-load; the ESC-menu panel is retired, since 1.12's own menu has no AddOns row
- the glyph atlas follows the window scale, so maximised text stops washing out and a title stops measuring wider than it draws; an unpositioned frame positions nothing, instead of landing at the screen origin

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 19:31:56 +07:00

443 lines
27 KiB
XML

<Ui>
<!--
The reference's SHARED widget kit, in our own terms. Interface\FrameXML\UIPanelTemplates.xml
is the SPECIFICATION — the template names, the child names, the art, every offset and every
handler's observable effect are read off the extracted 1.12.1 file, and the line numbers
cited below are that file's. Nothing here is required to be *spelled* the way it spells it,
and the two Lua handlers are not.
WHY THIS FILE EXISTS AT ALL. Every window benilla has built so far declared its own private
copy of these — `BenillaQuestPanelButtonTemplate`, `BenillaTrainerPanelButtonTemplate`,
`BenillaMacroPanelButtonTemplate` and a dozen siblings, each the same four state textures on
the same UI-Panel-Button art. That was fine while the only consumer was our own XML. It
stopped being fine the day `CreateFrame`'s fourth argument started working (decision 1203):
an addon writes `CreateFrame("Button", "MyBtn", UIParent, "UIPanelButtonTemplate")` and
nothing else, and 185 of the corpus's 218 addons' template call sites name templates we had
never declared. These are those templates, under the reference's own names — the 1190 rule
(a name the shipped 1.12 UI defines is FrameXML's, and belongs in `assets/ui`) applied to
the ranked list `addon_harness` now prints.
Every name here is in `reference/1.12-globals.tsv`; none is invented.
NO DEVIATIONS — the state textures below are the reference's, `<NormalTexture
inherits="UIPanelButtonUpTexture"/>` and all. That is worth a note only because it was not
true when this file first landed: the loader expanded `inherits=` on `<Layers>` regions and
on nested `<Frames>` children but not on a Button's state-texture or a Slider's thumb, so a
faithful transcription produced buttons with no art AND NO ERROR. The first version carried
the resolved art inline as a workaround; both gaps are now fixed in
`loader/widgets.rs` (`apply_button`/`apply_slider` call `expand_region`, the same call a
`<Layers>` region gets) and the workaround is gone. Reverting either fix makes
`a_panel_button_from_the_template_labels_and_paints` and
`a_scroll_frame_from_the_template_wires_its_bar_two_parents_deep` fail.
NOT CARRIED, deliberately:
· `FauxScrollFrameTemplate` (ref l.213-225) — benilla already ships one under the reference's
own name in ScrollTemplates.xml, built as a plain `<Frame>` over `BenillaScrollBarTemplate`
(decisions 0247/0250/0251). Two declarations of one name would race; re-pointing ours at
the reference's `<ScrollFrame>` shape is its own job with its own risk, not this pass's.
· `TabButtonTemplate` (ref l.303-402) — already declared in UiPanels.xml, with its
fit/highlight deviations recorded there (decision 1004).
(`GameMenuButtonTemplate`, ref l.403-410, was on this list as "already in GameMenuFrame.xml"
until the colour picker needed it from above that file's LAST-in-the-toc seat. It is below
now, in the reference's own file for it, and GameMenuFrame.xml's private copy is gone.)
AND WHAT THIS SUPERSEDES BUT DOES NOT DELETE: `UIPanelButtonTemplate` below is the shared
original of `BenillaQuestPanelButtonTemplate`,
`BenillaCraftPanelButtonTemplate`, `BenillaQuestLogPanelButtonTemplate`,
`BenillaFriendsPanelButtonTemplate`, `BenillaTrainerPanelButtonTemplate`,
`BenillaMacroPanelButtonTemplate`, `BenillaTradeSkillPanelButtonTemplate` and
`BenillaDressUpPanelButtonTemplate` — eight copies of the same eight lines. Re-pointing those
windows at this template is a separate, mechanical pass; nothing here changes them.
-->
<Script><![CDATA[
-- The two scroll-frame handlers `UIPanelScrollFrameTemplate` below calls by name. Their
-- contract — the names, the arguments, and every branch's observable effect — is the
-- reference's (UIPanelTemplates.lua l.150-157 and l.254-305); the code is ours.
-- `ScrollFrame_OnLoad` and the whole `FauxScrollFrame_*` family already live in
-- ScrollTemplates.xml, which loads immediately before this file; these two are the
-- remainder of that kit.
-- One wheel notch pans by half a bar-height, up or down. The wheel is SOUNDLESS, unlike the
-- arrow buttons — the reference's own split, and the director's (trainer_tests.rs).
function ScrollFrameTemplate_OnMouseWheel(value)
local scrollBar = getglobal(this:GetName() .. "ScrollBar")
local step = scrollBar:GetHeight() / 2
if value > 0 then
step = -step
end
scrollBar:SetValue(scrollBar:GetValue() + step)
end
-- Reconcile a ScrollFrame's bar, arrows and thumb to a range the engine has just
-- recomputed. `scrollrange` is the engine's own second argument when this runs as the
-- handler; a caller who omits it gets the frame's current range instead.
--
-- All four children hang off the OWNER's name two `$parent` levels down
-- (`MyScrollScrollBarScrollUpButton`), so they are resolved ONCE here — the reference walks
-- back to getglobal at each of the ten points it touches one. `$parentThumbTexture` is what
-- publishes the last of them; that publication did not exist when this file was first
-- written (`apply_slider` applied a named thumb's layout and never set the global, the one
-- asymmetry with a Button's state textures), and the gap was fixed rather than routed
-- around.
function ScrollFrame_OnScrollRangeChanged(scrollrange)
local frame = this
local scrollbar = getglobal(frame:GetName() .. "ScrollBar")
local up = getglobal(scrollbar:GetName() .. "ScrollUpButton")
local down = getglobal(scrollbar:GetName() .. "ScrollDownButton")
local thumb = getglobal(scrollbar:GetName() .. "ThumbTexture")
scrollrange = scrollrange or frame:GetVerticalScrollRange()
local value = min(scrollbar:GetValue(), scrollrange)
scrollbar:SetMinMaxValues(0, scrollrange)
scrollbar:SetValue(value)
-- Nothing to scroll, and two ways of saying so — which one is the OWNER's call:
-- a hideable bar leaves altogether, a fixed one stays in place and greys out. On the
-- way back only the DOWN arrow wakes, because the offset is still zero and there is
-- nowhere up to go; the frame's own vertical-scroll handler below wakes the up arrow
-- the moment that stops being true.
local empty = floor(scrollrange) == 0
if not empty then
down:Show()
up:Show()
scrollbar:Show()
down:Enable()
elseif frame.scrollBarHideable then
scrollbar:Hide()
down:Hide()
up:Hide()
else
down:Disable()
up:Disable()
down:Show()
up:Show()
end
if empty then thumb:Hide() else thumb:Show() end
-- The frame's own border (ref l.285-304), if it declares one: all three regions are the
-- OWNER's to name, so all three are optional, and the pair is decided together because
-- a half-declared border is no border. Note this leg asks the FRAME for its range
-- rather than trusting the argument, and wants an exact zero where the bar above floors
-- first — two different questions, and the reference keeps them apart.
if frame.scrollBarHideable then
local bordered = frame:GetVerticalScrollRange() ~= 0
local top = getglobal(frame:GetName() .. "Top")
local bottom = getglobal(frame:GetName() .. "Bottom")
local middle = getglobal(frame:GetName() .. "Middle")
if top and bottom then
if bordered then top:Show() bottom:Show() else top:Hide() bottom:Hide() end
end
if middle then
if bordered then middle:Show() else middle:Hide() end
end
end
end
]]></Script>
<!-- The five shared panel-button faces (ref l.3-17). Declared under their own names because
they ARE 1.12 globals an addon's XML may inherit; the state textures below also carry the
resolved art inline, for the reason in the header. -->
<Texture name="UIPanelButtonUpTexture" file="Interface\Buttons\UI-Panel-Button-Up" virtual="true">
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
</Texture>
<Texture name="UIPanelButtonDownTexture" file="Interface\Buttons\UI-Panel-Button-Down" virtual="true">
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
</Texture>
<Texture name="UIPanelButtonDisabledTexture" file="Interface\Buttons\UI-Panel-Button-Disabled" virtual="true">
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
</Texture>
<Texture name="UIPanelButtonDisabledDownTexture" file="Interface\Buttons\UI-Panel-Button-Disabled-Down" virtual="true">
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
</Texture>
<Texture name="UIPanelButtonHighlightTexture" file="Interface\Buttons\UI-Panel-Button-Highlight" alphaMode="ADD" virtual="true">
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
</Texture>
<!-- ref l.18-27. THE panel button: 19 call sites across 3 corpus addons, and the shared
original of nine private copies in our own assets/ui. Note it declares no `<Size>` — an
instance sets its own, and a bare CreateFrame of it comes out 0x0 until the addon does. -->
<Button name="UIPanelButtonTemplate" virtual="true">
<ButtonText name="$parentText"/>
<NormalFont inherits="GameFontNormal"/>
<HighlightFont inherits="GameFontHighlight"/>
<DisabledFont inherits="GameFontDisable"/>
<NormalTexture inherits="UIPanelButtonUpTexture"/>
<PushedTexture inherits="UIPanelButtonDownTexture"/>
<DisabledTexture inherits="UIPanelButtonDisabledTexture"/>
<HighlightTexture inherits="UIPanelButtonHighlightTexture"/>
</Button>
<!-- ref l.403-410, verbatim. The ESC menu's button: a 144x21 UIPanelButtonTemplate whose label
trio is overridden to GameFontHighlight/GameFontHighlight/GameFontDisable — the menu's
labels are WHITE, not the gold a normal panel button wears. It lived in GameMenuFrame.xml
with its art inlined until ColorPickerFrame.xml needed it too (the reference's own colour
picker builds its Okay/Cancel from this template, and loads far ahead of the game menu,
which is deliberately LAST in the toc). Moving it here is where the reference has it. -->
<Button name="GameMenuButtonTemplate" inherits="UIPanelButtonTemplate" virtual="true">
<Size><AbsDimension x="144" y="21"/></Size>
<NormalFont inherits="GameFontHighlight"/>
<HighlightFont inherits="GameFontHighlight"/>
<DisabledFont inherits="GameFontDisable"/>
</Button>
<!-- ref l.28-81. The THREE-SLICE panel button: same art, cut 12/stretch/12 so it can be any
width without the end caps smearing, and its own OnMouseDown/OnMouseUp swap the three
slices to the Down sheet (there is no PushedTexture on this one — the layer regions ARE
the pressed state). The slices are `<Layers>` regions, so their `$parent` names publish
and the handlers' getglobal finds them. -->
<Button name="UIPanelButtonTemplate2" virtual="true">
<Size><AbsDimension x="40" y="22"/></Size>
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentLeft" file="Interface\Buttons\UI-Panel-Button-Up">
<Size><AbsDimension x="12" y="22"/></Size>
<Anchors><Anchor point="LEFT"/></Anchors>
<TexCoords left="0" right="0.09375" top="0" bottom="0.6875"/>
</Texture>
<Texture name="$parentRight" file="Interface\Buttons\UI-Panel-Button-Up">
<Size><AbsDimension x="12" y="22"/></Size>
<Anchors><Anchor point="RIGHT"/></Anchors>
<TexCoords left="0.53125" right="0.625" top="0" bottom="0.6875"/>
</Texture>
<Texture name="$parentMiddle" file="Interface\Buttons\UI-Panel-Button-Up">
<Size><AbsDimension x="12" y="22"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentLeft" relativePoint="RIGHT"/>
<Anchor point="RIGHT" relativeTo="$parentRight" relativePoint="LEFT"/>
</Anchors>
<TexCoords left="0.09375" right="0.53125" top="0" bottom="0.6875"/>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnMouseDown>
getglobal(this:GetName() .. "Left"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down")
getglobal(this:GetName() .. "Middle"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down")
getglobal(this:GetName() .. "Right"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Down")
</OnMouseDown>
<OnMouseUp>
getglobal(this:GetName() .. "Left"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up")
getglobal(this:GetName() .. "Middle"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up")
getglobal(this:GetName() .. "Right"):SetTexture("Interface\\Buttons\\UI-Panel-Button-Up")
</OnMouseUp>
</Scripts>
<ButtonText name="$parentText"/>
<NormalFont inherits="GameFontNormal"/>
<HighlightFont inherits="GameFontHighlight"/>
<DisabledFont inherits="GameFontDisable"/>
<HighlightTexture inherits="UIPanelButtonHighlightTexture"/>
</Button>
<!-- ref l.82-90. The permanently-greyed variant: the Disabled sheet in the Normal slot, white
label. Used for a button that reads as unavailable but still takes clicks. -->
<Button name="UIPanelButtonGrayTemplate" virtual="true">
<NormalFont inherits="GameFontHighlight"/>
<HighlightFont inherits="GameFontHighlight"/>
<DisabledFont inherits="GameFontDisable"/>
<NormalTexture inherits="UIPanelButtonDisabledTexture"/>
<PushedTexture inherits="UIPanelButtonDisabledDownTexture"/>
<DisabledTexture inherits="UIPanelButtonDisabledTexture"/>
<HighlightTexture inherits="UIPanelButtonHighlightTexture"/>
</Button>
<!-- ref l.91-103. The round X in a window's top-right corner — 8 call sites across 4 corpus
addons, the most-wanted template after the checkbox and the panel button. Note the name has
no `Template` suffix; that is the reference's own spelling, and the reference-globals table
agrees. Its OnClick is `HideUIPanel(this:GetParent())`, the verb UiPanels.xml defines: a
Lua global resolved at click time, so the load order between the two files is free. -->
<Button name="UIPanelCloseButton" virtual="true">
<Size><AbsDimension x="32" y="32"/></Size>
<Scripts>
<OnClick>HideUIPanel(this:GetParent())</OnClick>
</Scripts>
<NormalTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Up"/>
<PushedTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Down"/>
<HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/>
</Button>
<!-- ref l.104-124. The scroll-arrow kit. `UIPanelScrollBarButton` is the shared crop — the
1.12 arrow art is 32x32 with the glyph in the centre 16, which is what the 0.25..0.75
TexCoords take (ScrollTemplates.xml's own bar applies the identical crop). -->
<Texture name="UIPanelScrollBarButton" virtual="true">
<TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/>
</Texture>
<Button name="UIPanelScrollUpButtonTemplate" virtual="true">
<Size><AbsDimension x="16" y="16"/></Size>
<NormalTexture inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Up"/>
<PushedTexture inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Down"/>
<DisabledTexture inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Disabled"/>
<HighlightTexture inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Highlight" alphaMode="ADD"/>
</Button>
<Button name="UIPanelScrollDownButtonTemplate" virtual="true">
<Size><AbsDimension x="16" y="16"/></Size>
<NormalTexture inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Up"/>
<PushedTexture inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Down"/>
<DisabledTexture inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Disabled"/>
<HighlightTexture inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Highlight" alphaMode="ADD"/>
</Button>
<!-- ref l.125-165. The scroll bar itself: a Slider carrying its two step buttons as nested
frames, so `$parentScrollUpButton`/`$parentScrollDownButton` publish under the OWNER's
name two levels down (`MyScrollScrollBarScrollUpButton`) — which is exactly what
`ScrollFrame_OnLoad` and `FauxScrollFrame_Update` getglobal for. The value model here is
the REFERENCE's: `OnValueChanged` pushes the value straight into the parent ScrollFrame's
`SetVerticalScroll`, i.e. pixels of pan. (benilla's own `BenillaScrollBarTemplate` in
ScrollTemplates.xml is the faux twin of this — same art and same child names, but its
OnValueChanged drives a row offset instead. Both are needed: ours serves our windows, this
serves an addon that names the reference template.) -->
<Slider name="UIPanelScrollBarTemplate" virtual="true">
<Size><AbsDimension x="16" y="0"/></Size>
<Frames>
<!-- Both arrows step by half a bar-height and differ only in sign; unlike the wheel,
both click. -->
<Button name="$parentScrollUpButton" inherits="UIPanelScrollUpButtonTemplate">
<Anchors><Anchor point="BOTTOM" relativePoint="TOP"/></Anchors>
<Scripts>
<OnClick>
local bar = this:GetParent()
bar:SetValue(bar:GetValue() - bar:GetHeight() / 2)
PlaySound("UChatScrollButton")
</OnClick>
</Scripts>
</Button>
<Button name="$parentScrollDownButton" inherits="UIPanelScrollDownButtonTemplate">
<Anchors><Anchor point="TOP" relativePoint="BOTTOM"/></Anchors>
<Scripts>
<OnClick>
local bar = this:GetParent()
bar:SetValue(bar:GetValue() + bar:GetHeight() / 2)
PlaySound("UChatScrollButton")
</OnClick>
</Scripts>
</Button>
</Frames>
<Scripts>
<OnValueChanged>this:GetParent():SetVerticalScroll(arg1)</OnValueChanged>
</Scripts>
<ThumbTexture name="$parentThumbTexture" inherits="UIPanelScrollBarButton" file="Interface\Buttons\UI-ScrollBar-Knob">
<Size><AbsDimension x="16" y="16"/></Size>
<TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/>
</ThumbTexture>
</Slider>
<!-- ref l.166-212. The REAL scroll frame: an engine `<ScrollFrame>` that pans and clips a
scroll child, with the bar above pinned down its right edge (inset 16 top and bottom so
the arrow buttons sit inside the track span). 6 call sites across 2 corpus addons.
`ScrollFrame_OnLoad` — the reference's own name for it — is declared in ScrollTemplates.xml;
the other two handlers are this file's script block. An instance supplies its own
`<ScrollChild>` — without one the frame has no scroll range at all, which the loader now
says out loud. -->
<ScrollFrame name="UIPanelScrollFrameTemplate" virtual="true">
<Frames>
<Slider name="$parentScrollBar" inherits="UIPanelScrollBarTemplate">
<Anchors>
<Anchor point="TOPLEFT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="6" y="-16"/></Offset></Anchor>
<Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="6" y="16"/></Offset></Anchor>
</Anchors>
</Slider>
</Frames>
<Scripts>
<OnLoad>ScrollFrame_OnLoad()</OnLoad>
<OnScrollRangeChanged>ScrollFrame_OnScrollRangeChanged(arg2)</OnScrollRangeChanged>
<!-- Each arrow is live only while there is somewhere its way to go: up dies at offset
zero, down dies once the bar has been seated at the top of its range. The bar's
own value is re-read for the down test rather than arg1 being reused, because
SetValue above may have clamped it. (The reference's comment on this pair reads
"The code to disable the ScrollDownButton is pretty hacked, but it works" — it
asks the same question as `(value - max) == 0`.) -->
<OnVerticalScroll>
local scrollbar = getglobal(this:GetName() .. "ScrollBar")
scrollbar:SetValue(arg1)
local up = getglobal(scrollbar:GetName() .. "ScrollUpButton")
local down = getglobal(scrollbar:GetName() .. "ScrollDownButton")
local _, maxScroll = scrollbar:GetMinMaxValues()
if arg1 == 0 then up:Disable() else up:Enable() end
if scrollbar:GetValue() == maxScroll then down:Disable() else down:Enable() end
</OnVerticalScroll>
<OnMouseWheel>ScrollFrameTemplate_OnMouseWheel(arg1)</OnMouseWheel>
</Scripts>
</ScrollFrame>
<!-- ref l.226-279. The standard text box: a three-slice Common-Input-Border under an EditBox,
with the reference's escape/focus trio. 5 call sites across 3 corpus addons. The
direct-child `<FontString>` is the box's TEXT region (the engine's LoadXML slot, not a
layer) — `loader/regions.rs`'s `apply_special_fontstrings`. -->
<EditBox name="InputBoxTemplate" enableMouse="true" virtual="true">
<Layers>
<Layer level="BACKGROUND">
<Texture name="$parentLeft" file="Interface\Common\Common-Input-Border">
<Size><AbsDimension x="8" y="20"/></Size>
<Anchors><Anchor point="LEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
<TexCoords left="0" right="0.0625" top="0" bottom="0.625"/>
</Texture>
<Texture name="$parentRight" file="Interface\Common\Common-Input-Border">
<Size><AbsDimension x="8" y="20"/></Size>
<Anchors><Anchor point="RIGHT"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor></Anchors>
<TexCoords left="0.9375" right="1.0" top="0" bottom="0.625"/>
</Texture>
<Texture name="$parentMiddle" file="Interface\Common\Common-Input-Border">
<Size><AbsDimension x="10" y="20"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="$parentLeft" relativePoint="RIGHT"/>
<Anchor point="RIGHT" relativeTo="$parentRight" relativePoint="LEFT"/>
</Anchors>
<TexCoords left="0.0625" right="0.9375" top="0" bottom="0.625"/>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnEscapePressed>this:ClearFocus()</OnEscapePressed>
<OnEditFocusLost>this:HighlightText(0, 0)</OnEditFocusLost>
<OnEditFocusGained>this:HighlightText()</OnEditFocusGained>
</Scripts>
<FontString inherits="ChatFontNormal"/>
</EditBox>
<!-- ref l.280-302. THE most-wanted template in the whole corpus: 69 `CreateFrame` call sites.
A 32x32 checkbox with its label hung off the right edge, and no scripts of its own — the
checked flag toggles in the engine BEFORE `OnClick` fires (script/button.rs), so an addon
that sets only an OnClick reads the new state there, which is what every one of those 69
sites assumes. -->
<CheckButton name="UICheckButtonTemplate" virtual="true">
<Size><AbsDimension x="32" y="32"/></Size>
<Layers>
<Layer level="ARTWORK">
<FontString name="$parentText" inherits="GameFontNormalSmall">
<Anchors><Anchor point="LEFT" relativePoint="RIGHT"><Offset><AbsDimension x="-2" y="0"/></Offset></Anchor></Anchors>
</FontString>
</Layer>
</Layers>
<NormalTexture file="Interface\Buttons\UI-CheckBox-Up"/>
<PushedTexture file="Interface\Buttons\UI-CheckBox-Down"/>
<HighlightTexture file="Interface\Buttons\UI-CheckBox-Highlight" alphaMode="ADD"/>
<CheckedTexture file="Interface\Buttons\UI-CheckBox-Check"/>
<DisabledCheckedTexture file="Interface\Buttons\UI-CheckBox-Check-Disabled"/>
</CheckButton>
<!-- ref l.411-437. The radio button — the same CheckButton machinery on the four-frame
UI-RadioButton strip (normal / checked / highlight are three crops of one 64x16 sheet).
Carried because it is the checkbox's sibling in the same file and costs nothing; no corpus
addon names it today. -->
<CheckButton name="UIRadioButtonTemplate" virtual="true">
<Size><AbsDimension x="16" y="16"/></Size>
<Layers>
<Layer level="BACKGROUND">
<FontString name="$parentText" inherits="GameFontNormalSmall">
<Anchors><Anchor point="LEFT" relativePoint="RIGHT"><Offset><AbsDimension x="5" y="0"/></Offset></Anchor></Anchors>
</FontString>
</Layer>
</Layers>
<NormalTexture file="Interface\Buttons\UI-RadioButton">
<TexCoords left="0" right="0.25" top="0" bottom="1"/>
</NormalTexture>
<HighlightTexture file="Interface\Buttons\UI-RadioButton" alphaMode="ADD">
<TexCoords left="0.5" right="0.75" top="0" bottom="1"/>
</HighlightTexture>
<CheckedTexture file="Interface\Buttons\UI-RadioButton">
<TexCoords left="0.25" right="0.5" top="0" bottom="1"/>
</CheckedTexture>
</CheckButton>
</Ui>