fix(ui): Options panel Config tab content escapes the window frame — stale viewport anchor capture, not a missing clip
The Config tab's footer sat mid-panel with further rows drawing below the window's bottom edge. Live-DAT measured: the mounted tab-host root is authored 300x362 (retail's real default window size), but the Config page slot underneath keeps its own larger design geometry (298x575 against a 300x600 canvas) until retail's real four-edge UiLayoutPolicy (UIElement::UpdateForParentSizeChange @0x00462640) shrinks it on the first ApplyAnchor pass -- verified stable, this part already worked. The actual bug: UiTemplateListBox.Viewport (the UiScrollablePanel that hosts + clips every row) is a programmatic C# element seeded at Bind time, BEFORE the tree's first draw frame -- before the ListBox has ever shrunk. Its legacy anchor baseline is captured lazily on its own first ApplyAnchor call, which lands AFTER the ListBox has already shrunk earlier in that same frame (parent-before-child draw order). That capture measures a negative bottom margin the stretch math preserves forever: the viewport stayed locked at its original 560px design height, clipping rows to a bound retail never actually gave the window on screen. Fix: force the viewport's anchor capture to happen immediately after seeding it, while its Width/Height still exactly equal a zero-margin baseline against the CURRENT (pre-shrink) parent, instead of lazily on the first draw frame against an already-shrunk parent. This is #372's sequel -- #372 fixed the 0x0 collapse case; this is the "ListBox itself later shrinks" case #372's own fixture never exercised. Three new tests (UiTemplateListBoxViewportTests using the live-DAT-measured 298x575/276x560 numbers, plus two ConfigOptionsPageControllerTests against the real production Bind path and the committed host fixture) all fail pre-fix, confirmed by temporarily reverting the change. Scoped to UiTemplateListBox's own viewport; UiScrollablePanel/ApplyAnchor/ ComputeAnchoredRect are untouched, so chat's transcript scrolling and every other UiScrollablePanel/UiItemList consumer are unaffected. fix #412 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
97a7be12ee
commit
c623b57ad3
4 changed files with 310 additions and 0 deletions
|
|
@ -177,6 +177,42 @@ public sealed class UiTemplateListBox : UiDatElement
|
|||
Height = Height,
|
||||
};
|
||||
base.AddChild(_viewport);
|
||||
|
||||
// #412-class fix (2026-08-16, overnight hover/UI round, Batch A bug 2):
|
||||
// #372's seed above only fixed the 0×0 collapse for a ListBox whose OWN
|
||||
// size never changes after the viewport is created. It does NOT hold for
|
||||
// the Options panel's real mount: this ListBox (0x10000200 etc.) is a
|
||||
// DAT-imported element carrying its own retail four-edge UiLayoutPolicy
|
||||
// (UIElement::UpdateForParentSizeChange @0x00462640), and a page
|
||||
// controller's Bind (which lazily creates this viewport, calling
|
||||
// AddItemFromTemplateList) runs BEFORE the tree's first real draw frame —
|
||||
// i.e. before ANY ApplyAnchor pass has ever run. The Options tab-host's
|
||||
// page slot (298×575 authored) is taller than its actual 300×362 mounted
|
||||
// container, so on the FIRST draw frame the slot's LayoutPolicy shrinks
|
||||
// it top-down (e.g. to ~298×337), and THIS ListBox — also LayoutPolicy-
|
||||
// driven, recomputed fresh every call, no capture-staleness of its own —
|
||||
// shrinks right behind it (e.g. to ~282×297) in the SAME frame, BEFORE
|
||||
// its per-child loop ever reaches the viewport below it. The viewport
|
||||
// above was seeded at BIND time against the ListBox's PRE-shrink size
|
||||
// (276×560) but its own legacy Left|Top|Right|Bottom anchor baseline is
|
||||
// only CAPTURED lazily, on ITS first ApplyAnchor call — which lands AFTER
|
||||
// the ListBox has already shrunk in that same frame. That capture then
|
||||
// measures a NEGATIVE bottom margin (parentH(297) - (0+560) = -263) which
|
||||
// ComputeAnchoredRect's stretch math preserves forever (h = parentH - mB -
|
||||
// mT = 297 - (-263) - 0 = 560): the viewport is permanently locked at its
|
||||
// ORIGINAL oversized height, clipping its rows to a bound retail never
|
||||
// actually gave it on screen. Every row past the real ~297px stays
|
||||
// "visible" per LayoutScrollableChildren's cull test and paints straight
|
||||
// through the footer and past the window's real bottom edge — the exact
|
||||
// "dozens of rows below the window frame" symptom (#412-class report:
|
||||
// Full Screen/Sync/Screen Brightness/Adaptive Degrade/quality dropdowns
|
||||
// drawing outside the panel). Forcing the capture to happen NOW, while
|
||||
// Width/Height still exactly equal the ListBox's CURRENT (pre-shrink, but
|
||||
// zero-margin) size, makes the captured margins (0,0,0,0) instead of
|
||||
// negative — ComputeAnchoredRect then tracks whatever height the ListBox
|
||||
// ACTUALLY ends up at after its own LayoutPolicy runs, on every frame
|
||||
// after this one, exactly like #372 intended.
|
||||
_viewport.CaptureCurrentAnchorBaseline();
|
||||
}
|
||||
return _viewport;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue