fix(ui): OP2 re-review closure (coordinator pass) — AP-195, tooltip port, zero-children pin
Closes the mechanism lens's REOPEN (one MUST-FIX) and both lenses' small
residuals on the OP2 rework (b236a442); the blast lens re-review was
CLOSED outright. Fable-direct per the two-failure escalation rule.
- AP-195 filed: UIOption_CheckboxBitfield64 ports HALF of Refresh
@0x004859C0 — the ANY-set checkbox predicate is exact, but the ALL-set
LED media swap (P0x10000082=0x06004D17 / P0x10000083=0x06004D19) and
the ListBox self-sizing tail (ResizeTo/CalculatePaperSize — the block
IS a UIElement_ListBox in retail) are unported, and the block's row
stacking is a second divergent implementation beside UiTemplateListBox.
All due at OP5 before the Chat tab's connected gate; the IsSet doc
comment now names both halves instead of quoting only the ported one.
- Row tooltips: UiButton gains settable TooltipText surfaced through the
shared GetTooltipText hover pipeline (UiCatalogSlot's pattern);
UiCheckboxBitfield64.AddChild applies the row tooltip retail stamps in
CreateChildren @0x00485DF0, and documents that the 0x10000084 row-index
attribute stamp is deliberately replaced by the typed mask closure.
- AD-73 addendum: UiTemplateListBox.ConsumesDatChildren=true is inert
only while no authored Type-5 element carries children — that premise
is now conformance-PINNED across all 32 fixtures (a future DAT
regeneration surfacing an authored child fails the build instead of
silently dropping it).
- Plan doc: OP2's contract names UiTabPanel.cs (retail UIElement_Panel),
not the fictional-class-named UiTabControl.cs; ledger records OP1 and
OP2 both CLOSED.
Full Release suite: 12,871 passed / 4 skipped / 0 failed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6f48e34152
commit
5242de9f15
7 changed files with 943 additions and 6 deletions
|
|
@ -88,6 +88,17 @@ public sealed class UiButton : UiElement, IUiGlobalTimeListener, IUiDatStateful
|
|||
/// <summary>Label color (default white).</summary>
|
||||
public Vector4 LabelColor { get; set; } = Vector4.One;
|
||||
|
||||
/// <summary>Settable tooltip, surfaced through the shared
|
||||
/// <see cref="UiElement.GetTooltipText"/> hover pipeline (same pattern as
|
||||
/// <see cref="UiCatalogSlot"/>). Retail option rows stamp theirs via
|
||||
/// <c>UIElement::SetTooltip</c> during row construction
|
||||
/// (e.g. <c>UIOption_CheckboxBitfield64::CreateChildren @0x00485DF0</c>).</summary>
|
||||
public string? TooltipText { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string? GetTooltipText() =>
|
||||
string.IsNullOrWhiteSpace(TooltipText) ? null : TooltipText;
|
||||
|
||||
/// <summary>Retail LayoutDesc property <c>0x21</c> (two-pass glyph outline,
|
||||
/// <c>UIElement_Text::SetOutline @0x0046a81c</c>). Seeded by DatWidgetFactory
|
||||
/// from the element's effective-default state, same as <see cref="UiText.Outline"/>
|
||||
|
|
|
|||
|
|
@ -167,6 +167,13 @@ public sealed class UiCheckboxBitfield64 : UiPanel
|
|||
}
|
||||
|
||||
checkbox.Label = label;
|
||||
// Retail CreateChildren @0x00485DF0 stamps the row tooltip via
|
||||
// SetTooltip (OP2 re-review §2.2). Its @0x00485E3E companion — the
|
||||
// SetAttribute_Int(cb, 0x10000084, i) row-INDEX stamp retail later
|
||||
// reads back to find which row a click meant — is deliberately
|
||||
// replaced by the typed mask closure below: equivalent routing,
|
||||
// without a stringly attribute round-trip.
|
||||
checkbox.TooltipText = tooltip;
|
||||
checkbox.Selected = IsSet(lowMask, highMask);
|
||||
checkbox.OnClick = () => ToggleRow(lowMask, highMask, checkbox);
|
||||
|
||||
|
|
@ -195,7 +202,11 @@ public sealed class UiCheckboxBitfield64 : UiPanel
|
|||
/// Retail <c>UIOption_CheckboxBitfield64::Refresh @0x004859C0</c>: a row is checked
|
||||
/// when ANY bit of its mask is set in the current value — NOT when every bit is
|
||||
/// set. <c>lowHit = current.low & mask.low; highHit = current.high &
|
||||
/// mask.high; checked = (lowHit | highHit) != 0</c>.
|
||||
/// mask.high; checked = (lowHit | highHit) != 0</c>. This is HALF of Refresh:
|
||||
/// the same pass also computes the ALL-set predicate to swap each row's LED
|
||||
/// media between the two authored surfaces (<c>P0x10000082 = 0x06004D17</c> /
|
||||
/// <c>P0x10000083 = 0x06004D19</c>) — not ported yet, register row AP-195,
|
||||
/// due with the Chat tab (OP5) alongside the ListBox self-sizing tail.
|
||||
/// </summary>
|
||||
private bool IsSet(ulong lowMask, ulong highMask)
|
||||
=> (CurrentLow & lowMask) != 0 || (CurrentHigh & highMask) != 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue