mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 03:51:05 -04:00
feat(ui): make Blueprint the default color scheme
- Add the Blueprint scheme: navy canvas, pale blue sheet, dark navy part outlines, orange-red rapids and twelve distinct, readable part fills. - Use it as the settings default and the fallback for unknown scheme names, and list it first in Options. Saved scheme choices are kept. - Run the palette spacing and readability tests over Blueprint and Classic. - Document the default in nesting-view-colors.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
66afea5a51
commit
c875edcdd1
7 files changed
+66
-14
No files matched your search
@@ -38,23 +38,28 @@ public class ClassicPaletteTests
|
||||
return System.Math.Sqrt((l1 - l2) * (l1 - l2) + (a1 - a2) * (a1 - a2) + (b1 - b2) * (b1 - b2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClassicFillsAreClearlyDistinctFromEachOther()
|
||||
public static TheoryData<string> ListedPalettes => new() { "Blueprint", "Classic" };
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ListedPalettes))]
|
||||
public void FillsAreClearlyDistinctFromEachOther(string name)
|
||||
{
|
||||
var colors = ColorSchemeRegistry.Get("Classic").PartColors;
|
||||
var colors = ColorSchemeRegistry.Get(name).PartColors;
|
||||
Assert.Equal(12, colors.Length);
|
||||
for (var i = 0; i < colors.Length; i++)
|
||||
{
|
||||
for (var j = i + 1; j < colors.Length; j++)
|
||||
Assert.True(DeltaE(colors[i], colors[j]) >= 30,
|
||||
$"Classic colors {i} and {j} are too similar ({DeltaE(colors[i], colors[j]):F1}).");
|
||||
$"{name} colors {i} and {j} are too similar ({DeltaE(colors[i], colors[j]):F1}).");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClassicFillsStayReadableAndClearOfEtchGreenAndTheSheet()
|
||||
[Theory]
|
||||
[MemberData(nameof(ListedPalettes))]
|
||||
public void FillsStayReadableAndClearOfEtchGreenAndTheSheet(string name)
|
||||
{
|
||||
var scheme = ColorSchemeRegistry.Get("Classic");
|
||||
var scheme = ColorSchemeRegistry.Get(name);
|
||||
Assert.Equal(name, scheme.Name);
|
||||
Assert.All(scheme.PartColors, color =>
|
||||
{
|
||||
Assert.True(Contrast(color, Color.Black) >= 4.5, $"{color} is too dark for black part IDs.");
|
||||
|
||||
@@ -30,7 +30,7 @@ public class FestiveColorSchemeTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FestiveSchemesRoundTripAndLeaveClassicAsDefault()
|
||||
public void FestiveSchemesRoundTripAndLeaveBlueprintAsDefault()
|
||||
{
|
||||
foreach (var name in new[] { "Halloween", "Christmas", "4th of July" })
|
||||
{
|
||||
@@ -41,7 +41,7 @@ public class FestiveColorSchemeTests
|
||||
Assert.Equal(scheme.PartColors.Select(c => c.ToArgb()), restored.PartColors.Select(c => c.ToArgb()));
|
||||
}
|
||||
|
||||
Assert.Equal("Classic", ColorSchemeRegistry.Get(null).Name);
|
||||
Assert.Equal("Blueprint", ColorSchemeRegistry.Get(null).Name);
|
||||
}
|
||||
|
||||
private static double Distance(Color a, Color b)
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace OpenNest
|
||||
StringComparer.OrdinalIgnoreCase
|
||||
)
|
||||
{
|
||||
["Blueprint"] = BuildBlueprint(),
|
||||
["Classic"] = BuildClassic(),
|
||||
["Pastel"] = BuildPastel(),
|
||||
["Dark"] = BuildDark(),
|
||||
@@ -24,6 +25,8 @@ namespace OpenNest
|
||||
["4th of July"] = BuildFourthOfJuly(),
|
||||
};
|
||||
|
||||
public const string DefaultSchemeName = "Blueprint";
|
||||
|
||||
private static List<ColorScheme> diskCache;
|
||||
|
||||
public static IEnumerable<ColorScheme> AllSchemes
|
||||
@@ -40,12 +43,12 @@ namespace OpenNest
|
||||
public static ColorScheme Get(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return builtIns["Classic"];
|
||||
return builtIns[DefaultSchemeName];
|
||||
|
||||
var hit = AllSchemes.FirstOrDefault(s =>
|
||||
string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase)
|
||||
);
|
||||
return hit ?? builtIns["Classic"];
|
||||
return hit ?? builtIns[DefaultSchemeName];
|
||||
}
|
||||
|
||||
public static void ApplyActiveFromSettings()
|
||||
@@ -227,6 +230,39 @@ namespace OpenNest
|
||||
},
|
||||
};
|
||||
|
||||
// The default scheme. Its twelve fills were picked farthest-first in Lab (at least
|
||||
// ~30 CIE76 apart), readable with black part IDs and clear of etch green, the sheet
|
||||
// and the canvas.
|
||||
private static ColorScheme BuildBlueprint() =>
|
||||
new ColorScheme
|
||||
{
|
||||
Name = "Blueprint",
|
||||
BackgroundColor = Color.FromArgb(24, 52, 92),
|
||||
LayoutOutlineColor = Color.FromArgb(120, 150, 190),
|
||||
LayoutFillColor = Color.FromArgb(226, 236, 246),
|
||||
BoundingBoxColor = Color.FromArgb(140, 200, 255),
|
||||
RapidColor = Color.FromArgb(230, 90, 40),
|
||||
OriginColor = Color.FromArgb(150, 175, 205),
|
||||
EdgeSpacingColor = Color.FromArgb(160, 185, 215),
|
||||
PreviewPartColor = Color.FromArgb(255, 200, 40),
|
||||
PartOutlineColor = Color.FromArgb(20, 40, 70),
|
||||
PartColors = new[]
|
||||
{
|
||||
Color.FromArgb(232, 136, 79),
|
||||
Color.FromArgb(32, 168, 253),
|
||||
Color.FromArgb(116, 242, 171),
|
||||
Color.FromArgb(252, 138, 213),
|
||||
Color.FromArgb(198, 198, 88),
|
||||
Color.FromArgb(28, 231, 250),
|
||||
Color.FromArgb(248, 186, 187),
|
||||
Color.FromArgb(137, 169, 132),
|
||||
Color.FromArgb(169, 152, 202),
|
||||
Color.FromArgb(253, 116, 137),
|
||||
Color.FromArgb(238, 216, 165),
|
||||
Color.FromArgb(104, 169, 195),
|
||||
},
|
||||
};
|
||||
|
||||
private static ColorScheme BuildClassic() =>
|
||||
new ColorScheme
|
||||
{
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace OpenNest.Forms
|
||||
Settings.Default.CreateNewNestOnOpen = checkBox1.Checked;
|
||||
Settings.Default.AutoSizePlateFactor = (double)numericUpDown1.Value;
|
||||
Settings.Default.ActiveColorScheme =
|
||||
colorSchemeCombo.SelectedItem as string ?? "Classic";
|
||||
colorSchemeCombo.SelectedItem as string ?? ColorSchemeRegistry.DefaultSchemeName;
|
||||
|
||||
var disabledNames = new List<string>();
|
||||
foreach (DataGridViewRow row in strategyGrid.Rows)
|
||||
|
||||
Generated
+1
-1
@@ -283,7 +283,7 @@ namespace OpenNest.Properties {
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("Classic")]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("Blueprint")]
|
||||
public string ActiveColorScheme {
|
||||
get {
|
||||
return ((string)(this["ActiveColorScheme"]));
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="ActiveColorScheme" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">Classic</Value>
|
||||
<Value Profile="(Default)">Blueprint</Value>
|
||||
</Setting>
|
||||
<Setting Name="UpdateFeedUrl" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# Nesting-view colors
|
||||
|
||||
## Default scheme
|
||||
|
||||
**Blueprint** is the default for new installs and the fallback for missing or
|
||||
unknown scheme names: deep navy canvas, pale blue sheet, dark navy part
|
||||
outlines, orange-red rapids and twelve part fills at least ~30 CIE76 apart that
|
||||
stay readable with black part IDs and clear of the etch green, the sheet and the
|
||||
canvas. A scheme already saved in **Tools > Options** is kept; choose Blueprint
|
||||
there to switch an existing install. Classic remains available.
|
||||
|
||||
## Workshop
|
||||
|
||||
Choose **Tools > Options > Color scheme > Workshop**, then **Save** for a
|
||||
high-contrast per-drawing view:
|
||||
|
||||
|
||||
Reference in new issue
Block a user