feat(style): add the segmented control

WindowTab picks its layout with two radio buttons that are one setting wearing
two labels. A setting row knows one label and one control, so the choice was
either two rows that misstate the relationship or a control that holds the whole
choice. This is the latter, and it generalises to any small closed set.

Segment bounds come from rounded edges rather than a per-segment width. At 201
pixels over two segments the naive form paints two 100.5px halves that land on
the same physical column, which leaves a seam in the middle and a gap on the
right. Deriving each edge from the run means segment i ends exactly where i+1
starts.

Hover keys are derived per segment for the same reason the toggle derives its
own: the caller has already spent its id on the enclosing row, and sharing it
would tie the row highlight to whichever segment the mouse is over.

Disabled is a parameter rather than a BeginDisabled scope because that alpha
never reaches draw-list output. The invisible buttons are still submitted while
disabled so item count and cursor advance do not change between the two states.

MetricsMath gains Center, which is what CenterY always was underneath. Reusing
CenterY to centre text horizontally would have read as a bug at every call site.
This commit is contained in:
2026-08-18 13:37:43 +02:00
parent cade398b4e
commit 688c05cd77
3 changed files with 162 additions and 3 deletions
+6 -3
View File
@@ -6,8 +6,11 @@ internal static class MetricsMath
{
internal static float Scale(float raw, float scale) => raw * scale;
// Vertical centering for text inside a fixed-height row. Frozen offsets keep
// their mis-centering at every other font size; a computed one does not.
// Centering an inner extent inside an outer one. Frozen offsets keep their
// mis-centering at every other font size; a computed one does not.
internal static float Center(float outer, float inner) => (outer - inner) * 0.5f;
// Vertical centering for text inside a fixed-height row.
internal static float CenterY(float rowHeight, float textHeight) =>
(rowHeight - textHeight) * 0.5f;
Center(rowHeight, textHeight);
}