fix(style): make the setting row usable for the widgets that need it most

Review of the two new widgets found four things that would all have landed on
the first real tab.

SettingRow had no hit area and no return value, so "the whole row is clickable,
label included" -- which is the point of pairing it with a switch -- was not
reachable. The label half is now an InvisibleButton and Draw returns whether it
was clicked.

SetNextItemWidth is a silent no-op for Checkbox, RadioButton and
InvisibleButton: they size themselves from GetFrameHeight and never call
CalcItemWidth. So exactly the controls the settings tabs are full of would have
sat at the left edge of the control column, 200px from where the row promised
to put them. The callback now receives a context with AlignRight for widgets
that know their own size.

The switch and the row shared a HoverState key. An enabled switch would have
kept its row permanently highlighted, and hovering a disabled row would have
slid its knob to "on" -- the widget lying about its own value. ToggleSwitch
derives its animation key now, so a caller cannot collide even by passing the
same id to both.

The cursor advance moves from SetCursorScreenPos to ImGuiP.ItemSize. Both
advance the cursor, but only ItemSize is guaranteed to extend CursorMaxPos,
which is what the scrollbar measures. SetCursorScreenPos happens to do it on
ImGui 1.88, which is what Dalamud ships -- upstream removed that in 1.92 and
asserts on the pattern instead. ItemSize does not touch g.LastItemData, so the
save throttles stay intact.

Two smaller ones: the label column no longer collapses to a single pixel on a
narrow row (it stops at 60 and the control shrinks instead), and the toggle
geometry clamps its radius once rather than deriving travel from an unclamped
value. Descriptions wrap now instead of being cut at the column edge.

The gallery gained the pairing both widgets exist for, plus a style-override
variant -- the combination that would have exposed all of this.
This commit is contained in:
2026-08-18 11:59:52 +02:00
parent 86992c70f2
commit cbc4b17e1e
4 changed files with 123 additions and 36 deletions
+43 -10
View File
@@ -147,20 +147,42 @@ internal sealed class WidgetGalleryWindow : Window
BorderAbgr = _palette.Abgr(Token.Border, c),
};
SettingRow.Draw(
ImGui.GetID("gallery.settingrow.plain"),
"A plain option",
null,
colors,
() => ImGui.Checkbox("##gallery-sr-a", ref _toggleA)
);
var switchColors = new ToggleSwitchColors
{
TrackOffAbgr = _palette.Abgr(Token.SurfaceRaised, c),
TrackOnAbgr = _palette.Abgr(Token.AccentPrimary, c),
KnobAbgr = _palette.Abgr(Token.Text, c),
};
// The pairing both widgets exist for: switch inside a row, whole label
// half clickable.
var idA = ImGui.GetID("gallery.settingrow.switch");
if (
SettingRow.Draw(
idA,
"A switch in a row",
null,
colors,
ctx =>
{
var size = ToggleSwitch.CalcSize();
var pos = ctx.AlignRight(size);
ImGui.SetCursorScreenPos(pos);
if (ImGui.InvisibleButton("##gallery-sr-switch", size))
_toggleA = !_toggleA;
ToggleSwitch.Draw(idA, pos, _toggleA, switchColors);
}
)
)
_toggleA = !_toggleA;
SettingRow.Draw(
ImGui.GetID("gallery.settingrow.described"),
"With a description",
"The second line explains what the control above actually does.",
"The second line wraps rather than being cut, so a real settings "
+ "explanation actually fits into the label column.",
colors,
() => ImGui.Checkbox("##gallery-sr-b", ref _toggleB)
_ => ImGui.Checkbox("##gallery-sr-b", ref _toggleB)
);
SettingRow.Draw(
@@ -168,7 +190,18 @@ internal sealed class WidgetGalleryWindow : Window
"A deliberately very long label that has to be clipped somewhere",
null,
colors,
() => ImGui.SliderInt("##gallery-sr-c", ref _badgeCount, 0, 150)
_ => ImGui.SliderInt("##gallery-sr-c", ref _badgeCount, 0, 150)
);
// No separator, narrow control column: the variants a settings tab will
// actually reach for.
SettingRow.Draw(
ImGui.GetID("gallery.settingrow.styled"),
"Style override",
null,
colors,
_ => ImGui.SliderInt("##gallery-sr-d", ref _badgeCount, 0, 150),
new SettingRowStyle { DrawSeparator = false, PreferredControlWidth = 90f }
);
ImGui.Spacing();