Its readers were our own ActionBar and group-loot files, and both were retired when those windows moved to the stock FrameXML. The stock files leave a missing texture empty. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
282 lines
16 KiB
XML
282 lines
16 KiB
XML
<Ui>
|
|
<!--
|
|
Benilla's scroll kits, sharing one `Slider` bar, its arrow helpers and an optional trough:
|
|
a faux-scroll kit that re-binds a fixed set of rows to a moving data offset, and a
|
|
real-scroll kit that pans and clips a `<ScrollFrame>` child whose height is known only after
|
|
layout. A real-scroll bar overrides the template's OnValueChanged on its instance, which
|
|
wins because the loader runs every `<Scripts>` block in order.
|
|
Faux model: the value is pixels, `[0, (numItems - numToDisplay) * itemHeight]` in steps of
|
|
`itemHeight`; the parent holds the 0-based top row in `frame.offset` and its repaint in
|
|
`frame.updateFunc`, set by the owner's OnLoad.
|
|
Deviation: the faux parent is a plain `<Frame>`, not the reference's ScrollFrame relay,
|
|
which adds nothing because the reference's `SetVerticalScroll` stores the bar's value as is.
|
|
`FauxScrollFrameTemplate` and the `FauxScrollFrame_*`, `ScrollFrame_*` and
|
|
`ScrollingEdit_*` API are the stock `UIPanelTemplates` on the player's chain, which loads
|
|
after this file, so its declarations win.
|
|
-->
|
|
<Script><![CDATA[
|
|
-- Steps the bar by its valueStep. Deviation: one row on a faux list, where the reference
|
|
-- bar's arrows step half its height. Soundless: the reference plays UChatScrollButton on
|
|
-- an arrow click, never on the wheel, so the arrows' OnClick plays it.
|
|
function BenillaScrollBar_Step(scrollBar, dir)
|
|
local step = scrollBar:GetValueStep()
|
|
if step <= 0 then step = 1 end
|
|
scrollBar:SetValue(scrollBar:GetValue() + dir * step)
|
|
end
|
|
|
|
-- Greys each arrow at its end of the range (reference: ScrollFrame_OnScrollRangeChanged).
|
|
function BenillaScrollBar_UpdateArrows(scrollBar)
|
|
local minV, maxV = scrollBar:GetMinMaxValues()
|
|
local val = scrollBar:GetValue()
|
|
local up = getglobal(scrollBar:GetName() .. "ScrollUpButton")
|
|
local down = getglobal(scrollBar:GetName() .. "ScrollDownButton")
|
|
if val <= minV then up:Disable() else up:Enable() end
|
|
if val >= maxV then down:Disable() else down:Enable() end
|
|
end
|
|
|
|
-- The faux bar's OnValueChanged: the top row is the value rounded to the nearest row, so
|
|
-- thumb and rows agree, and `updateFunc` runs only when that row changes, which also ends
|
|
-- the loop when a repaint re-seats the thumb.
|
|
-- A ScrollFrame parent also gets the value through SetVerticalScroll, as the reference's
|
|
-- `UIPanelScrollBarTemplate` routes it (UIPanelTemplates.xml l.156-158).
|
|
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
|
|
|
|
-- Seats a trough on its bar with the reference's ReputationFrame hang, 8 left, 21 above and
|
|
-- 20 below (ReputationFrame.xml l.573-599 against UIPanelTemplates.xml l.166-181), which
|
|
-- puts each art socket on its arrow button. Lazy, because the bar is declared after its
|
|
-- trough and does not exist at the trough's OnLoad.
|
|
function BenillaScrollTrough_Seat(trough, scrollBar)
|
|
if trough.seated then return end
|
|
trough.seated = true
|
|
trough:ClearAllPoints()
|
|
trough:SetPoint("TOPLEFT", scrollBar, "TOPLEFT", -8, 21)
|
|
trough:SetPoint("BOTTOMRIGHT", scrollBar, "BOTTOMRIGHT", 7, -20)
|
|
end
|
|
|
|
-- Shows or hides a bar and its `<barname>Trough` together, seating the trough first; show
|
|
-- and hide a bar only through here. The trough is opt-in because 1.12 draws trough art per
|
|
-- window: `UIPanelScrollBarTemplate` carries only the arrows and the knob.
|
|
function BenillaScrollBar_SetShown(scrollBar, shown)
|
|
local trough = getglobal(scrollBar:GetName() .. "Trough")
|
|
if trough then BenillaScrollTrough_Seat(trough, scrollBar) end
|
|
if shown then
|
|
scrollBar:Show()
|
|
if trough then trough:Show() end
|
|
else
|
|
scrollBar:Hide()
|
|
if trough then trough:Hide() end
|
|
end
|
|
end
|
|
|
|
-- The same for a stock `FauxScrollFrameTemplate` frame, whose bar is the reference's: seats
|
|
-- `<frame>ScrollBarTrough` and mirrors the frame's shown state. Call it after
|
|
-- `FauxScrollFrame_Update`, which shows or hides the frame.
|
|
function BenillaScrollTrough_Follow(scrollFrameName)
|
|
local sf = getglobal(scrollFrameName)
|
|
if not sf then return end
|
|
local bar = getglobal(scrollFrameName .. "ScrollBar")
|
|
if not bar then return end
|
|
local trough = getglobal(bar:GetName() .. "Trough")
|
|
if not trough then return end
|
|
BenillaScrollTrough_Seat(trough, bar)
|
|
if sf:IsShown() then trough:Show() else trough:Hide() end
|
|
end
|
|
|
|
-- One row per wheel notch (+1 up) on a faux list, called from the owner window's
|
|
-- OnMouseWheel since the spin bubbles up the parent chain. Benilla-named: the reference has
|
|
-- no faux wheel function (its `ScrollFrameTemplate_OnMouseWheel` moves half the bar).
|
|
function BenillaFauxScrollFrame_OnMouseWheel(frame, delta)
|
|
local scrollBar = getglobal(frame:GetName() .. "ScrollBar")
|
|
BenillaScrollBar_Step(scrollBar, -delta)
|
|
end
|
|
|
|
-- ══════════════════════════ The real-scroll kit ══════════════════════════════════════════
|
|
-- Shaped on the reference `UIPanelScrollFrameTemplate` (UIPanelTemplates.xml l.166-211):
|
|
-- the bar is a `Slider` child, `$parentBar`, so `bar:GetParent()` is the frame it pans.
|
|
BENILLA_SCROLL_STEP = 20 -- px per arrow click or wheel notch
|
|
BENILLA_SCROLL_PAD = 20 -- px of room below the child's last element
|
|
|
|
-- Pans the frame the bar rides. The loop back through OnVerticalScroll and SyncBar ends in
|
|
-- one hop: SyncBar writes the value the bar already holds, which Slider:SetValue ignores.
|
|
function BenillaScrollBar_OnValueChanged(bar, value)
|
|
bar:GetParent():SetVerticalScroll(value)
|
|
BenillaScrollBar_UpdateArrows(bar)
|
|
end
|
|
|
|
-- Fits the bar to the frame's live range, [0, range] px, and hides it when the content fits
|
|
-- (reference: ScrollFrame_OnScrollRangeChanged). Owners call it from OnScrollRangeChanged
|
|
-- and OnVerticalScroll.
|
|
function BenillaScroll_SyncBar(sf)
|
|
local bar = getglobal(sf:GetName() .. "Bar")
|
|
if not bar then return end
|
|
local range = sf:GetVerticalScrollRange()
|
|
bar:SetValueStep(BENILLA_SCROLL_STEP)
|
|
bar:SetMinMaxValues(0, range)
|
|
bar:SetValue(sf:GetVerticalScroll())
|
|
BenillaScrollBar_UpdateArrows(bar)
|
|
BenillaScrollBar_SetShown(bar, range > 0)
|
|
end
|
|
|
|
-- Pans by `delta` px, clamped here: SetVerticalScroll stores any value, as the reference's
|
|
-- does; the reference's ScrollFrameTemplate_OnMouseWheel clamps through its bar's range.
|
|
function BenillaScroll_Step(sf, delta)
|
|
local target = sf:GetVerticalScroll() + delta
|
|
local range = sf:GetVerticalScrollRange()
|
|
if target > range then target = range end
|
|
if target < 0 then target = 0 end
|
|
sf:SetVerticalScroll(target)
|
|
BenillaScroll_SyncBar(sf)
|
|
end
|
|
|
|
-- The wheel's delta is +1 per notch up, and up scrolls toward the top.
|
|
function BenillaScroll_OnMouseWheel(sf, delta)
|
|
BenillaScroll_Step(sf, -delta * BENILLA_SCROLL_STEP)
|
|
end
|
|
|
|
-- A widget's resolved bottom, or nil if hidden, a blank FontString, or not laid out yet.
|
|
function BenillaScroll_WidgetBottom(w)
|
|
if not w then return nil end
|
|
if w.IsShown then
|
|
if not w:IsShown() then return nil end
|
|
elseif w.GetText then
|
|
local t = w:GetText()
|
|
if not t or t == "" then return nil end
|
|
end
|
|
return w:GetBottom()
|
|
end
|
|
|
|
-- Sizes the scroll child to its lowest visible widget plus BENILLA_SCROLL_PAD and updates
|
|
-- the frame's range. Rects resolve after Lua runs, so owners re-run it from OnUpdate until
|
|
-- it returns false; it writes only on a real change, since SetHeight invalidates layout.
|
|
function BenillaScroll_ResizeChild(scrollName, widgets)
|
|
local sf = getglobal(scrollName)
|
|
-- The frame's own child, not a derived name: the reference pairs `<X>ScrollFrame` with
|
|
-- `<X>ScrollChildFrame`.
|
|
local child = sf:GetScrollChild()
|
|
if not child then return false end
|
|
local top = child:GetTop()
|
|
if not top then return false end
|
|
local bottom = nil
|
|
for i = 1, table.getn(widgets) do
|
|
local b = BenillaScroll_WidgetBottom(getglobal(widgets[i]))
|
|
if b and (not bottom or b < bottom) then bottom = b end
|
|
end
|
|
local height = 1
|
|
if bottom then height = (top - bottom) + BENILLA_SCROLL_PAD end
|
|
if height < 1 then height = 1 end
|
|
if math.abs(child:GetHeight() - height) < 1 then return false end
|
|
child:SetHeight(height)
|
|
sf:UpdateScrollChildRect()
|
|
return true
|
|
end
|
|
]]></Script>
|
|
|
|
<!--
|
|
The bar: a 16px `Slider` with step buttons above and below the track, on the stock 1.12
|
|
scrollbar art cropped to its centred 16px (the `0.25..0.75` TexCoords of the reference's
|
|
`UIPanelScrollBarButton`).
|
|
-->
|
|
<Slider name="BenillaScrollBarTemplate" virtual="true">
|
|
<Size><AbsDimension x="16" y="0"/></Size>
|
|
<Frames>
|
|
<Button name="$parentScrollUpButton">
|
|
<Size><AbsDimension x="16" y="16"/></Size>
|
|
<Anchors><Anchor point="BOTTOM" relativePoint="TOP"/></Anchors>
|
|
<NormalTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Up"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></NormalTexture>
|
|
<PushedTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Down"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></PushedTexture>
|
|
<DisabledTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Disabled"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></DisabledTexture>
|
|
<HighlightTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Highlight" alphaMode="ADD"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></HighlightTexture>
|
|
<Scripts><OnClick>BenillaScrollBar_Step(this:GetParent(), -1); PlaySound("UChatScrollButton")</OnClick></Scripts>
|
|
</Button>
|
|
<Button name="$parentScrollDownButton">
|
|
<Size><AbsDimension x="16" y="16"/></Size>
|
|
<Anchors><Anchor point="TOP" relativePoint="BOTTOM"/></Anchors>
|
|
<NormalTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Up"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></NormalTexture>
|
|
<PushedTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Down"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></PushedTexture>
|
|
<DisabledTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Disabled"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></DisabledTexture>
|
|
<HighlightTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Highlight" alphaMode="ADD"><TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/></HighlightTexture>
|
|
<Scripts><OnClick>BenillaScrollBar_Step(this:GetParent(), 1); PlaySound("UChatScrollButton")</OnClick></Scripts>
|
|
</Button>
|
|
</Frames>
|
|
<Scripts>
|
|
<OnValueChanged>BenillaFauxScrollBar_OnValueChanged(self, arg1)</OnValueChanged>
|
|
</Scripts>
|
|
<ThumbTexture name="$parentThumbTexture" 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>
|
|
|
|
<!--
|
|
A bar's trough, the recessed channel it rides in; the reference's scroll kit has none.
|
|
Declare it before its bar, so it draws beneath, named `<barname>Trough` and with no
|
|
anchors: BenillaScrollTrough_Seat seats it on the bar.
|
|
`UI-Character-ScrollBar` (64x256) holds two 31-wide channel pieces, the left column
|
|
(u 0 .. 31/64) capped at the top and the right (u 33/64 .. 1) at the bottom, each with a
|
|
16-tall socket for its arrow button: rows 4-19 at the top, rows 87-102 at the bottom.
|
|
Deviation: cut as a three-slice (both socket ends at natural height, the plain channel
|
|
stretched between) where the reference overlaps two quads, since two quads reach only 362
|
|
units and a page here is 563 tall.
|
|
The black fill is the reference's trough backing (ItemTextFrame's 0.8-alpha `Middle`). It
|
|
is in BACKGROUND and the art in BORDER because the client orders overlapping quads within
|
|
one layer by texture handle; the bar's buttons (ARTWORK) and knob (OVERLAY) draw above both.
|
|
-->
|
|
<Frame name="BenillaScrollTroughTemplate" virtual="true" hidden="true">
|
|
<Size><AbsDimension x="31"/></Size>
|
|
<Layers>
|
|
<Layer level="BACKGROUND">
|
|
<!-- The channel interior: x 6..24 of the 31-wide piece, inset 6 from each edge. -->
|
|
<Texture name="$parentFill">
|
|
<Anchors>
|
|
<Anchor point="TOPLEFT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor>
|
|
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-6" y="0"/></Offset></Anchor>
|
|
</Anchors>
|
|
<Color r="0" g="0" b="0" a="0.8"/>
|
|
</Texture>
|
|
</Layer>
|
|
<Layer level="BORDER">
|
|
<!-- Cap + up-arrow socket + crossbar: left column, rows 0..22 (v 0 .. 23/256). -->
|
|
<Texture name="$parentTop" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
|
<Size><AbsDimension y="23"/></Size>
|
|
<Anchors>
|
|
<Anchor point="TOPLEFT"/>
|
|
<Anchor point="TOPRIGHT"/>
|
|
</Anchors>
|
|
<TexCoords left="0" right="0.484375" top="0" bottom="0.08984375"/>
|
|
</Texture>
|
|
<!-- Crossbar + down-arrow socket + cap: right column, rows 82..107
|
|
(v 82/256 .. 108/256), ending on v 0.421875 as ReputationFrame's does. -->
|
|
<Texture name="$parentBottom" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
|
<Size><AbsDimension y="26"/></Size>
|
|
<Anchors>
|
|
<Anchor point="BOTTOMLEFT"/>
|
|
<Anchor point="BOTTOMRIGHT"/>
|
|
</Anchors>
|
|
<TexCoords left="0.515625" right="1.0" top="0.3203125" bottom="0.421875"/>
|
|
</Texture>
|
|
<!-- The stretched run between them: left column rows 30..70, plain rails only.
|
|
Declared last: an anchor to a later sibling falls back to the parent. -->
|
|
<Texture name="$parentMiddle" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
|
<Anchors>
|
|
<Anchor point="TOPLEFT" relativeTo="$parentTop" relativePoint="BOTTOMLEFT"/>
|
|
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBottom" relativePoint="TOPRIGHT"/>
|
|
</Anchors>
|
|
<TexCoords left="0" right="0.484375" top="0.1171875" bottom="0.2734375"/>
|
|
</Texture>
|
|
</Layer>
|
|
</Layers>
|
|
</Frame>
|
|
|
|
</Ui>
|