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.
Layout constants lived as bare floats in the components: row heights, hit
widths, insets, reserve widths. None of them multiplied by GlobalScale, so at
125% or 150% display scaling the text grows and the boxes do not. The quick
buttons stop fitting into their 130px column.
Metrics holds the design values and exposes scaled properties. The Raw
constants stay reachable for the few places that must store or compare an
unscaled value: Sidebar.GetWidth (a SelfTest pins it against raw numbers) and
the width slider bounds.
Scale is pinned once per frame against ImGui.GetFrameCount(). GlobalScale is a
live value the Dalamud slider moves on every dragged frame, so reading it per
access can shift a CalcSize away from its matching Draw inside one frame, and
costs three native calls each time.
Not in ThemeLayout: that record is serialised into theme JSON, and layout
customisation is out of scope per the master spec.
MetricsMath is the pure half so the build suite can pin the arithmetic. Text
heights are measured rather than scaled -- the font is built from
Config.FontSizeV2, which GlobalScale does not feed into.