Revert "The Benilla scroll bar template scrolls its parent itself (#1730)"
This reverts e0895013. Two things were wrong with taking it.
**It was resolved by taking upstream's whole file.** `git checkout --theirs` on a
conflicted path takes that file's entire other side, not the conflicting hunk, so
the commit quietly cut 1454 lines out of this fork's own `OptionsFrame.xml`
(4586 → 3132) and replaced `ScriptLogFrame.xml` wholesale. That is what the 180
new test failures were: `BenillaKeyBindings_String` and `OptionsFrameSliders`
undefined, because the `<Script>` blocks defining them were gone.
**And the change itself is a regression here.** Its premise is that
`BenillaScrollBarTemplate`'s `OnValueChanged` is a faux-list handler every
instance has to override. In this fork it is not: our
`BenillaFauxScrollBar_OnValueChanged` (`ScrollTemplates.xml:33`) does the
faux-list `offset`/`updateFunc` step *and* `frame:SetVerticalScroll(value)` when
the parent is a ScrollFrame — a superset of upstream's
`BenillaScrollBar_OnValueChanged`. Swapping the template onto the plain handler
and deleting the faux one would take the faux-list path away from every bar built
from the template.
The earlier claim in e0895013's message — that
`BenillaFauxScrollBar_OnValueChanged` was "defined nowhere in the repo" — was
also wrong. It is defined at `ScrollTemplates.xml:33`. The grep behind that claim
ran against the conflicted working copy, where upstream's *non-conflicting*
deletion of the definition had already been applied, so only the call site showed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,16 @@
|
||||
<Ui>
|
||||
<!--
|
||||
The script error log, which 1.12 does not have, so every name carries the `Benilla` prefix;
|
||||
the stock `ScriptErrors` dialog shows one message, this keeps the log. Laid out on the
|
||||
ClassTrainer panel art as the class trainer lays itself out (Blizzard_TrainerUI.xml:214-356
|
||||
and :481-513, Blizzard_TrainerUI.lua:469-474): its rows, its list, its detail under the
|
||||
list and its two buttons in the art's sockets. It collects as a 1.12 error-log addon does:
|
||||
it wraps the handler `geterrorhandler` holds, the stock `_ERRORMESSAGE`
|
||||
(BasicControls.xml:16), which still runs after it. An addon that later calls
|
||||
`seterrorhandler` replaces the chain, as in 1.12.
|
||||
The script error log, which 1.12 does not have, so every name carries the `Benilla` prefix
|
||||
(`tests::reference_surface`); the stock `ScriptErrors` dialog shows one message, this keeps
|
||||
the log. Shaped like the reference's CraftFrame. It polls the engine:
|
||||
`BenillaGetNumScriptErrors()` is (retained, total-ever), `BenillaGetScriptErrorInfo(i)` is
|
||||
`seq, kind, message, count` (1-based, oldest first, nil past the end).
|
||||
-->
|
||||
<Script><![CDATA[
|
||||
-- A pushable above every stock panel's, so a game window opening pushes the log aside.
|
||||
UIPanelWindows["BenillaScriptLogFrame"] = { area = "left", pushable = 9, whileDead = 1 }
|
||||
|
||||
-- The class trainer's rows (`CLASS_TRAINER_SKILLS_DISPLAYED`, Blizzard_TrainerUI.lua:470).
|
||||
BENILLA_SCRIPTLOG_ROWS = 11
|
||||
BENILLA_SCRIPTLOG_ROWS = 13
|
||||
BENILLA_SCRIPTLOG_ROW_HEIGHT = 16
|
||||
-- A wrapped row would break the faux kit's fixed rows.
|
||||
BENILLA_SCRIPTLOG_ROW_CHARS = 52
|
||||
@@ -22,39 +18,6 @@
|
||||
-- A `seq`, not an index: indices shift when the cap evicts.
|
||||
BenillaScriptLogSelected = nil
|
||||
|
||||
-- Distinct messages kept before the oldest is evicted.
|
||||
BENILLA_SCRIPTLOG_CAP = 256
|
||||
-- Rows oldest first, each { seq, message, count }; `total` is the last `seq` handed out,
|
||||
-- kept apart from the row count so an eviction or a clear never renumbers.
|
||||
BenillaScriptLog = { rows = {}, total = 0 }
|
||||
|
||||
-- A repeat bumps its row's count and keeps its place.
|
||||
function BenillaScriptLog_Record(message)
|
||||
if type(message) ~= "string" then message = tostring(message) end
|
||||
local log = BenillaScriptLog
|
||||
local found = nil
|
||||
for i = 1, table.getn(log.rows) do
|
||||
if log.rows[i].message == message then found = log.rows[i] end
|
||||
end
|
||||
if found then
|
||||
found.count = found.count + 1
|
||||
else
|
||||
log.total = log.total + 1
|
||||
if table.getn(log.rows) >= BENILLA_SCRIPTLOG_CAP then table.remove(log.rows, 1) end
|
||||
table.insert(log.rows, { seq = log.total, message = message, count = 1 })
|
||||
end
|
||||
if BenillaScriptLogFrame and BenillaScriptLogFrame:IsVisible() then
|
||||
BenillaScriptLog_Update()
|
||||
end
|
||||
end
|
||||
|
||||
-- The chain: the log first, guarded so a fault in it cannot stop the stock handler.
|
||||
local benillaStockErrorHandler = geterrorhandler()
|
||||
seterrorhandler(function(message)
|
||||
pcall(BenillaScriptLog_Record, message)
|
||||
return benillaStockErrorHandler(message)
|
||||
end)
|
||||
|
||||
-- `strsub` counts bytes, so the cut backs up over UTF-8 continuation bytes (0x80..0xBF).
|
||||
function BenillaScriptLog_RowText(message)
|
||||
local cut = strfind(message, "\n", 1, 1)
|
||||
@@ -72,10 +35,18 @@
|
||||
return head
|
||||
end
|
||||
|
||||
function BenillaScriptLog_Update()
|
||||
local shown = table.getn(BenillaScriptLog.rows)
|
||||
local total = BenillaScriptLog.total
|
||||
-- `load` red (the addon is not running), `error` amber (code raised), `warn` grey (a call
|
||||
-- was accepted and quietly did nothing).
|
||||
function BenillaScriptLog_RowColor(kind)
|
||||
if kind == "load" then return 1.0, 0.3, 0.3 end
|
||||
if kind == "warn" then return 0.65, 0.65, 0.65 end
|
||||
return 1.0, 0.82, 0.0
|
||||
end
|
||||
|
||||
function BenillaScriptLog_Update()
|
||||
local shown, total = BenillaGetNumScriptErrors()
|
||||
|
||||
-- "Problems", because two of the three kinds are not errors.
|
||||
local summary
|
||||
if total == 0 then
|
||||
summary = "No problems this session."
|
||||
@@ -97,17 +68,18 @@
|
||||
for i = 1, BENILLA_SCRIPTLOG_ROWS do
|
||||
local button = getglobal("BenillaScriptLogRow" .. i)
|
||||
local index = offset + i
|
||||
local row = BenillaScriptLog.rows[index]
|
||||
if row then
|
||||
button.seq = row.seq
|
||||
button.message = row.message
|
||||
local seq, kind, message, count = BenillaGetScriptErrorInfo(index)
|
||||
if seq then
|
||||
button.seq = seq
|
||||
button.message = message
|
||||
-- `#12 x1113`: one deduplicated failure that happened 1,113 times.
|
||||
local label = "#" .. row.seq
|
||||
if row.count > 1 then label = label .. " x" .. row.count end
|
||||
local label = "#" .. seq
|
||||
if count > 1 then label = label .. " x" .. count end
|
||||
button.index:SetText(label)
|
||||
button.label:SetText(BenillaScriptLog_RowText(row.message))
|
||||
button.label:SetText(BenillaScriptLog_RowText(message))
|
||||
button.label:SetTextColor(BenillaScriptLog_RowColor(kind))
|
||||
button:Show()
|
||||
if row.seq == BenillaScriptLogSelected then selectedRow = button end
|
||||
if seq == BenillaScriptLogSelected then selectedRow = button end
|
||||
else
|
||||
button.seq = nil
|
||||
button.message = nil
|
||||
@@ -127,16 +99,15 @@
|
||||
BenillaScriptLog_UpdateDetail()
|
||||
end
|
||||
|
||||
-- The selected message in full, traceback and all, in a box a player can select and copy
|
||||
-- from. A text that has not changed is left alone: `SetText` collapses the selection, so a
|
||||
-- new error arriving must not undo one about to be copied. A different text takes the
|
||||
-- keyboard from the box, as a click on another row does.
|
||||
-- The selected message in full, traceback and all.
|
||||
function BenillaScriptLog_UpdateDetail()
|
||||
local text = ""
|
||||
if BenillaScriptLogSelected then
|
||||
for _, row in ipairs(BenillaScriptLog.rows) do
|
||||
if row.seq == BenillaScriptLogSelected then
|
||||
text = row.message
|
||||
local shown = BenillaGetNumScriptErrors()
|
||||
for i = 1, shown do
|
||||
local seq, _, message = BenillaGetScriptErrorInfo(i)
|
||||
if seq == BenillaScriptLogSelected then
|
||||
text = message
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -144,24 +115,12 @@
|
||||
if text == "" then
|
||||
text = "Select a row above to read it in full."
|
||||
end
|
||||
local box = getglobal("BenillaScriptLogDetailText")
|
||||
if text ~= box.shown then
|
||||
box.shown = text
|
||||
box:ClearFocus()
|
||||
box:SetText(text)
|
||||
end
|
||||
getglobal("BenillaScriptLogDetailText"):SetText(text)
|
||||
end
|
||||
|
||||
-- The box is read-only: a player's edit is undone. The restore's own `SetText` raises
|
||||
-- another change, which finds the text equal and stops; `SetText` of an equal text does
|
||||
-- nothing. The selection an edit replaced is put back, so Ctrl+C still copies it all.
|
||||
function BenillaScriptLogDetail_OnTextChanged()
|
||||
local shown = this.shown or ""
|
||||
if this:GetText() ~= shown then
|
||||
this:SetText(shown)
|
||||
this:HighlightText()
|
||||
end
|
||||
ScrollingEdit_OnTextChanged(getglobal("BenillaScriptLogDetailScroll"))
|
||||
-- Text rects resolve after Lua runs, so the detail child is re-measured every frame.
|
||||
function BenillaScriptLogFrame_OnUpdate()
|
||||
BenillaScroll_ResizeChild("BenillaScriptLogDetailScroll", { "BenillaScriptLogDetailText" })
|
||||
end
|
||||
|
||||
function BenillaScriptLogRow_OnClick(button)
|
||||
@@ -174,7 +133,7 @@
|
||||
BenillaScriptLog_Update()
|
||||
end
|
||||
|
||||
function BenillaScriptLogFrame_OnLoad()
|
||||
function BenillaScriptLogFrame_OnLoad(self)
|
||||
-- Masks the square icon to the portrait ring.
|
||||
SetPortraitToTexture("BenillaScriptLogFramePortrait",
|
||||
"Interface\\Icons\\INV_Misc_Note_01")
|
||||
@@ -198,7 +157,7 @@
|
||||
|
||||
-- `/errors clear`: keeps the numbering, so a number never names two failures.
|
||||
function BenillaScriptLog_Clear()
|
||||
BenillaScriptLog.rows = {}
|
||||
BenillaClearScriptErrors()
|
||||
BenillaScriptLogSelected = nil
|
||||
if getglobal("BenillaScriptLogFrame"):IsVisible() then
|
||||
BenillaScriptLog_Update()
|
||||
@@ -225,16 +184,15 @@
|
||||
<HighlightTexture file="Interface\Buttons\UI-Listbox-Highlight2" alphaMode="ADD"/>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
this.index = getglobal(this:GetName() .. "Index")
|
||||
this.label = getglobal(this:GetName() .. "Label")
|
||||
self.index = getglobal(self:GetName() .. "Index")
|
||||
self.label = getglobal(self:GetName() .. "Label")
|
||||
</OnLoad>
|
||||
<OnClick>BenillaScriptLogRow_OnClick(this)</OnClick>
|
||||
<OnClick>BenillaScriptLogRow_OnClick(self)</OnClick>
|
||||
</Scripts>
|
||||
</Button>
|
||||
|
||||
<Frame name="BenillaScriptLogFrame" parent="UIParent" hidden="true">
|
||||
<!-- The standard left-slot panel size. No <Anchors>: ShowUIPanel seats it. Under UIParent,
|
||||
as the stock panels are, so it takes the UI scale with them. -->
|
||||
<Frame name="BenillaScriptLogFrame" hidden="true">
|
||||
<!-- The standard left-slot panel size. No <Anchors>: ShowUIPanel seats it. -->
|
||||
<Size><AbsDimension x="384" y="512"/></Size>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
@@ -274,9 +232,8 @@
|
||||
</Layer></Layers>
|
||||
</Frame>
|
||||
|
||||
<!-- The class trainer's first row (ClassTrainerSkill1, Blizzard_TrainerUI.xml:214-222). -->
|
||||
<Button name="BenillaScriptLogRow1" inherits="BenillaScriptLogRowTemplate">
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="22" y="-100"/></Offset></Anchor></Anchors>
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="22" y="-94"/></Offset></Anchor></Anchors>
|
||||
</Button>
|
||||
<Button name="BenillaScriptLogRow2" inherits="BenillaScriptLogRowTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="BenillaScriptLogRow1" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||||
<Button name="BenillaScriptLogRow3" inherits="BenillaScriptLogRowTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="BenillaScriptLogRow2" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||||
@@ -288,29 +245,28 @@
|
||||
<Button name="BenillaScriptLogRow9" inherits="BenillaScriptLogRowTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="BenillaScriptLogRow8" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||||
<Button name="BenillaScriptLogRow10" inherits="BenillaScriptLogRowTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="BenillaScriptLogRow9" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||||
<Button name="BenillaScriptLogRow11" inherits="BenillaScriptLogRowTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="BenillaScriptLogRow10" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||||
<Button name="BenillaScriptLogRow12" inherits="BenillaScriptLogRowTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="BenillaScriptLogRow11" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||||
<Button name="BenillaScriptLogRow13" inherits="BenillaScriptLogRowTemplate"><Anchors><Anchor point="TOPLEFT" relativeTo="BenillaScriptLogRow12" relativePoint="BOTTOMLEFT"/></Anchors></Button>
|
||||
|
||||
<!-- The class trainer's list frame (Blizzard_TrainerUI.xml:313-322, 184 tall as its .lua:471
|
||||
sets it). Only the faux kit's right-hand Slider renders. -->
|
||||
<!-- Only the faux kit's right-hand Slider renders. -->
|
||||
<ScrollFrame name="BenillaScriptLogListScrollFrame" inherits="FauxScrollFrameTemplate">
|
||||
<Size><AbsDimension x="296" y="184"/></Size>
|
||||
<Anchors><Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-67" y="-96"/></Offset></Anchor></Anchors>
|
||||
<Scripts>
|
||||
<Size><AbsDimension x="293" y="208"/></Size>
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="22" y="-94"/></Offset></Anchor></Anchors>
|
||||
<Scripts>
|
||||
<!-- The stock kit has no `updateFunc`, so the repaint is wired here. -->
|
||||
<OnVerticalScroll>FauxScrollFrame_OnVerticalScroll(BENILLA_SCRIPTLOG_ROW_HEIGHT, BenillaScriptLog_Update)</OnVerticalScroll>
|
||||
</Scripts>
|
||||
</ScrollFrame>
|
||||
</ScrollFrame>
|
||||
|
||||
<!-- The class trainer's detail pane, 8 under its list and 119 tall (Blizzard_TrainerUI.xml:
|
||||
346-356, .lua:472), so it ends above the buttons' sockets. The real-scroll kit: a
|
||||
message with its traceback has variable height. -->
|
||||
<!-- The real-scroll kit: a message with its traceback has variable height. -->
|
||||
<ScrollFrame name="BenillaScriptLogDetailScroll">
|
||||
<Size><AbsDimension x="296" y="119"/></Size>
|
||||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaScriptLogListScrollFrame" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-8"/></Offset></Anchor></Anchors>
|
||||
<Size><AbsDimension x="293" y="128"/></Size>
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="22" y="-314"/></Offset></Anchor></Anchors>
|
||||
<Scripts>
|
||||
<OnLoad>this:SetScrollChild(getglobal(this:GetName() .. "Child"))</OnLoad>
|
||||
<OnMouseWheel>BenillaScroll_OnMouseWheel(this, arg1)</OnMouseWheel>
|
||||
<OnVerticalScroll>BenillaScroll_SyncBar(this)</OnVerticalScroll>
|
||||
<OnScrollRangeChanged>BenillaScroll_SyncBar(this)</OnScrollRangeChanged>
|
||||
<OnLoad>self:SetScrollChild(getglobal(self:GetName() .. "Child"))</OnLoad>
|
||||
<OnMouseWheel>BenillaScroll_OnMouseWheel(self, arg1)</OnMouseWheel>
|
||||
<OnVerticalScroll>BenillaScroll_SyncBar(self)</OnVerticalScroll>
|
||||
<OnScrollRangeChanged>BenillaScroll_SyncBar(self)</OnScrollRangeChanged>
|
||||
</Scripts>
|
||||
<Frames>
|
||||
<Slider name="$parentBar" inherits="BenillaScrollBarTemplate" hidden="true">
|
||||
@@ -318,82 +274,64 @@
|
||||
<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>
|
||||
<Scripts><OnValueChanged>BenillaScrollBar_OnValueChanged(self, arg1)</OnValueChanged></Scripts>
|
||||
</Slider>
|
||||
<!-- Mouse-enabled and the pane's full height, as SendMailScrollChildFrame is
|
||||
(MailFrame.xml:604-659): a click below the text focuses the box. -->
|
||||
<Frame name="$parentChild" enableMouse="true">
|
||||
<Size><AbsDimension x="296" y="119"/></Size>
|
||||
<Frame name="$parentChild">
|
||||
<Size><AbsDimension x="293" y="128"/></Size>
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||||
<Frames>
|
||||
<!-- A multi-line box in a scroll frame as MailFrame.xml:616-649 hosts the mail
|
||||
body: `autoFocus="false"`, so the keyboard stays with the game until a
|
||||
click, and Escape clears the focus. A multi-line box is as tall as its
|
||||
insets and its wrapped text, so the scroll frame ranges over it as
|
||||
ScrollingEdit_OnTextChanged (UIPanelTemplates.lua:307) recomputes. The
|
||||
insets seat the text 6 in and 6 down, 270 wide, and leave 20 below
|
||||
the last line. No `letters`, so the whole error goes in. Read-only
|
||||
through OnTextChanged; a click selects it all, so Ctrl+C copies the
|
||||
error. Not wired: the stock scroll-to-caret (UIPanelTemplates.lua:
|
||||
314-342), since selecting all leaves the caret at the end and a
|
||||
click would scroll a long traceback to its bottom. -->
|
||||
<EditBox name="BenillaScriptLogDetailText" multiLine="true" autoFocus="false">
|
||||
<Size><AbsDimension x="296" y="119"/></Size>
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||||
<TextInsets><AbsInset left="6" right="20" top="6" bottom="20"/></TextInsets>
|
||||
<Scripts>
|
||||
<OnTextChanged>BenillaScriptLogDetail_OnTextChanged()</OnTextChanged>
|
||||
<OnEditFocusGained>this:HighlightText()</OnEditFocusGained>
|
||||
<OnEscapePressed>this:ClearFocus()</OnEscapePressed>
|
||||
</Scripts>
|
||||
<FontString inherits="GameFontHighlightSmall"/>
|
||||
</EditBox>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnMouseUp>BenillaScriptLogDetailText:SetFocus()</OnMouseUp>
|
||||
</Scripts>
|
||||
<Layers>
|
||||
<Layer level="ARTWORK">
|
||||
<!-- 270 wide so the traceback wraps rather than clips. -->
|
||||
<FontString name="BenillaScriptLogDetailText" inherits="GameFontHighlightSmall" justifyH="LEFT" justifyV="TOP" text="">
|
||||
<Size><AbsDimension x="270" y="0"/></Size>
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="6" y="-6"/></Offset></Anchor></Anchors>
|
||||
</FontString>
|
||||
</Layer>
|
||||
</Layers>
|
||||
</Frame>
|
||||
</Frames>
|
||||
</ScrollFrame>
|
||||
|
||||
<!-- The art's two button sockets, where the class trainer's Train and Exit sit
|
||||
(Blizzard_TrainerUI.xml:481-513). -->
|
||||
<Button name="BenillaScriptLogClearButton" inherits="UIPanelButtonTemplate" text="Clear">
|
||||
<Size><AbsDimension x="80" y="22"/></Size>
|
||||
<Anchors><Anchor point="CENTER" relativePoint="TOPLEFT"><Offset><AbsDimension x="224" y="-420"/></Offset></Anchor></Anchors>
|
||||
<Size><AbsDimension x="96" y="22"/></Size>
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="22" y="-455"/></Offset></Anchor></Anchors>
|
||||
<Scripts><OnClick>BenillaScriptLog_Clear()</OnClick></Scripts>
|
||||
</Button>
|
||||
<Button name="BenillaScriptLogCloseBottomButton" inherits="UIPanelButtonTemplate" text="Close">
|
||||
<Size><AbsDimension x="80" y="22"/></Size>
|
||||
<Anchors><Anchor point="CENTER" relativePoint="TOPLEFT"><Offset><AbsDimension x="305" y="-420"/></Offset></Anchor></Anchors>
|
||||
<Size><AbsDimension x="96" y="22"/></Size>
|
||||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="219" y="-455"/></Offset></Anchor></Anchors>
|
||||
<Scripts><OnClick>HideUIPanel(getglobal("BenillaScriptLogFrame"))</OnClick></Scripts>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnLoad>BenillaScriptLogFrame_OnLoad()</OnLoad>
|
||||
<OnLoad>BenillaScriptLogFrame_OnLoad(self)</OnLoad>
|
||||
<!-- A spin bubbles up the parent chain; the detail pane's own handler wins there. -->
|
||||
<OnMouseWheel>BenillaScriptLogFrame_OnMouseWheel(arg1)</OnMouseWheel>
|
||||
<OnShow>BenillaScriptLog_Update()</OnShow>
|
||||
<OnUpdate>BenillaScriptLogFrame_OnUpdate()</OnUpdate>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
<!-- The player's commands, as an addon registers them; after the stock ChatFrame.lua, which
|
||||
declares SlashCmdList. -->
|
||||
<!-- Benilla's slash commands, handed to SubmitChatInput (ui_chat::input); loads after the
|
||||
stock ChatFrame.xml, which declares SlashCmdList. -->
|
||||
<Script><![CDATA[
|
||||
-- Deviation: 1.12 has no `/reload` (later clients added it; 1.12 reloads through
|
||||
-- `/console reloadui`); kept so a player can reload the interface after toggling addons.
|
||||
SLASH_BENILLA_RELOAD1 = "/reload"
|
||||
SlashCmdList["BENILLA_RELOAD"] = function()
|
||||
ReloadUI()
|
||||
end
|
||||
|
||||
-- `/errors` toggles the log and `/errors clear` empties it; `/err` is the short form.
|
||||
SLASH_BENILLA_ERRORS1 = "/errors"
|
||||
SLASH_BENILLA_ERRORS2 = "/err"
|
||||
SlashCmdList["BENILLA_ERRORS"] = function(msg)
|
||||
local arg = string.lower((string.gsub(msg or "", "^%s*(.-)%s*$", "%1")))
|
||||
if arg == "clear" then
|
||||
BenillaScriptLog_Clear()
|
||||
else
|
||||
BenillaScriptLog_Toggle()
|
||||
local BENILLA_COMMANDS = {
|
||||
{ "CHATTEST", "/chattest" },
|
||||
{ "SHOT", "/shot" },
|
||||
{ "LIQUID", "/liquid" },
|
||||
{ "CASTVIS", "/castvis" },
|
||||
{ "PARTYTEST", "/partytest" },
|
||||
{ "REACTION", "/reaction", "/react" },
|
||||
{ "RELOAD", "/reload" },
|
||||
{ "ERRORS", "/errors", "/err" },
|
||||
{ "CONVERTRAID", "/convertraid" },
|
||||
}
|
||||
for _, row in ipairs(BENILLA_COMMANDS) do
|
||||
local key = "BENILLA_" .. row[1]
|
||||
for i = 2, table.getn(row) do
|
||||
setglobal("SLASH_" .. key .. (i - 1), row[i])
|
||||
end
|
||||
SlashCmdList[key] = function(msg)
|
||||
SubmitChatInput(row[2] .. " " .. (msg or ""))
|
||||
end
|
||||
end
|
||||
]]></Script>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
Benilla's scroll parts: a `Slider` bar with its arrow helpers, an optional trough, and a
|
||||
real-scroll kit that pans a `<ScrollFrame>` child whose height is known only after layout.
|
||||
Faux lists use the stock `FauxScrollFrameTemplate`; this file declares only `Benilla` names.
|
||||
The bar template carries the real-scroll OnValueChanged itself, as the reference's
|
||||
`UIPanelScrollBarTemplate` does (UIPanelTemplates.xml:156-158); an instance adds nothing.
|
||||
A real-scroll bar overrides the template's OnValueChanged on its instance, which wins
|
||||
because the loader runs every `<Scripts>` block in order.
|
||||
-->
|
||||
<Script><![CDATA[
|
||||
-- One valueStep per step, where the reference's arrows and wheel move half the bar
|
||||
@@ -26,6 +26,23 @@
|
||||
if val >= maxV then down:Disable() else down:Enable() end
|
||||
end
|
||||
|
||||
-- The value is pixels in steps of a row; the parent holds the 0-based top row in
|
||||
-- `frame.offset` and its repaint in `frame.updateFunc`, which runs only when that row
|
||||
-- changes, so a repaint that re-seats the thumb ends the loop. A ScrollFrame parent also
|
||||
-- gets SetVerticalScroll, as UIPanelTemplates.xml:156-158 routes it.
|
||||
function BenillaFauxScrollBar_OnValueChanged(scrollBar, value)
|
||||
local frame = scrollBar:GetParent()
|
||||
local step = scrollBar:GetValueStep()
|
||||
if step <= 0 then step = 1 end
|
||||
local newOffset = floor(value / step + 0.5)
|
||||
if newOffset ~= frame.offset then
|
||||
frame.offset = newOffset
|
||||
if frame.updateFunc then frame.updateFunc() end
|
||||
end
|
||||
BenillaScrollBar_UpdateArrows(scrollBar)
|
||||
if frame.SetVerticalScroll then frame:SetVerticalScroll(value) end
|
||||
end
|
||||
|
||||
-- ReputationFrame's hang, 8 left, 21 above, 20 below (ReputationFrame.xml:573-599 against
|
||||
-- UIPanelTemplates.xml:166-181). Lazy: the bar does not exist at the trough's OnLoad.
|
||||
function BenillaScrollTrough_Seat(trough, scrollBar)
|
||||
@@ -79,18 +96,11 @@
|
||||
BenillaScrollBar_UpdateArrows(bar)
|
||||
end
|
||||
|
||||
-- The range the bar follows: the engine's, the reference's union of the child's whole
|
||||
-- subtree, unless the frame measures its own content (`sf.contentRange`).
|
||||
function BenillaScroll_Range(sf)
|
||||
if sf.contentRange then return sf.contentRange(sf) end
|
||||
return sf:GetVerticalScrollRange()
|
||||
end
|
||||
|
||||
-- Hides the bar when the content fits (reference: ScrollFrame_OnScrollRangeChanged).
|
||||
function BenillaScroll_SyncBar(sf)
|
||||
local bar = getglobal(sf:GetName() .. "Bar")
|
||||
if not bar then return end
|
||||
local range = BenillaScroll_Range(sf)
|
||||
local range = sf:GetVerticalScrollRange()
|
||||
bar:SetValueStep(BENILLA_SCROLL_STEP)
|
||||
bar:SetMinMaxValues(0, range)
|
||||
bar:SetValue(sf:GetVerticalScroll())
|
||||
@@ -101,7 +111,7 @@
|
||||
-- Clamped here: SetVerticalScroll stores any value, as the reference's does.
|
||||
function BenillaScroll_Step(sf, delta)
|
||||
local target = sf:GetVerticalScroll() + delta
|
||||
local range = BenillaScroll_Range(sf)
|
||||
local range = sf:GetVerticalScrollRange()
|
||||
if target > range then target = range end
|
||||
if target < 0 then target = 0 end
|
||||
sf:SetVerticalScroll(target)
|
||||
@@ -173,7 +183,7 @@
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnValueChanged>BenillaScrollBar_OnValueChanged(this, arg1)</OnValueChanged>
|
||||
<OnValueChanged>BenillaFauxScrollBar_OnValueChanged(self, arg1)</OnValueChanged>
|
||||
</Scripts>
|
||||
<ThumbTexture name="$parentThumbTexture" file="Interface\Buttons\UI-ScrollBar-Knob">
|
||||
<Size><AbsDimension x="16" y="16"/></Size>
|
||||
|
||||
@@ -171,57 +171,3 @@ fn the_corpus_favourite_template_composes_parent_two_levels_deep() {
|
||||
assert!(s.take_errors().is_empty());
|
||||
assert_eq!(s.take_warnings(), Vec::<String>::new());
|
||||
}
|
||||
|
||||
/// `BenillaScrollBarTemplate` carries the real-scroll `OnValueChanged` itself, as
|
||||
/// `UIPanelScrollBarTemplate` does (`UIPanelTemplates.xml:156-158`): a bare instance, with no
|
||||
/// handler of its own, pans its `ScrollFrame` parent and greys the arrow at the range's end.
|
||||
#[test]
|
||||
fn the_benilla_scroll_bar_template_scrolls_its_parent_by_itself() {
|
||||
let _data = benilla_formats::wow_data_or_skip!();
|
||||
let mut s = UiScript::new().unwrap();
|
||||
s.set_screen_size(1024.0, 768.0);
|
||||
load_ui(&s);
|
||||
let _ = s.take_warnings();
|
||||
let _ = s.take_errors();
|
||||
|
||||
s.run(
|
||||
r#"
|
||||
BarHost = CreateFrame("ScrollFrame", "BenillaTemplateProbeHost", UIParent)
|
||||
BarHost.updateFunc = function() UpdateCalls = (UpdateCalls or 0) + 1 end
|
||||
Bar = CreateFrame("Slider", "BenillaTemplateProbeBar", BarHost, "BenillaScrollBarTemplate")
|
||||
Bar:SetMinMaxValues(0, 100)
|
||||
Bar:SetValueStep(20)
|
||||
Bar:SetValue(40)
|
||||
"#,
|
||||
)
|
||||
.expect("a bare instance of the bar template must not error");
|
||||
|
||||
assert_eq!(
|
||||
s.eval::<f32>("return BarHost:GetVerticalScroll()").unwrap(),
|
||||
40.0,
|
||||
"the template's own OnValueChanged scrolls the parent"
|
||||
);
|
||||
assert!(
|
||||
s.eval::<bool>("return BarHost.offset == nil and UpdateCalls == nil")
|
||||
.unwrap(),
|
||||
"a scroll is not a faux list's `offset`/`updateFunc` write on the parent"
|
||||
);
|
||||
assert!(
|
||||
s.eval::<bool>(r#"return BenillaTemplateProbeBarScrollDownButton:IsEnabled() == 1"#)
|
||||
.unwrap(),
|
||||
"mid-range, the down arrow is live"
|
||||
);
|
||||
s.run("Bar:SetValue(100)").unwrap();
|
||||
assert_eq!(
|
||||
s.eval::<f32>("return BarHost:GetVerticalScroll()").unwrap(),
|
||||
100.0
|
||||
);
|
||||
assert!(
|
||||
s.eval::<bool>(r#"return BenillaTemplateProbeBarScrollDownButton:IsEnabled() ~= 1"#)
|
||||
.unwrap(),
|
||||
"at the end of the range the down arrow greys"
|
||||
);
|
||||
|
||||
assert!(s.take_errors().is_empty());
|
||||
assert_eq!(s.take_warnings(), Vec::<String>::new());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user