fix #385: Options dropdowns — white centered text + size-to-content popup
User gate report (Campaign OP happy-testing round, 2026-08-13): every Config-tab dropdown drew its text gold + left-aligned and its popup a fixed 6 rows regardless of item count. All three were unmeasured styling divergences — the authored data (new probe menuprobe3, live DAT) says: - button label child 0x10000355: fontColor white, hJustify=Center - row template 0x1000035A: fontColor white, hJustify=Center - popup ListBox 0x10000358: edge-docked L=T=R=B=1, the authored condition arming retail UIElement_Menu::RecalculatePopupSize @0x0046caf0 — popup resizes to the ListBox's summed content height, uncapped (0x0046e5f4..0046e66c via ResizeScrollableArea's 0x32 broadcast) UiMenu gains three opt-in properties (ButtonTextCentered, ItemTextCentered, PopupSizeToContent) plus retail Open @0x0046cc42's empty-list gate; chat + vendor keep the class defaults, so their shipped behavior is untouched. ConfigOptionsPageController.ApplyMenuChrome wires all four corrections for the 8 Config menus with the probe citation. The same probe found vendor's authored popup ListBox is ALSO docked while our vendor dropdown ships G5's fixed 6-row window — filed as #386 + register row AD-88 (UNCLEAR: the G5 retail screenshot and the decomp mechanism conflict) instead of silently reworking a user-gated surface. The "resolution change resizes the window" observation from the same report is #374's designed windowed-mode behavior (display-mode switching is #376/#377) — no change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
028920420d
commit
a9b6435f55
8 changed files with 422 additions and 9 deletions
|
|
@ -489,4 +489,76 @@ public class UiMenuTests
|
|||
Assert.Equal(0f, menu.TextIndent);
|
||||
Assert.Equal(0f, menu.ButtonTextIndent);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// User gate report 2026-08-13: fixed-6-row popups for short option
|
||||
// lists. Retail (UIElement_Menu::RecalculatePopupSize @0x0046caf0)
|
||||
// sizes the popup to the ListBox's summed content height, uncapped,
|
||||
// when the authored ListBox is edge-docked — see
|
||||
// UiMenu.PopupSizeToContent's own doc for the full mechanism.
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
private static UiMenu MakeScrollableMenu(int itemCount, bool sizeToContent) => new UiMenu
|
||||
{
|
||||
Width = 120f, Height = 18f,
|
||||
Scrollable = true,
|
||||
OpenUpward = false,
|
||||
RowsPerColumn = 6,
|
||||
RowHeight = 18f,
|
||||
ColumnWidth = 100f,
|
||||
PopupSizeToContent = sizeToContent,
|
||||
Items = Enumerable.Range(0, itemCount)
|
||||
.Select(i => new UiMenu.MenuItem($"Item {i}", (object?)i)).ToArray(),
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void SizeToContent_ShrinksThePopupToTheItemCount()
|
||||
{
|
||||
// 3 items: interior 3*18, plus the 5px bevel top+bottom.
|
||||
Assert.Equal(3 * 18f + 10f, MakeScrollableMenu(3, sizeToContent: true).PopupOuterHeight);
|
||||
// Control: without size-to-content the fixed 6-row window stands.
|
||||
Assert.Equal(6 * 18f + 10f, MakeScrollableMenu(3, sizeToContent: false).PopupOuterHeight);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SizeToContent_GrowsPastTheFixedWindow_AndTheLastRowIsPickable()
|
||||
{
|
||||
// Retail's content sum is UNCAPPED — 9 items = 9 rows, no scrolling.
|
||||
UiMenu menu = MakeScrollableMenu(9, sizeToContent: true);
|
||||
Assert.Equal(9 * 18f + 10f, menu.PopupOuterHeight);
|
||||
|
||||
Assert.True(menu.OnEvent(new UiEvent(0, menu, UiEventType.MouseDown, 0, 10, 5))); // open
|
||||
Assert.True(menu.IsOpen);
|
||||
|
||||
object? fired = null;
|
||||
menu.OnSelect = p => fired = p;
|
||||
// Row 8 (the 9th item) sits past the old 6-row window: it must be
|
||||
// directly pickable with NO scroll. Downward popup: interior starts
|
||||
// at Height + border.
|
||||
float ly = menu.Height + 5f + 8 * menu.RowHeight + menu.RowHeight / 2f;
|
||||
Assert.True(menu.OnEvent(new UiEvent(0, menu, UiEventType.MouseDown, 0, 10, (int)ly)));
|
||||
Assert.Equal(8, fired);
|
||||
Assert.False(menu.IsOpen); // picking closes, same as every other path
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyItems_ButtonClickDoesNotOpen()
|
||||
{
|
||||
// Retail UIElement_Menu::Open @0x0046cc42 gates on
|
||||
// m_listBox->m_listItems.m_num != 0 — an itemless menu never opens.
|
||||
UiMenu menu = MakeScrollableMenu(0, sizeToContent: true);
|
||||
Assert.True(menu.OnEvent(new UiEvent(0, menu, UiEventType.MouseDown, 0, 10, 5)));
|
||||
Assert.False(menu.IsOpen);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TextStyleDefaults_PreserveChatAndVendorBehavior()
|
||||
{
|
||||
// The three 2026-08-13 additions are opt-in: chat's gold left-aligned
|
||||
// caption and vendor's fixed 6-row window are untouched by default.
|
||||
var menu = new UiMenu();
|
||||
Assert.False(menu.ButtonTextCentered);
|
||||
Assert.False(menu.ItemTextCentered);
|
||||
Assert.False(menu.PopupSizeToContent);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue