fix(style): close the remaining unreserved-space cases

Three more instances of the pattern the previous fix only half caught.

The section header clipped its description and not its title, so a translated
heading wider than the pane ran out over the scrollbar. Only the window clip
rect stopped it, not the content width.

Row's separator used an unscaled 1px offset with a scaled stroke. ImGui strokes
centred on the path, so at UI scale 2 half the line sits below the rectangle the
row reserved -- and rows stack flush, so it landed in the first pixel row of the
next one. Offset now derives from the thickness.

The segmented control claimed in its own comment to share the setting row's
contract. It did not. It took a position as a parameter and then re-pinned the
layout cursor to it, which moves a caller's layout whenever that position was
not the cursor, and it advanced by the full height where the other two subtract
ItemSpacing.Y. It now reads the cursor like they do, and the comment says why
the advance still differs: those two stack flush because they are list entries,
this is a single control and takes the normal gap.

Also: the label centres against the control band when it has no description
below it, since a slider draws its text at FramePadding.Y and a top-aligned
label sits visibly high next to it. Gallery arrays are held rather than rebuilt
per frame, which its own comment already demanded two sections earlier. And
SectionHeader.Reset is gone -- no caller, and section state keys off ids rather
than labels, so nothing needs to clear it on a language change.
This commit is contained in:
2026-08-18 14:38:42 +02:00
parent 0c3023c8cb
commit 64db8986e6
5 changed files with 46 additions and 22 deletions
+13 -10
View File
@@ -282,6 +282,16 @@ internal sealed class WidgetGalleryWindow : Window
private int _segmentTwo;
private int _segmentThree = 1;
// Held, not rebuilt per frame: a collection expression inside Draw
// allocates a fresh array on every frame the window is open.
private readonly int[] _badgeSamples = [1, 9, 0, 120];
private static readonly FontAwesomeIcon[] GalleryGlyphs =
[
FontAwesomeIcon.ArrowUpRightFromSquare,
FontAwesomeIcon.Check,
FontAwesomeIcon.CheckCircle,
];
private void DrawSegmentedSection(ThemeColors c)
{
var colors = new SegmentedControlColors
@@ -298,7 +308,6 @@ internal sealed class WidgetGalleryWindow : Window
_segmentTwo = SegmentedControl.Draw(
ImGui.GetID("gallery.segmented.two"),
ImGui.GetCursorScreenPos(),
width,
SegmentLabelsTwo,
_segmentTwo,
@@ -307,7 +316,6 @@ internal sealed class WidgetGalleryWindow : Window
_segmentThree = SegmentedControl.Draw(
ImGui.GetID("gallery.segmented.three"),
ImGui.GetCursorScreenPos(),
width,
SegmentLabelsThree,
_segmentThree,
@@ -318,7 +326,6 @@ internal sealed class WidgetGalleryWindow : Window
// and no overhang on the right.
SegmentedControl.Draw(
ImGui.GetID("gallery.segmented.odd"),
ImGui.GetCursorScreenPos(),
201f,
SegmentLabelsThree,
0,
@@ -334,7 +341,8 @@ internal sealed class WidgetGalleryWindow : Window
ImGui.TextUnformatted("Badge");
ImGui.SliderInt("count##badge", ref _badgeCount, 0, 150);
int[] samples = [1, 9, _badgeCount, 120];
_badgeSamples[2] = _badgeCount;
var samples = _badgeSamples;
var origin = ImGui.GetCursorScreenPos();
var x = origin.X;
foreach (var n in samples)
@@ -393,12 +401,7 @@ internal sealed class WidgetGalleryWindow : Window
ImGui.TextUnformatted("IconButton");
var size = new Vector2(Metrics.SidebarPopOutHitWidth, Metrics.SidebarRowHeight);
FontAwesomeIcon[] glyphs =
[
FontAwesomeIcon.ArrowUpRightFromSquare,
FontAwesomeIcon.Check,
FontAwesomeIcon.CheckCircle,
];
var glyphs = GalleryGlyphs;
for (var i = 0; i < glyphs.Length; i++)
{