mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-14 01:05:07 -05:00
ColorScheme, ColorSchemeRegistry, ColorSchemeSerializer and the Schemes folder move into the toolkit-neutral library, keeping the OpenNest namespace, so the Avalonia app can share the built-in palettes, the scheme files and the recolour-on-open rule. ColorScheme is now pure colour data with a Version that changes with any colour. Its GDI+ pens and brushes move to GdiSchemeTools in the WinForms project (still one set per thread, rebuilt after a colour change), reached through scheme.Gdi(). The legacy part outline uses ColorShade.Dark, a port of ControlPaint.Dark's HLS arithmetic; a WinForms test compares the two across a colour sweep on Windows. The registry no longer walks Application.OpenForms: Apply raises Applied, and EditNestForm subscribes once to recolour every open nest window as before. The saved scheme is read under the same ActiveColorScheme setting (SavedSchemeName/ApplySaved for the shared user-settings file); WinForms still reads it through Settings.Default. Schemes/*.json now copies beside both desktop apps from OpenNest.Desktop. Pure scheme tests move to OpenNest.Desktop.Tests, with new ones for built-in round trips, scheme files, bad files, the saved name and the recolour rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.1 KiB
C#
57 lines
2.1 KiB
C#
using System.Drawing;
|
|
|
|
namespace OpenNest.Desktop.Tests;
|
|
|
|
public class FestiveColorSchemeTests
|
|
{
|
|
[Theory]
|
|
[InlineData("Halloween")]
|
|
[InlineData("Christmas")]
|
|
[InlineData("4th of July")]
|
|
public void FestiveSchemeKeepsPartsDistinctAndReadable(string name)
|
|
{
|
|
var scheme = ColorSchemeRegistry.Get(name);
|
|
|
|
Assert.Equal(name, scheme.Name);
|
|
Assert.False(scheme.UseGoldenAngleColors);
|
|
Assert.True(scheme.PartColors.Length >= 12);
|
|
Assert.Equal(Color.Lime.ToArgb(), scheme.EtchColor.ToArgb());
|
|
Assert.True(scheme.SelectedPartColor.IsEmpty);
|
|
|
|
var colors = scheme.PartColors;
|
|
for (var i = 0; i < colors.Length; i++)
|
|
{
|
|
// Part IDs are drawn in black over the fill.
|
|
Assert.True(Luminance(colors[i]) >= 90, $"{name} part color {i} is too dark for black part IDs.");
|
|
Assert.True(Distance(colors[i], scheme.EtchColor) >= 120, $"{name} part color {i} is too close to the etch color.");
|
|
for (var j = i + 1; j < colors.Length; j++)
|
|
Assert.True(Distance(colors[i], colors[j]) >= 40, $"{name} part colors {i} and {j} are too similar.");
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void FestiveSchemesRoundTripAndLeaveClassicAsDefault()
|
|
{
|
|
foreach (var name in new[] { "Halloween", "Christmas", "4th of July" })
|
|
{
|
|
var scheme = ColorSchemeRegistry.Get(name);
|
|
var restored = ColorSchemeSerializer.Deserialize(ColorSchemeSerializer.Serialize(scheme));
|
|
Assert.Equal(name, restored.Name);
|
|
Assert.Equal(scheme.BackgroundColor.ToArgb(), restored.BackgroundColor.ToArgb());
|
|
Assert.Equal(scheme.PartColors.Select(c => c.ToArgb()), restored.PartColors.Select(c => c.ToArgb()));
|
|
}
|
|
|
|
Assert.Equal("Classic", ColorSchemeRegistry.Get(null).Name);
|
|
}
|
|
|
|
private static double Distance(Color a, Color b)
|
|
{
|
|
var dr = a.R - b.R;
|
|
var dg = a.G - b.G;
|
|
var db = a.B - b.B;
|
|
return System.Math.Sqrt(dr * dr + dg * dg + db * db);
|
|
}
|
|
|
|
private static double Luminance(Color c) => 0.299 * c.R + 0.587 * c.G + 0.114 * c.B;
|
|
}
|