From 4b982e8eeb9f36e268c55d239f52413e6c32b8f1 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sun, 25 Oct 2026 12:56:51 -0400 Subject: [PATCH] fix(desktop): paint the utilization bar when its fill is a sliver A one-pixel fill (about 2% on the Nesting Progress bar) asked GDI+ for a zero-size corner arc, which threw "Parameter is not valid" mid-nest. Clamp the corner radius to the rectangle and fall back to a plain rectangle. Co-Authored-By: Claude Opus 5.5 --- .../Controls/DensityBarTests.cs | 33 +++++++++++++++++++ OpenNest/Controls/DensityBar.cs | 8 +++++ 2 files changed, 41 insertions(+) create mode 100644 OpenNest.WinForms.Tests/Controls/DensityBarTests.cs diff --git a/OpenNest.WinForms.Tests/Controls/DensityBarTests.cs b/OpenNest.WinForms.Tests/Controls/DensityBarTests.cs new file mode 100644 index 00000000..d2474038 --- /dev/null +++ b/OpenNest.WinForms.Tests/Controls/DensityBarTests.cs @@ -0,0 +1,33 @@ +using System.Drawing; +using System.Reflection; +using System.Windows.Forms; +using OpenNest.Controls; + +namespace OpenNest.WinForms.Tests.Controls; + +/// +/// The Nesting Progress utilization bar paints at every value and size: a sliver of fill +/// (about 1% on the default bar) once threw from a zero-size corner arc. +/// +public class DensityBarTests +{ + [Theory] + [InlineData(60, 8, 0.0)] + [InlineData(60, 8, 0.01)] + [InlineData(60, 8, 0.02)] + [InlineData(60, 8, 0.05)] + [InlineData(60, 8, 0.5)] + [InlineData(60, 8, 1.0)] + [InlineData(60, 4, 0.5)] + [InlineData(3, 2, 1.0)] + [InlineData(1, 1, 1.0)] + public void Paints_without_throwing(int width, int height, double value) + { + using var bar = new DensityBar { Size = new Size(width, height), Value = value }; + using var bitmap = new Bitmap(System.Math.Max(width, 1), System.Math.Max(height, 1)); + using var g = Graphics.FromImage(bitmap); + + typeof(DensityBar).GetMethod("OnPaint", BindingFlags.Instance | BindingFlags.NonPublic)! + .Invoke(bar, new object[] { new PaintEventArgs(g, bar.ClientRectangle) }); + } +} diff --git a/OpenNest/Controls/DensityBar.cs b/OpenNest/Controls/DensityBar.cs index 3db455af..c5258e8a 100644 --- a/OpenNest/Controls/DensityBar.cs +++ b/OpenNest/Controls/DensityBar.cs @@ -67,6 +67,14 @@ namespace OpenNest.Controls private static GraphicsPath CreateRoundedRect(Rectangle rect, int radius) { var path = new GraphicsPath(); + // GDI+ refuses a zero-size arc, which a sliver of fill would need. + radius = System.Math.Min(radius, System.Math.Min(rect.Width, rect.Height) / 2); + if (radius <= 0) + { + path.AddRectangle(rect); + return path; + } + var d = radius * 2; path.AddArc(rect.X, rect.Y, d, d, 180, 90); path.AddArc(rect.Right - d, rect.Y, d, d, 270, 90);