feat(ui): defaults.json-backed new nests; retire .nstdot templates

New nests now load plate defaults from %APPDATA%/OpenNest/defaults.json
instead of a .nstdot nest template:

- Tools > Nest Defaults... edits the file directly (new dialog).
- Tools > Save Current Plate as Defaults captures the active plate with
  no dialog (visible when a nest is open).
- New_Click no longer unzips a template; a corrupt defaults file warns
  once per session and falls back to built-in values.
- First run converts an existing NestTemplatePath .nstdot to
  defaults.json and clears the legacy setting (kept readable on a
  failed conversion); the setting itself stays, marked legacy.
- Save As no longer offers the .nstdot filter; SaveTemplate removed.
- BomImportForm and OptionsForm template plumbing removed in favor of
  the shared NestDefaults store.
This commit is contained in:
aj
2026-09-28 08:20:49 -04:00
parent bdb78a689d
commit f44c1d465f
11 changed files with 644 additions and 187 deletions
+14 -13
View File
@@ -34,9 +34,9 @@ public class NestDefaultsTests : IDisposable
};
original.Save(_path);
var loaded = NestDefaults.Load(_path, out var loadedFromDisk);
var loaded = NestDefaults.Load(_path, out var status);
Assert.True(loadedFromDisk);
Assert.Equal(NestDefaultsStatus.Ok, status);
Assert.Equal(Units.Millimeters, loaded.Units);
Assert.Equal(original.Size, loaded.Size);
Assert.Equal(3, loaded.Quadrant);
@@ -58,20 +58,20 @@ public class NestDefaultsTests : IDisposable
[Fact]
public void Load_MissingFile_ReturnsFallback()
{
var loaded = NestDefaults.Load(_path, out var loadedFromDisk);
var loaded = NestDefaults.Load(_path, out var status);
Assert.False(loadedFromDisk);
Assert.Equal(NestDefaultsStatus.Missing, status);
AssertFallback(loaded);
}
[Fact]
public void Load_CorruptJson_ReturnsFallbackButReportsFile()
public void Load_CorruptJson_ReturnsFallbackButReportsInvalid()
{
File.WriteAllText(_path, "{ this is not json");
var loaded = NestDefaults.Load(_path, out var loadedFromDisk);
var loaded = NestDefaults.Load(_path, out var status);
Assert.True(loadedFromDisk);
Assert.Equal(NestDefaultsStatus.Invalid, status);
AssertFallback(loaded);
}
@@ -80,9 +80,9 @@ public class NestDefaultsTests : IDisposable
{
File.WriteAllText(_path, """{ "units": "millimeters", "partSpacing": 4 }""");
var loaded = NestDefaults.Load(_path, out var loadedFromDisk);
var loaded = NestDefaults.Load(_path, out var status);
Assert.True(loadedFromDisk);
Assert.Equal(NestDefaultsStatus.Ok, status);
Assert.Equal(Units.Millimeters, loaded.Units);
Assert.Equal(4, loaded.PartSpacing);
// Untouched fields keep fallback values.
@@ -107,9 +107,10 @@ public class NestDefaultsTests : IDisposable
"""
);
var loaded = NestDefaults.Load(_path, out var loadedFromDisk);
var loaded = NestDefaults.Load(_path, out var status);
Assert.True(loadedFromDisk);
// The file parses; only the invalid values fall back, so no warning.
Assert.Equal(NestDefaultsStatus.Ok, status);
Assert.Equal(Units.Inches, loaded.Units);
Assert.Equal(new Size(100, 100), loaded.Size);
Assert.Equal(1, loaded.Quadrant);
@@ -144,9 +145,9 @@ public class NestDefaultsTests : IDisposable
"""
);
var loaded = NestDefaults.Load(_path, out var loadedFromDisk);
var loaded = NestDefaults.Load(_path, out var status);
Assert.True(loadedFromDisk);
Assert.Equal(NestDefaultsStatus.Ok, status);
Assert.Equal(2, loaded.PartSpacing);
}