fix(vt): list column fix round 7/11 — short check columns draw unchecked

DrawCheckCell drew nothing for a row past its own column's bound data —
inconsistent with docs/plugin-ui-markup.md's own description of VVS's
HudList, which materializes every cell in a row regardless of which
columns actually have data for it. Text/icon cells rightly stay
no-draw past their own count (no sensible default string or icon), but
a check cell always has one: unchecked.

DrawCheckCell now computes isChecked defensively (false when the flags
array is null or too short) instead of returning early, so a short
check column draws the unchecked lamp for every row past its own data
just like every other row.

New test: a 3-row list (driven by a longer text column) with a check
column bound to only 1 row now shows the unchecked lamp for rows 1 and
2 — shown to fail first (0 unchecked lamp quads, since DrawCheckCell
returned early past index 0).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-06 21:09:41 +02:00
parent 184f687691
commit f8e5edb848
2 changed files with 49 additions and 3 deletions

View file

@ -672,6 +672,43 @@ public sealed class MarkupListColumnsTests
$"expected row 1's glyph ({uncheckedY}) below row 0's ({checkedY})");
}
// ── Fix round: short check columns draw the unchecked lamp past their
// own row count (fix item 7) ────────────────────────────────────────────
[Fact]
public void CheckColumn_DrawsUncheckedLamp_ForRowsPastItsOwnRowCount()
{
// col0 (text) has 3 rows, driving the overall row count. col1 (last,
// check) only binds 1 row of its own — VVS materializes every cell
// regardless (docs/plugin-ui-markup.md already documented this), so
// rows 1 and 2 must STILL draw an unchecked lamp, not nothing.
var list = new UiMarkupList
{
Width = 60f, Height = 60f, RowHeight = 18f,
SelectedIndexSource = () => -1,
BackgroundColor = default, BorderColor = default,
Columns = new[]
{
UiMarkupListColumn.Text(20f, () => new[] { "a", "b", "c" }, null),
UiMarkupListColumn.Check(20f, () => new[] { true }, _ => { }),
},
};
var (renderer, ctx) = MakeContext(200f, 200f);
list.DrawSelfAndChildren(ctx);
var uncheckedQuads = renderer.DebugSpriteSegmentVerts
.SelectMany(s => Chunk(s.Verts))
.Where(v => ColorMatches(v, UiMarkupToggle.UncheckedInner))
.ToList();
// One unchecked lamp for row 1 (bool value false — not this test's
// case) never applies here since col1's only row (0) is TRUE; rows 1
// and 2 have no bound value at all and must still draw UNCHECKED.
Assert.True(uncheckedQuads.Count >= 2,
$"expected an unchecked lamp for both row 1 and row 2 (past col1's own "
+ $"1-row data), got {uncheckedQuads.Count} unchecked lamp quad(s)");
}
[Fact]
public void IconColumn_DrawsResolvedRowIcon_AndSkipsAMissingOne()
{