Files
benilla-octo/crates/benilla-app/assets/ui/MoneyFrame.xml
T
SamandClaude Fable 5 cf581aa2ac the auction house opens, the Honor tab lands, and a day of fixes
- the auction house end to end: right-clicking an auctioneer opens Browse/Bids/Auctions on the server's reply — search, the category tree from your own DBCs, the reference's 50-a-page pager, multi-key sorting (directions corrected at the bytes), bid/buyout, the sell slot with deposit and duration, cancel with its fee popup; prices sit on the reference's own money-frame kit in lined-up columns, the twenty auction messages split refusals-red / outcomes-to-chat, and a won or sold auction reads as a proper mail receipt — the window's Lua re-worded in our own terms after the overlap ratchet caught the first cut leaning on the reference's text
- the PvP honor system whole: the Honor tab and the inspect page over a real wire model, with current rank and highest-ever rank correctly two different fields
- a day of reported fixes: WASD survives a /logout re-entry, addon settings save on a window close and Cmd+Q (exactly once — a mac close could fire the tail twice), clams open again, random-enchant items name themselves on every surface, the loot window's rows hold their seats with legible counts, idle players stop sinking through building floors, the shooter re-pulls between Auto Shots, portraits loosen ~19% to the client's own aspect-1.0 matrix, and big creatures thump the camera off the CameraShakes table
- character select clicks like 1.12 — captions whiten on hover, buttons fire on release, Humans face straight ahead off the stage bone's real yaw, the facing is per-character, and hunter/warlock pets stand beside you at their family-ramp size with their own emitters (the imp's flames), the Voidwalker's sequence-hidden shackles culled
- the smaller player-facing set: nameplate on/off rows in Options with the CanAttack category gate (emissaries stop plating), the bonus bar slides up with igBonusBarOpen, the camera's framing height glides on a shapeshift, the open letter evicts the centre seat, the far-band fog hull stops printing a pale horizon stripe at low view distance, the guide arrow is gold with per-source rim art, error text fades through its shadow too, and /convertraid converts the party
- README: the auction house and PvP honor move out of "not built yet"

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 19:04:27 +07:00

618 lines
34 KiB
XML

<Ui>
<!--
THE MONEY FRAME KIT — `MoneyFrameTemplate` / `SmallMoneyFrameTemplate`, the `MoneyTypeInfo`
table and the `MoneyFrame_*` API that drives them.
This is **our implementation** of that kit. The specification it implements is the extracted
1.12 `Interface\FrameXML\MoneyFrame.lua` (356 lines) and `MoneyFrame.xml` (297), cited below
as `ref l.N`: the names, the published field names, the constants and every branch of the
collapse rule are the specification's, because addons call this by name and a compatible kit
has no freedom in any of that. How it is written — the structure, the helpers, the local
names, the comments — is ours.
WHY IT IS HERE: it is FrameXML's surface, not Rust's (decision 1190 — a name the shipped 1.12
UI defines belongs in a UI file, never hardcoded), and the addon corpus asks for it by name.
`MoneyFrame_SetType` is wanted by 11 addons, `MoneyFrame_Update` by 9, `SmallMoneyFrame_OnLoad`
by 9, and 13 declare a frame `inherits="SmallMoneyFrameTemplate"`. `MoneyTypeInfo` was one of
the top runtime walls the frame rename left standing.
── THE OTHER COIN KIT, and why there are still two ──────────────────────────────────────────
Eight of our windows (merchant, bank, trade, mail, quest, quest log, taxi, trainer) do NOT use
this file. They render coins through `BenillaMoney_Set`/`_Clear`/`_SetColor` in
MerchantFrame.xml: a three-SLOT chain (`<prefix>Coin1..3`) that fills only the non-zero
denominations in display order and re-flows, rather than three fixed GoldButton/SilverButton/
CopperButton frames that hide themselves. That kit takes its coin TexCoords, its collapse and
its shrink from the same specification as this one, and its layout is the one the director has
signed off across those eight windows.
The auction house is the exception, and the reason the reconciliation started there rather
than anywhere else: the three-slot kit has no notion of a money TYPE, so it cannot express
`showSmallerCoins` or `fixedWidth` — and those two flags ARE the auction house's price column
(`MoneyTypeInfo["AUCTION"]`, declared below and, until AuctionFrame.xml moved, used by
nothing). On the three-slot kit "1g" showed as one lone gold coin where the reference shows
`1g 0s 0c`, and a column of prices packed tight instead of lining up. That is not a layout
preference to re-approve, it is the kit being the wrong kit. See decision 1522.
So the two still coexist, and the split is now by KIT CAPABILITY as much as by audience:
· `BenillaMoney_*` + `<prefix>Coin1..3` — the eight windows whose look is signed off and
whose money is all plain collapsing STATIC amounts, which that kit renders correctly.
· `MoneyFrame_*` + `MoneyTypeInfo` here — the names and structure an addon writes against,
what an addon's `inherits="SmallMoneyFrameTemplate"` resolves to, and what the auction
house is laid out on.
Finishing the migration — moving those eight onto `SmallMoneyFrameTemplate` and retiring
`BenillaMoney_*` — is still the right end state; it is a re-layout of hand-authored art in
eight files (an approved look), so it stays named here rather than done in passing.
── WHAT IS NOT CARRIED, and why (each is guarded at its own site below) ─────────────────────
· THE COIN PICKUP. `OpenCoinPickupFrame`/`UpdateCoinPickupFrame`/`CoinPickupFrame` belong to
CoinPickupFrame.lua/.xml, which we do not ship — and the engine verbs underneath them
(`PickupPlayerMoney`, `DropCursorMoney`, `PickupTradeMoney`, `AddTradeMoney`) are not built
either, so a picked-up coin would have nowhere to go. The coin buttons still take the mouse
for a `canPickup` type (that is the specified state) and the click is guarded, so it does
nothing.
· `GetCursorMoney` (PLAYER's amount, ref l.17) — the engine verb for coins held on the cursor.
With no coin pickup there is no cursor money, so its term is not approximated away: it is
structurally zero. Stated at the spot.
· `GetSendMailMoney` / `GetSendMailCOD` (ref l.73, l.90) — 1.12 engine verbs we have not
built. We ship their SETTERS (`SetSendMailMoney`/`SetSendMailCOD`, which MailFrame.xml
drives); nothing reads the amount back yet, so those two types read 0.
· `message()` (ref l.145, l.173, l.181) — the one-line StaticPopup shim, which belongs to
BasicControls.xml, a file family we have not built. Guarded, so a misuse of the API stays
silent instead of erroring on the diagnostic.
· `Button:GetTextWidth()` (ref l.202 etc.) — BUILT, and called here, exactly as the
specification calls it. It forwards to the label FontString's `GetStringWidth`, which the
engine now answers inside the tick that asked (`script::measure`).
· The four `Pickup*`/`Add*` mail verbs the pickup closures name are not in 1.12's `_G` either
(they are absent from reference/1.12-globals.tsv) — so those closures are as unreachable
here as they are there. They exist because the table's shape is the contract.
-->
<Script><![CDATA[
-- ── What a coin is worth ─────────────────────────────────────────────────────────────────
-- Published globals: an addon that formats a price does the same split we do below, and
-- reads these rather than spelling 100 twice.
COPPER_PER_SILVER = 100
SILVER_PER_GOLD = 100
COPPER_PER_GOLD = COPPER_PER_SILVER * SILVER_PER_GOLD
-- ── How wide a coin draws ────────────────────────────────────────────────────────────────
-- One coin icon's width at each of the two sizes the templates below come in, and the gap
-- between two coin buttons — NEGATIVE, because the three deliberately bite into each other
-- so a group reads as one number rather than as three. `COIN_BUTTON_WIDTH` is the fixed slot
-- a `fixedWidth` type pads its smaller coins out to, so a column of prices lines up.
-- The values are the specification's (ref l.2-12): measurements of the shipped coin art, not
-- ours to re-derive.
MONEY_ICON_WIDTH = 19
MONEY_ICON_WIDTH_SMALL = 13
MONEY_BUTTON_SPACING = -4
MONEY_BUTTON_SPACING_SMALL = -4
COIN_BUTTON_WIDTH = 32
-- ── The money types (ref l.14-103) ───────────────────────────────────────────────────────
--
-- A money frame carries no amount of its own: it carries a TYPE, and the type says where the
-- number comes from and how the coins behave. An entry has three parts:
--
-- · `UpdateFunc()` returns the amount, in copper. It is called with the global `this` bound
-- to the frame being painted, so a type may read the frame as well as the engine.
-- · `PickupFunc(amount)` / `DropFunc()` are the cursor verbs a click-to-pick-up type drives.
-- · the display flags `MoneyFrame_Update` reads: `collapse` (drop leading zero
-- denominations), `showSmallerCoins` (keep the trailing ones on even at zero; the value
-- "Backpack" additionally keeps copper on by itself), `canPickup` (the coins take the
-- mouse), `fixedWidth` (pad the smaller coins to COIN_BUTTON_WIDTH), `truncateSmallCoins`
-- (drop copper once there is gold).
--
-- Nothing else is consulted. That is why those field names and the two function signatures
-- are the published contract and not an implementation detail: addons register types of their
-- own into this table and expect exactly these parts to be honoured.
MoneyTypeInfo = { }
-- Read an amount through an engine verb that may not be built here yet: absent, it reads 0
-- rather than calling into nil. Two of the seven types below need it — see the header.
local function AmountFrom(verbName)
local verb = getglobal(verbName)
if verb then
return verb()
end
return 0
end
-- The purse. The specification subtracts a third term here (ref l.17,
-- `GetMoney() - GetCursorMoney() - GetPlayerTradeMoney()`): coins lifted onto the cursor by
-- the coin-pickup frame. benilla ships neither that frame nor the `PickupPlayerMoney` verb
-- behind it, so the term is structurally 0 rather than approximated away — it comes back the
-- moment either lands.
MoneyTypeInfo["PLAYER"] = {
UpdateFunc = function() return GetMoney() - GetPlayerTradeMoney() end,
PickupFunc = function(amount) PickupPlayerMoney(amount) end,
DropFunc = function() DropCursorMoney() end,
collapse = 1,
canPickup = 1,
showSmallerCoins = "Backpack",
}
-- A number the owner parked on the frame itself — what `MoneyFrame_Update(name, amount)`
-- leaves behind, and how an addon shows a price it worked out for itself.
MoneyTypeInfo["STATIC"] = {
UpdateFunc = function() return this.staticMoney end,
collapse = 1,
}
-- The auction house's price column: the same source as STATIC, but the smaller coins pad out
-- to a fixed slot and stay on at zero, so a stack of prices reads as a column of digits.
MoneyTypeInfo["AUCTION"] = {
UpdateFunc = function() return this.staticMoney end,
collapse = 1,
showSmallerCoins = "Backpack",
fixedWidth = 1,
truncateSmallCoins = nil,
}
-- Our side of an open trade, and the other party's. Only ours is click-to-pick-up.
MoneyTypeInfo["PLAYER_TRADE"] = {
UpdateFunc = function() return GetPlayerTradeMoney() end,
PickupFunc = function(amount) PickupTradeMoney(amount) end,
DropFunc = function() AddTradeMoney() end,
collapse = 1,
canPickup = 1,
}
MoneyTypeInfo["TARGET_TRADE"] = {
UpdateFunc = function() return GetTargetTradeMoney() end,
collapse = 1,
}
-- Mail postage and cash-on-delivery. Postage explicitly does NOT collapse (ref l.84): the
-- send-mail frame wants all three coins standing whatever the amount, because you are typing
-- into them. Both read 0 until their engine getters exist — see the header.
MoneyTypeInfo["SEND_MAIL"] = {
UpdateFunc = function() return AmountFrom("GetSendMailMoney") end,
PickupFunc = function(amount) PickupSendMailMoney(amount) end,
DropFunc = function() AddSendMailMoney() end,
collapse = nil,
canPickup = 1,
showSmallerCoins = "Backpack",
}
MoneyTypeInfo["SEND_MAIL_COD"] = {
UpdateFunc = function() return AmountFrom("GetSendMailCOD") end,
PickupFunc = function(amount) PickupSendMailCOD(amount) end,
DropFunc = function() AddSendMailCOD() end,
collapse = 1,
canPickup = 1,
}
-- ── Hearing about a change (ref l.105-140) ───────────────────────────────────────────────
--
-- Every money frame registers all five money events; each then decides whether the one that
-- arrived is about the number IT is showing. That pairing is data, not control flow, so it is
-- written as data: one row per event, in the order the templates register them, naming the
-- money types that event can change.
local MONEY_EVENTS = {
{ "PLAYER_MONEY", { PLAYER = 1 } },
{ "PLAYER_TRADE_MONEY", { PLAYER = 1, PLAYER_TRADE = 1 } },
{ "TRADE_MONEY_CHANGED", { TARGET_TRADE = 1 } },
{ "SEND_MAIL_MONEY_CHANGED", { PLAYER = 1, SEND_MAIL = 1 } },
{ "SEND_MAIL_COD_CHANGED", { PLAYER = 1, SEND_MAIL_COD = 1 } },
}
-- The same rows keyed by event name, built once, so the handler below is a lookup.
local moneyEventTypes = { }
for _, row in ipairs(MONEY_EVENTS) do
moneyEventTypes[row[1]] = row[2]
end
local function MoneyFrameListen(frame)
for _, row in ipairs(MONEY_EVENTS) do
frame:RegisterEvent(row[1])
end
end
-- The two OnLoads differ in exactly one thing: `small`, which is what picks the 13px coin and
-- its tighter spacing over the 19px one in MoneyFrame_Update below. Both then take type
-- PLAYER, so a frame nobody tells otherwise shows the purse.
function MoneyFrame_OnLoad()
MoneyFrameListen(this)
MoneyFrame_SetType("PLAYER")
end
function SmallMoneyFrame_OnLoad()
MoneyFrameListen(this)
this.small = 1
MoneyFrame_SetType("PLAYER")
end
function MoneyFrame_OnEvent()
if not this.info or not this:IsVisible() then
return
end
local affected = moneyEventTypes[event]
if affected and affected[this.moneyType] then
MoneyFrame_UpdateMoney()
end
end
-- ── Painting ─────────────────────────────────────────────────────────────────────────────
-- A money frame's three coin buttons, biggest first. Every verb below addresses them as a
-- trio, so this is the one place their `$parent<Denomination>Button` names are spelled.
local function MoneyFrameCoins(frameName)
return getglobal(frameName .. "GoldButton"),
getglobal(frameName .. "SilverButton"),
getglobal(frameName .. "CopperButton")
end
-- Point a frame at a money type (ref l.142-162): remember it, wire the mouse to match, and
-- repaint. Reads `this` rather than taking a frame — that is the convention the eleven corpus
-- callers write against.
function MoneyFrame_SetType(type)
local info = MoneyTypeInfo[type]
if not info then
-- ref l.145 diagnoses this with `message()`, which we do not ship (see the header).
if message then
message("Invalid money type: " .. type)
end
return
end
this.info = info
this.moneyType = type
-- Only a click-to-pick-up type wants the mouse; on the rest a click falls through to
-- whatever is behind the coins.
local gold, silver, copper = MoneyFrameCoins(this:GetName())
local pickable = info.canPickup and true or false
gold:EnableMouse(pickable)
silver:EnableMouse(pickable)
copper:EnableMouse(pickable)
MoneyFrame_UpdateMoney()
end
-- Re-read the amount from the type and repaint (ref l.164-175). `this` again.
function MoneyFrame_UpdateMoney()
if not this.info then
if message then
message("Error moneyType not set")
end
return
end
local money = this.info.UpdateFunc()
MoneyFrame_Update(this:GetName(), money)
-- ref l.169-171 also feeds the coin-pickup frame while one is open. `hasPickup` is set
-- only by the coin click, which is guarded off (see the header), so this is unreachable
-- today rather than removed.
if this.hasPickup == 1 and UpdateCoinPickupFrame then
UpdateCoinPickupFrame(money)
end
end
-- Lay one denomination out: its digits, and the width those digits plus the coin icon need.
--
-- `Button:GetTextWidth()` right after `SetText`, which is what the specification writes
-- (ref l.202 and kin) and what the real client answers synchronously off its inline font
-- engine, so the coin is the right width on the frame that set its text.
--
-- This read used to return 0 — our measure landed at extract, a frame after the tick — and
-- left all three coins at exactly one bare icon width with their digits overlapping: the
-- director's "gold numbers are all cramped up when I first open the bags; close and open
-- again and it looks good", the reopen being the first open's cached measure. It was served
-- for a while by a digits-only advance table, since a number's width is a pure sum of
-- per-glyph advances. The engine answers the general question now (`script::measure`), so
-- this asks it the way the specification does.
local function ShowCoin(coin, coinName, amount, iconWidth)
coin:SetText(amount)
coin:SetWidth(coin:GetTextWidth() + iconWidth)
coin:Show()
end
-- Chain the next-bigger coin onto `coin`, and report what `coin` contributes to the group's
-- width.
--
-- Showing: the bigger coin hangs off this one's LEFT edge by `spacing` (negative — they
-- overlap), and the group grows by this coin's width less that overlap, but only when the
-- bigger coin is actually on screen to overlap with. Not showing: this coin hides and the
-- bigger one collapses onto its RIGHT edge, contributing nothing. `padToSlot` is the
-- `fixedWidth` exception, which sizes the coin to the fixed column slot first.
local function ChainCoin(bigger, coin, coinName, showing, padToSlot, spacing)
if not showing then
coin:Hide()
bigger:SetPoint("RIGHT", coinName, "RIGHT", 0, 0)
return 0
end
if padToSlot then
coin:SetWidth(COIN_BUTTON_WIDTH)
end
local grown = coin:GetWidth()
bigger:SetPoint("RIGHT", coinName, "LEFT", spacing, 0)
if bigger:IsVisible() then
grown = grown - spacing
end
return grown
end
-- THE PAINTER (ref l.177-270). Split a copper amount into the three denominations, size each
-- coin to its own digits plus its icon, and then — if the type collapses — drop the leading
-- zeros, re-chain what is left so the group packs tight, and report the frame's true width.
--
-- This one takes a frame NAME, not `this`: it is the only entry point in the family an owner
-- can call about a frame other than the one currently dispatching, which is how an addon
-- paints a STATIC frame it has just filled.
function MoneyFrame_Update(frameName, money)
local frame = getglobal(frameName)
local info = frame.info
if not info then
-- ref l.181 diagnoses and, notably, does NOT return: the coins below are still laid
-- out, and the collapse read further down is what actually stops it. Kept as-is.
if message then
message("Error moneyType not set")
end
end
-- Copper is the low two digits, silver the next two, gold everything above. Silver comes
-- out by subtracting the gold back off rather than by a second `mod`: `mod` here is 1.12's
-- `math.mod`, which truncates towards zero, so `mod(-1, 100)` is -1 and not 99 — the two
-- forms part company the moment `money` goes negative (which `GetMoney()` minus a trade
-- offer can), and this one is the specified answer.
-- A STATIC/AUCTION frame's amount is whatever its owner last parked on it, and on the
-- very first paint — `MoneyFrame_SetType`'s own repaint, in OnLoad, before any owner has
-- filled it — that is nil. The specification divides straight into it and throws there;
-- we answer 0, because the throw would take the whole `<OnLoad>`/`<OnShow>` chain down
-- with it and an empty price column is the honest reading of "nothing set yet".
money = money or 0
local gold = floor(money / COPPER_PER_GOLD)
local silver = floor((money - gold * COPPER_PER_GOLD) / COPPER_PER_SILVER)
local copper = mod(money, COPPER_PER_SILVER)
local goldCoin, silverCoin, copperCoin = MoneyFrameCoins(frameName)
local iconWidth, spacing = MONEY_ICON_WIDTH, MONEY_BUTTON_SPACING
if frame.small then
iconWidth, spacing = MONEY_ICON_WIDTH_SMALL, MONEY_BUTTON_SPACING_SMALL
end
ShowCoin(goldCoin, frameName .. "GoldButton", gold, iconWidth)
ShowCoin(silverCoin, frameName .. "SilverButton", silver, iconWidth)
ShowCoin(copperCoin, frameName .. "CopperButton", copper, iconWidth)
-- Remember what the frame is displaying — STATIC's own reader reads it back.
frame.staticMoney = money
-- A type that does not collapse is finished: all three coins stand, at the width their
-- digits asked for, and the frame keeps whatever width it was given.
if not info.collapse then
return
end
-- Gold leads. Present, it stays and sets the terms for the two below it; absent, it goes.
-- The running width starts at one icon's worth of frame padding.
local width = iconWidth
local keepSmaller, dropCopper
if gold > 0 then
width = width + goldCoin:GetWidth()
keepSmaller = info.showSmallerCoins and 1 or nil
dropCopper = info.truncateSmallCoins and 1 or nil
else
goldCoin:Hide()
end
-- Silver, then copper: each either shows — padded, chained and counted — or hides and lets
-- the coin above it collapse onto its edge. Silver showing under a `showSmallerCoins` type
-- is what carries the exemption down to copper; copper also survives at zero for a
-- "Backpack" type, and dies whatever it is once gold truncated it.
local showSilver = silver > 0 or keepSmaller
width = width + ChainCoin(goldCoin, silverCoin, frameName .. "SilverButton",
showSilver, keepSmaller and info.fixedWidth, spacing)
if showSilver and info.showSmallerCoins then
keepSmaller = 1
end
local showCopper = (copper > 0 or keepSmaller or info.showSmallerCoins == "Backpack")
and not dropCopper
width = width + ChainCoin(silverCoin, copperCoin, frameName .. "CopperButton",
showCopper, keepSmaller and info.fixedWidth, spacing)
frame:SetWidth(width)
end
-- A NO-OP, deliberately. The specification's whole body for this one sits inside a `--[[ ]]`
-- block (ref l.272-346) — an earlier painter that MoneyFrame_Update replaced. The name is in
-- the shipped client's `_G`, and an addon that calls it there gets exactly this: nothing.
function RefreshMoneyFrame(frameName, money, small, collapse, showSmallerCoins)
end
-- Recolour the DIGITS; the coin icons keep their own texture (ref l.348-356). This is how a
-- price you cannot afford turns red.
function SetMoneyFrameColor(frameName, r, g, b)
local gold, silver, copper = MoneyFrameCoins(frameName)
gold:SetTextColor(r, g, b)
silver:SetTextColor(r, g, b)
copper:SetTextColor(r, g, b)
end
-- A click on a coin opens the pickup frame on that denomination, seeded with what the frame is
-- currently showing; `denomination` is one coin's worth in copper, which is the unit the
-- pickup frame counts in.
--
-- Guarded, because we ship no coin pickup (see the header) — so today the click does nothing,
-- and the mouse-enabled state a `canPickup` type gives the coins is all that is observable.
-- Note the amount is read by calling the type's own `UpdateFunc` while `this` is still the
-- BUTTON rather than the frame, which is what the specification's own coin `<OnClick>` does
-- (ref MoneyFrame.xml l.20-23) and what a frame-reading type would see through.
function BenillaMoneyFrameCoin_OnClick(coin, denomination)
if not OpenCoinPickupFrame then
return
end
local frame = coin:GetParent()
OpenCoinPickupFrame(denomination, MoneyTypeInfo[frame.moneyType].UpdateFunc(), frame)
frame.hasPickup = 1
end
-- Closing a money frame takes any pickup it opened down with it.
function BenillaMoneyFrame_OnHide()
if this.hasPickup == 1 and CoinPickupFrame then
CoinPickupFrame:Hide()
this.hasPickup = 0
end
end
]]></Script>
<!--
MoneyFrameTemplate (ref MoneyFrame.xml l.3-149) — the LARGE kit: 192x28, 19px coins, the
NumberFontNormalLarge digits. The three buttons chain RIGHT-to-LEFT from the copper end, which
is what lets MoneyFrame_Update above re-point them past a hidden denomination.
`<PushedTextOffset>` is carried for provenance; our loader does not model it and ignores it.
-->
<Frame name="MoneyFrameTemplate" virtual="true">
<Size><AbsDimension x="192" y="28"/></Size>
<Frames>
<Button name="$parentCopperButton">
<Size><AbsDimension x="47" y="19"/></Size>
<Anchors>
<Anchor point="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor>
</Anchors>
<Scripts>
<OnClick>BenillaMoneyFrameCoin_OnClick(this, 1)</OnClick>
</Scripts>
<NormalTexture file="Interface\MoneyFrame\UI-MoneyIcons">
<Size><AbsDimension x="19" y="19"/></Size>
<Anchors><Anchor point="RIGHT"/></Anchors>
<TexCoords left="0.5" right="0.75" top="0" bottom="1"/>
</NormalTexture>
<ButtonText name="$parentText">
<Anchors>
<Anchor point="RIGHT"><Offset><AbsDimension x="-19" y="0"/></Offset></Anchor>
</Anchors>
</ButtonText>
<NormalFont inherits="NumberFontNormalLarge" justifyH="RIGHT"/>
<PushedTextOffset><AbsDimension x="0" y="0"/></PushedTextOffset>
</Button>
<Button name="$parentSilverButton">
<Size><AbsDimension x="47" y="19"/></Size>
<Anchors>
<Anchor point="RIGHT" relativeTo="$parentCopperButton" relativePoint="LEFT"><Offset><AbsDimension x="-4" y="0"/></Offset></Anchor>
</Anchors>
<Scripts>
<OnClick>BenillaMoneyFrameCoin_OnClick(this, COPPER_PER_SILVER)</OnClick>
</Scripts>
<NormalTexture file="Interface\MoneyFrame\UI-MoneyIcons">
<Size><AbsDimension x="19" y="19"/></Size>
<Anchors><Anchor point="RIGHT"/></Anchors>
<TexCoords left="0.25" right="0.5" top="0" bottom="1"/>
</NormalTexture>
<ButtonText name="$parentText">
<Anchors>
<Anchor point="RIGHT"><Offset><AbsDimension x="-19" y="0"/></Offset></Anchor>
</Anchors>
</ButtonText>
<NormalFont inherits="NumberFontNormalLarge" justifyH="RIGHT"/>
<PushedTextOffset><AbsDimension x="0" y="0"/></PushedTextOffset>
</Button>
<Button name="$parentGoldButton">
<Size><AbsDimension x="47" y="19"/></Size>
<Anchors>
<Anchor point="RIGHT" relativeTo="$parentSilverButton" relativePoint="LEFT"><Offset><AbsDimension x="-4" y="0"/></Offset></Anchor>
</Anchors>
<Scripts>
<OnClick>BenillaMoneyFrameCoin_OnClick(this, COPPER_PER_GOLD)</OnClick>
</Scripts>
<NormalTexture file="Interface\MoneyFrame\UI-MoneyIcons">
<Size><AbsDimension x="19" y="19"/></Size>
<Anchors><Anchor point="RIGHT"/></Anchors>
<TexCoords left="0" right="0.25" top="0" bottom="1"/>
</NormalTexture>
<ButtonText name="$parentText">
<Anchors>
<Anchor point="RIGHT"><Offset><AbsDimension x="-19" y="0"/></Offset></Anchor>
</Anchors>
</ButtonText>
<NormalFont inherits="NumberFontNormalLarge" justifyH="RIGHT"/>
<PushedTextOffset><AbsDimension x="0" y="0"/></PushedTextOffset>
</Button>
</Frames>
<Scripts>
<OnLoad>MoneyFrame_OnLoad()</OnLoad>
<OnEvent>MoneyFrame_OnEvent()</OnEvent>
<OnShow>MoneyFrame_UpdateMoney()</OnShow>
<OnHide>BenillaMoneyFrame_OnHide()</OnHide>
</Scripts>
</Frame>
<!--
SmallMoneyFrameTemplate (ref MoneyFrame.xml l.150-296) — the same kit at 128x13 with 13px
coins and NumberFontNormal digits, and `SmallMoneyFrame_OnLoad` in place of `MoneyFrame_OnLoad`
so `this.small` is set. This is the one the shipped UI uses nearly everywhere (merchant prices,
the purse, mail postage, trade offers) and the one 13 corpus addons inherit.
-->
<Frame name="SmallMoneyFrameTemplate" virtual="true">
<Size><AbsDimension x="128" y="13"/></Size>
<Frames>
<Button name="$parentCopperButton">
<Size><AbsDimension x="32" y="13"/></Size>
<Anchors>
<Anchor point="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor>
</Anchors>
<Scripts>
<OnClick>BenillaMoneyFrameCoin_OnClick(this, 1)</OnClick>
</Scripts>
<NormalTexture file="Interface\MoneyFrame\UI-MoneyIcons">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="RIGHT"/></Anchors>
<TexCoords left="0.5" right="0.75" top="0" bottom="1"/>
</NormalTexture>
<ButtonText name="$parentText">
<Anchors>
<Anchor point="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor>
</Anchors>
</ButtonText>
<NormalFont inherits="NumberFontNormal" justifyH="RIGHT"/>
<PushedTextOffset><AbsDimension x="0" y="0"/></PushedTextOffset>
</Button>
<Button name="$parentSilverButton">
<Size><AbsDimension x="32" y="13"/></Size>
<Anchors>
<Anchor point="RIGHT" relativeTo="$parentCopperButton" relativePoint="LEFT"><Offset><AbsDimension x="-4" y="0"/></Offset></Anchor>
</Anchors>
<Scripts>
<OnClick>BenillaMoneyFrameCoin_OnClick(this, COPPER_PER_SILVER)</OnClick>
</Scripts>
<NormalTexture file="Interface\MoneyFrame\UI-MoneyIcons">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="RIGHT"/></Anchors>
<TexCoords left="0.25" right="0.5" top="0" bottom="1"/>
</NormalTexture>
<ButtonText name="$parentText">
<Anchors>
<Anchor point="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor>
</Anchors>
</ButtonText>
<NormalFont inherits="NumberFontNormal" justifyH="RIGHT"/>
<PushedTextOffset><AbsDimension x="0" y="0"/></PushedTextOffset>
</Button>
<Button name="$parentGoldButton">
<Size><AbsDimension x="32" y="13"/></Size>
<Anchors>
<Anchor point="RIGHT" relativeTo="$parentSilverButton" relativePoint="LEFT"><Offset><AbsDimension x="-4" y="0"/></Offset></Anchor>
</Anchors>
<Scripts>
<OnClick>BenillaMoneyFrameCoin_OnClick(this, COPPER_PER_GOLD)</OnClick>
</Scripts>
<NormalTexture file="Interface\MoneyFrame\UI-MoneyIcons">
<Size><AbsDimension x="13" y="13"/></Size>
<Anchors><Anchor point="RIGHT"/></Anchors>
<TexCoords left="0" right="0.25" top="0" bottom="1"/>
</NormalTexture>
<ButtonText name="$parentText">
<Anchors>
<Anchor point="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor>
</Anchors>
</ButtonText>
<NormalFont inherits="NumberFontNormal" justifyH="RIGHT"/>
<PushedTextOffset><AbsDimension x="0" y="0"/></PushedTextOffset>
</Button>
</Frames>
<Scripts>
<OnLoad>SmallMoneyFrame_OnLoad()</OnLoad>
<OnEvent>MoneyFrame_OnEvent()</OnEvent>
<OnShow>MoneyFrame_UpdateMoney()</OnShow>
<OnHide>BenillaMoneyFrame_OnHide()</OnHide>
</Scripts>
</Frame>
</Ui>