From 8a9692a71d4f659d16ad86db47a8ac25182d7112 Mon Sep 17 00:00:00 2001 From: Jon Kazama Date: Wed, 19 Aug 2026 19:13:30 +0200 Subject: [PATCH] fix(chat): size the popups from their rows, not the rows from a guess An ImGui popup does not grow for draw-list content, so both new popups carried a fixed minimum width -- and German outran it within a day. The menu clipped Schnellauswahl and Chat ausblenden mid-word; the channel picker would have done the same to Freie Gesellschaft on a narrow theme font. PopupRow gets a CalcWidth that measures label plus icon plus padding under the faces that will draw them, and both popups take the widest visible entry as their width. Locale-proof by construction: whatever language writes the longest string sets the size. --- HellionChat/Ui/Components/InputBar.cs | 63 ++++++++++++++++++- .../Ui/StyleEngine/Widgets/PopupRow.cs | 17 +++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/HellionChat/Ui/Components/InputBar.cs b/HellionChat/Ui/Components/InputBar.cs index 377c30d..2e18f96 100644 --- a/HellionChat/Ui/Components/InputBar.cs +++ b/HellionChat/Ui/Components/InputBar.cs @@ -313,7 +313,18 @@ internal sealed class InputBar return; } - ImGui.Dummy(new Vector2(150f * StyleEngine.Metrics.Scale, 0f)); + var pickerWidth = 0f; + foreach (var chatType in tab.SelectedChannels.Keys) + { + if (chatType.ToInputChannel() is not { } ch) + continue; + pickerWidth = MathF.Max( + pickerWidth, + StyleEngine.Widgets.PopupRow.CalcWidth(ch.ToChatType().Name(), null, _fonts) + ); + } + + ImGui.Dummy(new Vector2(pickerWidth, 0f)); var i = 0; foreach (var chatType in tab.SelectedChannels.Keys) @@ -799,7 +810,55 @@ internal sealed class InputBar try { - ImGui.Dummy(new Vector2(160f * StyleEngine.Metrics.Scale, 0f)); + // Width from the widest visible entry, not a fixed minimum -- the + // popup does not grow for draw-list content, and German labels + // outran the first guess within a day. + var menuWidth = 0f; + if (_themeQuickPicker is not null) + menuWidth = MathF.Max( + menuWidth, + StyleEngine.Widgets.PopupRow.CalcWidth( + HellionStrings.Settings_QuickPicker_Tooltip, + FontAwesomeIcon.Palette, + _fonts + ) + ); + menuWidth = MathF.Max( + menuWidth, + StyleEngine.Widgets.PopupRow.CalcWidth( + HellionStrings.InputBar_Settings_Tooltip, + FontAwesomeIcon.Cog, + _fonts + ) + ); + menuWidth = MathF.Max( + menuWidth, + StyleEngine.Widgets.PopupRow.CalcWidth( + Language.Context_ScreenshotMode, + FontAwesomeIcon.Camera, + _fonts + ) + ); + if (Plugin.Config.ShowHideButton && _onHideWindow is not null) + menuWidth = MathF.Max( + menuWidth, + StyleEngine.Widgets.PopupRow.CalcWidth( + HellionStrings.InputBar_HideChat_Tooltip, + FontAwesomeIcon.EyeSlash, + _fonts + ) + ); + if (OnPopIn is not null) + menuWidth = MathF.Max( + menuWidth, + StyleEngine.Widgets.PopupRow.CalcWidth( + HellionStrings.InputBar_PopIn_Tooltip, + FontAwesomeIcon.Times, + _fonts + ) + ); + + ImGui.Dummy(new Vector2(menuWidth, 0f)); if ( _themeQuickPicker is not null diff --git a/HellionChat/Ui/StyleEngine/Widgets/PopupRow.cs b/HellionChat/Ui/StyleEngine/Widgets/PopupRow.cs index ba8a6ef..a16755d 100644 --- a/HellionChat/Ui/StyleEngine/Widgets/PopupRow.cs +++ b/HellionChat/Ui/StyleEngine/Widgets/PopupRow.cs @@ -21,6 +21,23 @@ internal static class PopupRow private const float IconGapRaw = 8f; private const float AccentBarRaw = 2f; + // The popup must be sized from its rows, not the rows from the popup: an + // ImGui popup does not grow for draw-list content, so a fixed minimum width + // clips whichever locale writes the longest labels. German did, first day. + internal static float CalcWidth(string label, FontAwesomeIcon? icon, FontManager fonts) + { + var scale = Metrics.Scale; + var w = PadXRaw * 2f * scale + ImGui.CalcTextSize(label).X; + + if (icon is { } glyph) + { + using (fonts.FontAwesome.Push()) + w += ImGui.CalcTextSize(glyph.ToIconString()).X + IconGapRaw * scale; + } + + return w; + } + internal static bool Draw( string id, string label,