feat(scoreboard): scroll speed is a property (20-400 px/s, persisted)

The marquee now has the dial it needs. `ScoreboardPresenter.PixelsPerSecond` is the single owner of
the range (20-400, default 120), the layer's properties expose it with a live px/s readout, and the
value is persisted as Scoreboard.ScrollSpeed because it is a READABILITY choice — re-dialling it
every launch would be a tax on the creator who needs the strip to be readable.

Advance() still takes an optional override so tests can drive exact distances.

Guard: the presenter test proves speed is real (same elapsed time, twice the speed, different
window) — not a value that is stored and ignored — and the panel test pins the control, its range
and the persistence key.
This commit is contained in:
2026-10-30 15:19:28 -07:00
parent 460b36204d
commit 28525c90aa
7 changed files with 61 additions and 3 deletions
+6 -1
View File
@@ -29,6 +29,11 @@ public class ScoreboardPropertiesTests
Assert.Contains("Simulate (dev)", block);
Assert.Contains("Brush.Attention", block);
// Scroll speed: a real dial, persisted, with its range owned by the presenter.
Assert.Contains("ScoreboardScrollSpeed", block);
Assert.Contains("Minimum=\"20\" Maximum=\"400\"", block);
Assert.Contains("Scoreboard.ScrollSpeed", SourceAssert.Text("Services", "LayoutStore.Settings.cs"));
// The master switch sits in the same panel: off hides the strip and stops the polling.
Assert.Contains("ScoreboardEnabled", panel);
@@ -61,7 +66,7 @@ public class ScoreboardPropertiesTests
{
"ScoreboardTextColor", "ScoreboardBackgroundColor", "ScoreboardBackgroundOpacity",
"ScoreboardFontSize", "ScoreboardColorOptions", "ScoreboardShowSubscribers",
"ScoreboardEnabled", "CanUseScoreboard",
"ScoreboardEnabled", "CanUseScoreboard", "ScoreboardScrollSpeed",
})
Assert.NotNull(type.GetProperty(name));
}