From bf48299f3e127a1da912c8e925e63fd6e788ee44 Mon Sep 17 00:00:00 2001 From: Descolada <16986957+Descolada@users.noreply.github.com> Date: Tue, 27 Oct 2026 11:00:14 +0200 Subject: [PATCH] Gtk: Fix untitled GroupBox sizing and preserve title styles Handle missing label widgets when accessing ClientSize and TextColor. Cache explicit text colors and reapply assigned font and color whenever GTK creates a label after a title change. Keep one GTK regression test for deferred styles and title replacement. --- src/Eto.Gtk/Forms/Controls/GroupBoxHandler.cs | 30 +++++++++--- test/Eto.Test.Gtk/UnitTests/GroupBoxTests.cs | 49 +++++++++++++++++++ 2 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 test/Eto.Test.Gtk/UnitTests/GroupBoxTests.cs diff --git a/src/Eto.Gtk/Forms/Controls/GroupBoxHandler.cs b/src/Eto.Gtk/Forms/Controls/GroupBoxHandler.cs index ac089a9227..d20e95467e 100644 --- a/src/Eto.Gtk/Forms/Controls/GroupBoxHandler.cs +++ b/src/Eto.Gtk/Forms/Controls/GroupBoxHandler.cs @@ -2,6 +2,8 @@ namespace Eto.GtkSharp.Forms.Controls { public class GroupBoxHandler : GtkPanel, GroupBox.IHandler { + static readonly object TextColor_Key = new object(); + public GroupBoxHandler () { Control = new EtoFrame { Handler = this }; @@ -13,10 +15,15 @@ public override string Text { get { return Control.Label; } set { - var needsFont = Control.LabelWidget == null && Widget.Properties.ContainsKey(GtkControl.Font_Key); + // GTK replaces the label when the title changes, so reapply assigned styles. Control.Label = value; - if (needsFont) - Control.LabelWidget?.SetFont(Font.ToPango()); + if (Control.LabelWidget is Gtk.Widget label) + { + if (Widget.Properties.ContainsKey(GtkControl.Font_Key)) + label.SetFont(Font.ToPango()); + if (Widget.Properties.Get(TextColor_Key) is Color color) + label.SetForeground(color); + } } } @@ -27,7 +34,7 @@ public override Size ClientSize { else { var label = Control.LabelWidget; var size = Size; - size.Height -= label.Allocation.Height + 10; + size.Height -= (label?.Allocation.Height ?? 0) + 10; size.Width -= 10; return size; } @@ -35,7 +42,7 @@ public override Size ClientSize { set { var label = Control.LabelWidget; var size = value; - size.Height += label.Allocation.Height + 10; + size.Height += (label?.Allocation.Height ?? 0) + 10; size.Width += 10; Size = size; } @@ -54,8 +61,17 @@ protected override void SetContainerContent(Gtk.Widget content) public Color TextColor { - get { return Control.LabelWidget.GetForeground(); } - set { Control.LabelWidget.SetForeground(value); } + get + { + if (Control.LabelWidget is Gtk.Widget label) + return label.GetForeground(); + return Widget.Properties.Get(TextColor_Key) ?? Control.GetForeground(); + } + set + { + Widget.Properties.Set(TextColor_Key, value); + Control.LabelWidget?.SetForeground(value); + } } } } diff --git a/test/Eto.Test.Gtk/UnitTests/GroupBoxTests.cs b/test/Eto.Test.Gtk/UnitTests/GroupBoxTests.cs new file mode 100644 index 0000000000..81fdcdc99d --- /dev/null +++ b/test/Eto.Test.Gtk/UnitTests/GroupBoxTests.cs @@ -0,0 +1,49 @@ +#if GTK3 +using Eto.GtkSharp; +using Eto.Test.UnitTests; +using NUnit.Framework; +using g = Gtk; + +namespace Eto.Test.Gtk.UnitTests +{ + [TestFixture] + public class GroupBoxTests : TestBase + { + [Test] + public void TitleChangesShouldPreserveAssignedStyles() + { + Invoke(() => + { + using var font = new Font(FontFamilies.Sans, 17, FontStyle.Bold); + using var groupBox = new GroupBox { Font = font, TextColor = Colors.Red }; + foreach (var title in new[] { "Title", "Renamed" }) + { + groupBox.Text = title; + AssertLabelStyle(groupBox, font, Colors.Red); + } + + groupBox.Text = null; + Assert.That(((g.Frame)groupBox.ControlObject).LabelWidget, Is.Null); + groupBox.TextColor = default(Color); + groupBox.Text = "Restored"; + AssertLabelStyle(groupBox, font, default(Color)); + }); + } + + static void AssertLabelStyle(GroupBox groupBox, Font font, Color color) + { + var label = ((g.Frame)groupBox.ControlObject).LabelWidget; + Assert.That(label, Is.Not.Null); + var actualFont = label.GetFont(); + var expectedFont = font.ToPango(); + Assert.Multiple(() => + { + Assert.That(actualFont.Size, Is.EqualTo(expectedFont.Size)); + Assert.That(actualFont.Weight, Is.EqualTo(expectedFont.Weight)); + Assert.That(actualFont.Style, Is.EqualTo(expectedFont.Style)); + Assert.That(label.GetForeground().ToArgb(), Is.EqualTo(color.ToArgb())); + }); + } + } +} +#endif