Files
benilla-octo/crates/benilla-app/assets/ui/TextStatusBar.xml
T
SamandClaude Fable 5 d1140829d7 the interface code is ours: the transcription debt is paid
- forty files that carried the reference's literal Lua are rewritten as our own expression of the behaviour — worst identical run 61 lines down to 7 — and the README now says exactly that
- the overlap gate measures the code itself across all four reference corpora, and ratchets: the number may only go down
- a lost session ends at the login screen instead of silently re-authenticating and stealing the account back
- a building's skybox is a real model: Caverns of Time's white ceiling becomes its painted nebula and additive stars

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

184 lines
9.1 KiB
XML

<!--
The shared status-bar readout machinery — the contract 1.12's TextStatusBar.lua/.xml defines
(decision 1082), written here in our own terms. A bar opts in by calling
TextStatusBar_Initialize() in its OnLoad (setting `textLockable`), wiring a FontString via
SetTextStatusBarText(bar, text), and routing its OnEnter/OnLeave/OnValueChanged through the
Show/Hide/Update functions here. The text is "value / max", shown while hovered (a lockShow
refcount) or always when the `statusBarText` cvar is "1" ("Status Text" in the options; our
GetCVar returns nil for a cvar the engine doesn't carry, which reads as OFF — the 1.12
default).
Customers: the XP bar (ActionBar.xml) and, since decision 1143, the player and pet frames'
health/power bars (UnitFrames.xml). `textLockable` is what the statusBarText cvar pins, and
which bars carry it is the REFERENCE's own split, not an omission of ours: 1.12 sets it on the
player's two bars, the pet's two and the XP bar, and on nothing else. The target frame's bars
are deliberately not lockable there — its numerals are hover-only — so ours have the machinery
wired and no text regions yet; the hover half needs mouse-enabled bars we do not have.
-->
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script><![CDATA[
-- The readout has exactly three reasons to be on screen, and every function below is some
-- combination of them: the Status Text option pins it (only on a bar that opted in with
-- `textLockable`), the pointer is on the bar (a refcount, so nested hovers balance), or the
-- bar is showing its zero text — a phrase rather than a number, which stands on its own.
--
-- The option test is the one of the three that reads from outside the bar, and it is asked
-- from three places, so it lives here once. It takes the option's VALUE rather than calling
-- GetCVar itself: the CVAR_UPDATE handler is handed the new value along with the event and
-- must not go asking the engine for the one it is being told about.
local function optionPins(bar, setting)
return setting == "1" and bar.textLockable
end
-- `bar` is optional and falls back to `this`, the same shape TextStatusBar_UpdateTextString
-- below already has (and for the same reason): the ref calls this from a bar's own OnLoad,
-- where `this` is the bar, but our unit frames wire their children from ONE shared
-- BenillaUnitFrame_OnLoad that holds each bar as a value, not as `this` (decision 1143).
function TextStatusBar_Initialize(bar)
if not bar then
bar = this
end
bar:RegisterEvent("CVAR_UPDATE")
bar.lockShow = 0
end
-- Hand a bar the FontString its readout lives in. A bar without one is never an error
-- below — it simply has nothing to say, and every entry point here checks for that.
function SetTextStatusBarText(bar, text)
if not bar or not text then
return
end
bar.TextString = text
end
function TextStatusBar_OnEvent(cvar, value)
if event ~= "CVAR_UPDATE" or cvar ~= "STATUS_BAR_TEXT" or not this.TextString then
return
end
-- Switching the option ON pins the readout up at once. Switching it off only puts the
-- readout away when nothing else is holding it there: a hover in progress keeps its own,
-- and gets to hide it when it ends.
if optionPins(this, value) then
this.TextString:Show()
elseif this.lockShow == 0 then
this.TextString:Hide()
end
end
-- Repaint one bar's readout from the value it is currently carrying. `textStatusBar` is
-- optional and falls back to `this` for the same reason TextStatusBar_Initialize's is.
function TextStatusBar_UpdateTextString(textStatusBar)
if not textStatusBar then
textStatusBar = this
end
local readout = textStatusBar.TextString
if not readout then
return
end
local value = textStatusBar:GetValue()
local _, valueMax = textStatusBar:GetMinMaxValues()
-- No ceiling is not the same thing as a bar at zero (below): it means the bar does not
-- apply to this unit at all, so the BAR leaves the screen rather than reading out a
-- number. Its readout is left exactly as it stands and comes back with it.
if valueMax <= 0 then
textStatusBar:Hide()
return
end
textStatusBar:Show()
if value == 0 and textStatusBar.zeroText then
-- Empty, and this bar has a phrase for empty. The phrase displaces the numbers and
-- is shown outright: it is a message, so neither the option nor a hover gates it,
-- and `isZero` is the flag that tells the hover not to take it away again.
textStatusBar.isZero = 1
readout:SetText(textStatusBar.zeroText)
readout:Show()
return
end
textStatusBar.isZero = nil
if textStatusBar.prefix then
readout:SetText(textStatusBar.prefix .. " " .. value .. " / " .. valueMax)
else
readout:SetText(value .. " / " .. valueMax)
end
if optionPins(textStatusBar, GetCVar("statusBarText")) or textStatusBar.lockShow > 0 then
readout:Show()
else
readout:Hide()
end
end
function TextStatusBar_OnValueChanged()
TextStatusBar_UpdateTextString()
end
function SetTextStatusBarTextPrefix(bar, prefix)
if bar and bar.TextString then
bar.prefix = prefix
end
end
function SetTextStatusBarTextZeroText(bar, zeroText)
if bar and bar.TextString then
bar.zeroText = zeroText
end
end
-- One more hold on the readout. `lockShow` counts rather than flags because two things can
-- be holding it open at once: the character sheet takes a hold for as long as it is open
-- (CharacterFrame_OnShow, decision 1146) and a hover on the same bar takes a second one on
-- top. Only the last release puts the readout away, so the hover still balances.
function ShowTextStatusBarText(bar)
if bar and bar.TextString then
bar.lockShow = (bar.lockShow or 0) + 1
bar.TextString:Show()
end
end
-- One hold released. The count floors at none rather than going negative, so an unbalanced
-- release — a frame hidden out from under a hover — cannot strand the readout on screen.
function HideTextStatusBarText(bar)
if bar and bar.TextString then
bar.lockShow = math.max((bar.lockShow or 0) - 1, 0)
-- Releasing a hold only puts the readout away if none of the three reasons is left.
-- The ref reads `this.isZero` for the middle one — a leak of the handler's own frame
-- into a helper that otherwise takes `bar`. Equivalent at every call site (each
-- caller passes its handler's own frame), so it is written as `bar`, which also
-- keeps the function callable outside a handler, where `this` is nil.
if bar.lockShow > 0 or bar.isZero == 1
or optionPins(bar, GetCVar("statusBarText")) then
bar.TextString:Show()
else
bar.TextString:Hide()
end
end
end
]]></Script>
<!--
The opt-in template (ref-TextStatusBar.xml): every script routed through the functions
above. One transcription cut, named: the ref OnEnter's TargetFrame arm (re-anchor the unit
tooltip under the target frame's bars) references a TextStatusBar-inheriting TargetFrame
bar we don't build yet — it is dead until that slice, so it is left out rather than
shipped unreachable. A frame that overrides all five scripts (the XP bar does) takes only
the StatusBar widget type from inheriting this.
-->
<StatusBar name="TextStatusBar" virtual="true">
<Scripts>
<OnLoad>TextStatusBar_Initialize()</OnLoad>
<OnEvent>TextStatusBar_OnEvent(arg1, arg2)</OnEvent>
<OnEnter>
TextStatusBar_UpdateTextString()
ShowTextStatusBarText(this)
if this.tooltipTitle and GameTooltip_AddNewbieTip then
BenillaTooltip_AddNewbieTipFor(this, this.tooltipTitle, 1.0, 1.0, 1.0, this.tooltipText, 1)
end
</OnEnter>
<OnLeave>
HideTextStatusBarText(this)
if GameTooltip then GameTooltip:Hide() end
</OnLeave>
<OnValueChanged>TextStatusBar_OnValueChanged()</OnValueChanged>
</Scripts>
</StatusBar>
</Ui>