mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-06 11:15:44 -05:00
feat(machines): assign each nest a machine and keep the support grid per machine
The support grid was one shared support-grid.json, off by default, and a nest had no machine at all, so a plasma table and a fiber laser could not have different grids, and nothing could pick machine-specific behavior later (lead-ins differ between laser and plasma; tabbing depends on the grid). - Nest.Machine (id + name) persists as top-level `machine` in nest.json; malformed values load as none. - MachineConfig.SupportGrid holds each machine's grid; a machine without one still falls back to the legacy support-grid.json. - New and BOM import assign the Tools > Nest Defaults machine (first by name when none is chosen) and give the nest that machine's grid. - Nest > Machine reassigns a nest and swaps in the new machine's grid; Nest > Support Grid saves machine defaults to the nest's machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
993555dba6
commit
9c78b4ebec
21 files changed
+513
-44
No files matched your search
@@ -57,6 +57,9 @@ namespace OpenNest
|
||||
|
||||
public Units Units { get; set; }
|
||||
|
||||
/// <summary>The machine this nest is cut on, or null when none is assigned.</summary>
|
||||
public NestMachine Machine { get; set; }
|
||||
|
||||
public DateTime DateCreated { get; set; }
|
||||
|
||||
public DateTime DateLastModified { get; set; }
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace OpenNest
|
||||
{
|
||||
/// <summary>
|
||||
/// The machine a nest is cut on: the id of its machine configuration plus the name it had,
|
||||
/// so a nest still says which machine it was made for on a PC without that configuration.
|
||||
/// </summary>
|
||||
public sealed class NestMachine
|
||||
{
|
||||
public NestMachine(Guid id, string name)
|
||||
{
|
||||
Id = id;
|
||||
Name = name ?? string.Empty;
|
||||
}
|
||||
|
||||
public Guid Id { get; }
|
||||
|
||||
public string Name { get; }
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,12 @@ public class MachineConfig
|
||||
/// <summary>Acceleration limits; null until entered, when <see cref="GetMotionOrPlaceholder"/> stands in.</summary>
|
||||
public MotionConfig? Motion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The support grid nests assigned this machine rest on; null until saved from
|
||||
/// Nest > Support Grid, when the legacy shared support-grid.json stands in.
|
||||
/// </summary>
|
||||
public SupportGridSettings? SupportGrid { get; set; }
|
||||
|
||||
public MotionConfig GetMotionOrPlaceholder() => Motion ?? MotionConfig.Placeholder(Units);
|
||||
|
||||
public ThicknessConfig? GetParameters(string material, double thickness) =>
|
||||
|
||||
@@ -46,6 +46,12 @@ public sealed class NestDefaults
|
||||
|
||||
public Spacing EdgeSpacing { get; set; } = new(1, 1, 1, 1);
|
||||
|
||||
/// <summary>
|
||||
/// The machine configuration new nests are assigned, or null to use the first machine
|
||||
/// by name. An id with no configuration on file falls back the same way.
|
||||
/// </summary>
|
||||
public Guid? MachineId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The built-in defaults used when no file exists and for every field
|
||||
/// that is missing or invalid. Matches the historical
|
||||
@@ -149,6 +155,10 @@ public sealed class NestDefaults
|
||||
)
|
||||
defaults.EdgeSpacing = new Spacing(left, bottom, right, top);
|
||||
|
||||
if (dto.MachineId is { ValueKind: JsonValueKind.String } machineId
|
||||
&& Guid.TryParse(machineId.GetString(), out var machine) && machine != Guid.Empty)
|
||||
defaults.MachineId = machine;
|
||||
|
||||
return defaults;
|
||||
}
|
||||
|
||||
@@ -166,6 +176,7 @@ public sealed class NestDefaults
|
||||
Quadrant = plate.Quadrant,
|
||||
PartSpacing = plate.PartSpacing,
|
||||
EdgeSpacing = plate.EdgeSpacing,
|
||||
MachineId = nest.Machine?.Id,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -203,6 +214,7 @@ public sealed class NestDefaults
|
||||
PartSpacing = Convert(PartSpacing),
|
||||
EdgeSpacing = new Spacing(Convert(EdgeSpacing.Left), Convert(EdgeSpacing.Bottom),
|
||||
Convert(EdgeSpacing.Right), Convert(EdgeSpacing.Top)),
|
||||
MachineId = MachineId,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -239,6 +251,7 @@ public sealed class NestDefaults
|
||||
Right = EdgeSpacing.Right,
|
||||
Top = EdgeSpacing.Top,
|
||||
},
|
||||
MachineId = MachineId is { } machineId ? JsonSerializer.SerializeToElement(machineId.ToString()) : null,
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(dto, JsonOptions);
|
||||
@@ -319,6 +332,9 @@ public sealed class NestDefaults
|
||||
public int? Quadrant { get; init; }
|
||||
public double? PartSpacing { get; init; }
|
||||
public SpacingDto? EdgeSpacing { get; init; }
|
||||
// Raw JSON for the same reason as Units.
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public JsonElement? MachineId { get; init; }
|
||||
}
|
||||
|
||||
private sealed record SizeDto
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using System.Text.Json.Nodes;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.IO.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// The nest's assigned machine persists as top-level <c>machine</c> (<c>id</c> and <c>name</c>);
|
||||
/// a nest without one writes no key, and a malformed one loads as none.
|
||||
/// </summary>
|
||||
public class NestMachinePersistenceTests
|
||||
{
|
||||
private static readonly NestMachine Machine = new(Guid.Parse("6f1a3c2e-5b7d-4e8f-9a0b-1c2d3e4f5a6b"), "Fiber 1");
|
||||
|
||||
private static Nest NestWith(NestMachine machine)
|
||||
{
|
||||
var nest = new Nest("machine") { Machine = machine };
|
||||
nest.PlateDefaults.Size = new Size(48, 96);
|
||||
nest.CreatePlate();
|
||||
return nest;
|
||||
}
|
||||
|
||||
private static MemoryStream Write(Nest nest)
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
Assert.True(new NestWriter(nest).Write(stream));
|
||||
stream.Position = 0;
|
||||
return stream;
|
||||
}
|
||||
|
||||
private static JsonNode NestJson(MemoryStream zip)
|
||||
{
|
||||
zip.Position = 0;
|
||||
using var archive = new ZipArchive(zip, ZipArchiveMode.Read, leaveOpen: true);
|
||||
using var reader = new StreamReader(archive.GetEntry("nest.json")!.Open(), Encoding.UTF8);
|
||||
var json = JsonNode.Parse(reader.ReadToEnd())!;
|
||||
zip.Position = 0;
|
||||
return json;
|
||||
}
|
||||
|
||||
private static MemoryStream Rewrite(MemoryStream zip, Action<JsonNode> edit)
|
||||
{
|
||||
var json = NestJson(zip);
|
||||
edit(json);
|
||||
var copy = new MemoryStream();
|
||||
zip.Position = 0;
|
||||
zip.CopyTo(copy);
|
||||
using (var archive = new ZipArchive(copy, ZipArchiveMode.Update, leaveOpen: true))
|
||||
{
|
||||
archive.GetEntry("nest.json")!.Delete();
|
||||
using var writer = new StreamWriter(archive.CreateEntry("nest.json").Open(), new UTF8Encoding(false));
|
||||
writer.Write(json.ToJsonString());
|
||||
}
|
||||
copy.Position = 0;
|
||||
return copy;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MachineRoundTrips()
|
||||
{
|
||||
var reopened = new NestReader(Write(NestWith(Machine))).Read();
|
||||
|
||||
Assert.Equal(Machine.Id, reopened.Machine!.Id);
|
||||
Assert.Equal("Fiber 1", reopened.Machine.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NestWithoutMachine_WritesNoKeyAndLoadsWithoutOne()
|
||||
{
|
||||
var zip = Write(NestWith(null));
|
||||
|
||||
Assert.False(NestJson(zip).AsObject().ContainsKey("machine"));
|
||||
Assert.Null(new NestReader(zip).Read().Machine);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("\"Fiber 1\"")]
|
||||
[InlineData("{\"id\":42,\"name\":\"Fiber 1\"}")]
|
||||
[InlineData("{\"id\":\"not-a-guid\",\"name\":\"Fiber 1\"}")]
|
||||
[InlineData("{\"id\":\"00000000-0000-0000-0000-000000000000\"}")]
|
||||
[InlineData("{\"name\":\"Fiber 1\"}")]
|
||||
public void MalformedMachine_LoadsAsNone(string machine)
|
||||
{
|
||||
var zip = Rewrite(Write(NestWith(Machine)), json => json["machine"] = JsonNode.Parse(machine));
|
||||
|
||||
var reopened = new NestReader(zip).Read();
|
||||
|
||||
Assert.Null(reopened.Machine);
|
||||
Assert.Equal("machine", reopened.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MachineWithoutName_LoadsWithEmptyName()
|
||||
{
|
||||
var zip = Rewrite(Write(NestWith(Machine)),
|
||||
json => json["machine"] = JsonNode.Parse($"{{\"id\":\"{Machine.Id}\",\"name\":7}}"));
|
||||
|
||||
var reopened = new NestReader(zip).Read();
|
||||
|
||||
Assert.Equal(Machine.Id, reopened.Machine!.Id);
|
||||
Assert.Equal("", reopened.Machine.Name);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,15 @@ namespace OpenNest.IO
|
||||
public string AssistGas { get; init; } = "";
|
||||
public string Status { get; init; } = "Quote";
|
||||
public string MadeBy { get; init; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// The machine the nest is cut on. Omitted when none is assigned; older files and
|
||||
/// older readers simply have none.
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonConverter(typeof(LenientMachineConverter))]
|
||||
public MachineDto Machine { get; init; }
|
||||
|
||||
public double Thickness { get; init; }
|
||||
public MaterialDto Material { get; init; } = new();
|
||||
public PlateDefaultsDto PlateDefaults { get; init; } = new();
|
||||
@@ -63,6 +72,43 @@ namespace OpenNest.IO
|
||||
public SupportBedDto SupportBed { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>A machine configuration's id and the name it had when the nest was saved.</summary>
|
||||
public record MachineDto
|
||||
{
|
||||
public Guid Id { get; init; }
|
||||
public string Name { get; init; } = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a malformed or wrongly typed machine, or one without a valid id, as none instead
|
||||
/// of failing the whole nest. A missing or wrongly typed name reads as empty.
|
||||
/// </summary>
|
||||
public sealed class LenientMachineConverter : JsonConverter<MachineDto>
|
||||
{
|
||||
public override MachineDto Read(ref Utf8JsonReader reader, Type typeToConvert,
|
||||
JsonSerializerOptions options)
|
||||
{
|
||||
using var document = JsonDocument.ParseValue(ref reader);
|
||||
var machine = document.RootElement;
|
||||
if (machine.ValueKind != JsonValueKind.Object
|
||||
|| !machine.TryGetProperty("id", out var id) || id.ValueKind != JsonValueKind.String
|
||||
|| !Guid.TryParse(id.GetString(), out var guid) || guid == Guid.Empty)
|
||||
return null;
|
||||
var name = machine.TryGetProperty("name", out var nameElement) && nameElement.ValueKind == JsonValueKind.String
|
||||
? nameElement.GetString()
|
||||
: "";
|
||||
return new MachineDto { Id = guid, Name = name };
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, MachineDto value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
writer.WriteString("id", value.Id);
|
||||
writer.WriteString("name", value.Name ?? "");
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A support bed layout. <see cref="Type"/> names the layout: only <c>grid</c>, a regular
|
||||
/// grid of contact points, so far. Lengths are in the nest's units.
|
||||
|
||||
@@ -539,6 +539,7 @@ namespace OpenNest.IO
|
||||
? status
|
||||
: NestStatus.Quote;
|
||||
nest.MadeBy = dto.MadeBy ?? "";
|
||||
nest.Machine = dto.Machine is { } machine ? new NestMachine(machine.Id, machine.Name) : null;
|
||||
|
||||
// Nest-level material and thickness (fall back to PlateDefaults for old files)
|
||||
var pd = dto.PlateDefaults;
|
||||
|
||||
@@ -105,6 +105,9 @@ namespace OpenNest.IO
|
||||
AssistGas = nest.AssistGas ?? "",
|
||||
Status = nest.Status.ToString(),
|
||||
MadeBy = nest.MadeBy ?? "",
|
||||
Machine = nest.Machine is { } machine
|
||||
? new MachineDto { Id = machine.Id, Name = machine.Name }
|
||||
: null,
|
||||
Thickness = nest.Thickness,
|
||||
Material = new MaterialDto
|
||||
{
|
||||
|
||||
@@ -166,4 +166,44 @@ public class LocalJsonProviderTests : IDisposable
|
||||
Assert.NotNull(loaded);
|
||||
Assert.Equal(1, loaded.SchemaVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SaveMachine_RoundTripsTheSupportGrid()
|
||||
{
|
||||
var provider = CreateProvider();
|
||||
var machine = new MachineConfig
|
||||
{
|
||||
Name = "Plasma",
|
||||
SupportGrid = new SupportGridSettings
|
||||
{
|
||||
Enabled = true,
|
||||
Units = Units.Millimeters,
|
||||
PitchX = 50,
|
||||
PitchY = 40,
|
||||
OffsetX = -5,
|
||||
StabilityMargin = 6,
|
||||
},
|
||||
};
|
||||
|
||||
provider.SaveMachine(machine);
|
||||
var grid = provider.GetMachine(machine.Id)!.SupportGrid!;
|
||||
|
||||
Assert.True(grid.Enabled);
|
||||
Assert.Equal(Units.Millimeters, grid.Units);
|
||||
Assert.Equal(50, grid.PitchX);
|
||||
Assert.Equal(40, grid.PitchY);
|
||||
Assert.Equal(-5, grid.OffsetX);
|
||||
Assert.Equal(6, grid.StabilityMargin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MachineWithoutSupportGrid_LoadsWithNone()
|
||||
{
|
||||
var provider = CreateProvider();
|
||||
var machine = new MachineConfig { Name = "Laser" };
|
||||
|
||||
provider.SaveMachine(machine);
|
||||
|
||||
Assert.Null(provider.GetMachine(machine.Id)!.SupportGrid);
|
||||
}
|
||||
}
|
||||
@@ -307,4 +307,49 @@ public class NestDefaultsTests : IDisposable
|
||||
Assert.Equal(1, loaded.PartSpacing);
|
||||
Assert.Equal(new Spacing(1, 1, 1, 1), loaded.EdgeSpacing);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MachineId_RoundTrips()
|
||||
{
|
||||
var id = Guid.NewGuid();
|
||||
new NestDefaults { MachineId = id }.Save(_path);
|
||||
|
||||
Assert.Equal(id, NestDefaults.Load(_path).MachineId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MachineId_Unset_IsNotWrittenAndLoadsAsNull()
|
||||
{
|
||||
new NestDefaults().Save(_path);
|
||||
|
||||
Assert.DoesNotContain("machineId", File.ReadAllText(_path));
|
||||
Assert.Null(NestDefaults.Load(_path).MachineId);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("42")]
|
||||
[InlineData("\"not-a-guid\"")]
|
||||
[InlineData("\"00000000-0000-0000-0000-000000000000\"")]
|
||||
public void MachineId_Invalid_LoadsAsNullAndKeepsOtherFields(string machineId)
|
||||
{
|
||||
File.WriteAllText(_path, $"{{\"partSpacing\": 4, \"machineId\": {machineId}}}");
|
||||
|
||||
var loaded = NestDefaults.Load(_path, out var status);
|
||||
|
||||
Assert.Equal(NestDefaultsStatus.Ok, status);
|
||||
Assert.Null(loaded.MachineId);
|
||||
Assert.Equal(4, loaded.PartSpacing);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FromNest_AndConvertedTo_KeepTheMachine()
|
||||
{
|
||||
var id = Guid.NewGuid();
|
||||
var nest = new Nest { Units = Units.Inches, Machine = new NestMachine(id, "Plasma") };
|
||||
|
||||
var defaults = NestDefaults.FromNest(nest);
|
||||
|
||||
Assert.Equal(id, defaults.MachineId);
|
||||
Assert.Equal(id, defaults.ConvertedTo(Units.Millimeters).MachineId);
|
||||
}
|
||||
}
|
||||
@@ -415,7 +415,7 @@ namespace OpenNest.Forms
|
||||
var importErrors = new List<string>();
|
||||
// Read when the nests are created, warning (once per session) like New does.
|
||||
var clamps = MachineSettings.LoadClampSettings(this);
|
||||
var supportGrid = MachineSettings.LoadSupportGridSettings();
|
||||
var machine = MachineSettings.DefaultMachine(_defaults, MachineSettings.LoadMachines());
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
@@ -439,10 +439,10 @@ namespace OpenNest.Forms
|
||||
jobName,
|
||||
nest =>
|
||||
{
|
||||
// As New does: saved defaults, then the machine clamps in those units.
|
||||
// As New does: saved defaults, then the machine clamps and grid in those units.
|
||||
_defaults.ApplyTo(nest);
|
||||
clamps.ApplyToNewNest(nest);
|
||||
supportGrid.ApplyToNewNest(nest);
|
||||
MachineSettings.AssignMachine(nest, machine);
|
||||
}
|
||||
);
|
||||
importErrors.AddRange(result.Errors);
|
||||
|
||||
@@ -79,9 +79,57 @@ namespace OpenNest.Forms
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <summary>The persisted machine support grid; never throws, and loads as off when unreadable.</summary>
|
||||
public static SupportGridSettings LoadSupportGridSettings() =>
|
||||
SupportGridSettings.Load(SupportGridSettings.DefaultPath);
|
||||
/// <summary>
|
||||
/// The machine new nests are assigned: the nest defaults' machine when it is on file,
|
||||
/// otherwise the first by name, or null when there are none.
|
||||
/// </summary>
|
||||
public static MachineConfig DefaultMachine(NestDefaults defaults, IEnumerable<MachineConfig> machines)
|
||||
{
|
||||
var sorted = machines.OrderBy(m => m.Name, StringComparer.CurrentCultureIgnoreCase).ToList();
|
||||
return sorted.FirstOrDefault(m => m.Id == defaults?.MachineId) ?? sorted.FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>The configuration of <paramref name="machine"/>, or null when none is assigned or it is not on file.</summary>
|
||||
public static MachineConfig FindMachine(NestMachine machine)
|
||||
{
|
||||
if (machine == null)
|
||||
return null;
|
||||
try
|
||||
{
|
||||
return CreateMachineProvider().GetMachine(machine.Id);
|
||||
}
|
||||
catch (IOException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns <paramref name="machine"/> to <paramref name="nest"/> (null for none) and gives
|
||||
/// every sheet that machine's support grid, or none when the machine gives nests no grid.
|
||||
/// </summary>
|
||||
public static void AssignMachine(Nest nest, MachineConfig machine)
|
||||
{
|
||||
nest.Machine = machine == null ? null : new NestMachine(machine.Id, machine.Name);
|
||||
var grid = LoadSupportGridSettings(machine);
|
||||
nest.SetSupportBed(grid.Enabled ? grid.GridFor(nest.Units) : null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The support grid of <paramref name="machine"/>; a machine without one saved yet, or no
|
||||
/// machine, uses the legacy shared support-grid.json. Never throws, and loads as off when unreadable.
|
||||
/// </summary>
|
||||
public static SupportGridSettings LoadSupportGridSettings(MachineConfig machine) =>
|
||||
machine?.SupportGrid ?? SupportGridSettings.Load(SupportGridSettings.DefaultPath);
|
||||
|
||||
/// <summary>Saves <paramref name="settings"/> as the support grid of the machine with <paramref name="machineId"/>.</summary>
|
||||
public static void SaveSupportGridSettings(Guid machineId, SupportGridSettings settings)
|
||||
{
|
||||
var provider = CreateMachineProvider();
|
||||
var machine = provider.GetMachine(machineId)
|
||||
?? throw new IOException("The machine configuration is no longer on file.");
|
||||
machine.SupportGrid = settings;
|
||||
provider.SaveMachine(machine);
|
||||
}
|
||||
|
||||
/// <summary>The single desktop entry point for the persisted machine clamp settings.</summary>
|
||||
public static ClampSettings LoadSavedClampSettings(out ClampSettingsStatus status) =>
|
||||
|
||||
Generated
+9
-1
@@ -93,6 +93,7 @@ namespace OpenNest.Forms
|
||||
mnuNestEdit = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuNestClamps = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuNestSupportGrid = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuNestMachine = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuNestImportDrawing = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuNestShapeLibrary = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuNestDrawingLibrary = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -600,7 +601,7 @@ namespace OpenNest.Forms
|
||||
//
|
||||
// mnuNest
|
||||
//
|
||||
mnuNest.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuNestEdit, mnuNestClamps, mnuNestSupportGrid, mnuNestImportDrawing, mnuNestShapeLibrary, mnuNestDrawingLibrary, toolStripMenuItem7, mnuNestFirstPlate, mnuNestLastPlate, toolStripMenuItem6, mnuNestNextPlate, mnuNestPreviousPlate, toolStripMenuItem12, runAutoNestToolStripMenuItem, autoSequenceAllPlatesToolStripMenuItem, mnuNestRemoveEmptyPlates, mnuNestClear, mnuNestValidate, mnuNestPost, toolStripMenuItem19, calculateCutTimeToolStripMenuItem, toolStripMenuItem22, mnuNestAutomaticCutOff, mnuNestPlanCutting, mnuNestRemoveLeadIns });
|
||||
mnuNest.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuNestEdit, mnuNestMachine, mnuNestClamps, mnuNestSupportGrid, mnuNestImportDrawing, mnuNestShapeLibrary, mnuNestDrawingLibrary, toolStripMenuItem7, mnuNestFirstPlate, mnuNestLastPlate, toolStripMenuItem6, mnuNestNextPlate, mnuNestPreviousPlate, toolStripMenuItem12, runAutoNestToolStripMenuItem, autoSequenceAllPlatesToolStripMenuItem, mnuNestRemoveEmptyPlates, mnuNestClear, mnuNestValidate, mnuNestPost, toolStripMenuItem19, calculateCutTimeToolStripMenuItem, toolStripMenuItem22, mnuNestAutomaticCutOff, mnuNestPlanCutting, mnuNestRemoveLeadIns });
|
||||
mnuNest.Name = "mnuNest";
|
||||
mnuNest.Size = new System.Drawing.Size(43, 20);
|
||||
mnuNest.Text = "&Nest";
|
||||
@@ -612,6 +613,12 @@ namespace OpenNest.Forms
|
||||
mnuNestEdit.Size = new System.Drawing.Size(205, 22);
|
||||
mnuNestEdit.Text = "Edit";
|
||||
mnuNestEdit.Click += EditNest_Click;
|
||||
//
|
||||
// mnuNestMachine
|
||||
//
|
||||
mnuNestMachine.Name = "mnuNestMachine";
|
||||
mnuNestMachine.Size = new System.Drawing.Size(205, 22);
|
||||
mnuNestMachine.Text = "Machine";
|
||||
//
|
||||
// mnuNestClamps
|
||||
//
|
||||
@@ -1378,6 +1385,7 @@ namespace OpenNest.Forms
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuNestEdit;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuNestClamps;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuNestSupportGrid;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuNestMachine;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuPlateEditClamps;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuNestImportDrawing;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuNestShapeLibrary;
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using OpenNest.Collections;
|
||||
using OpenNest.Data;
|
||||
using OpenNest.Engine.Fill;
|
||||
using OpenNest.Forms.Commands;
|
||||
|
||||
@@ -45,6 +46,56 @@ namespace OpenNest.Forms
|
||||
mnuNestDrawingLibrary.ToolTipText = databaseMode ? "" : NestStorage.DatabaseModeOnly;
|
||||
// Parts can be added without a plate change, so refresh the clear state on open.
|
||||
mnuNestClear.Enabled = activeForm?.PlateManager.CanClearAll ?? false;
|
||||
BuildMachineMenu();
|
||||
}
|
||||
|
||||
// Lists the machines on file, checking the active nest's; one assigned but no longer on
|
||||
// file is shown checked and disabled so the nest still says what it was made for.
|
||||
private void BuildMachineMenu()
|
||||
{
|
||||
mnuNestMachine.DropDownItems.Clear();
|
||||
var nest = activeForm?.Nest;
|
||||
mnuNestMachine.Enabled = nest != null;
|
||||
if (nest == null)
|
||||
{
|
||||
mnuNestMachine.DropDownItems.Add(new ToolStripMenuItem("(no nest open)") { Enabled = false });
|
||||
return;
|
||||
}
|
||||
|
||||
var machines = MachineSettings.LoadMachines()
|
||||
.OrderBy(m => m.Name, StringComparer.CurrentCultureIgnoreCase)
|
||||
.ToList();
|
||||
foreach (var machine in machines)
|
||||
{
|
||||
var item = new ToolStripMenuItem(machine.Name) { Checked = machine.Id == nest.Machine?.Id };
|
||||
item.Click += (_, _) => AssignMachine(machine);
|
||||
mnuNestMachine.DropDownItems.Add(item);
|
||||
}
|
||||
if (nest.Machine is { } assigned && machines.All(m => m.Id != assigned.Id))
|
||||
mnuNestMachine.DropDownItems.Add(new ToolStripMenuItem($"{assigned.Name} (not on file)") { Checked = true, Enabled = false });
|
||||
if (mnuNestMachine.DropDownItems.Count == 0)
|
||||
mnuNestMachine.DropDownItems.Add(new ToolStripMenuItem("(no machines; see Tools > Machine Configuration)") { Enabled = false });
|
||||
}
|
||||
|
||||
// Assigning a machine also puts every sheet on that machine's support grid.
|
||||
private void AssignMachine(MachineConfig machine)
|
||||
{
|
||||
var editForm = activeForm;
|
||||
if (editForm == null || editForm.Nest.Machine?.Id == machine.Id)
|
||||
return;
|
||||
|
||||
var nest = editForm.Nest;
|
||||
var views = ViewsOf(nest);
|
||||
if (IsPlateWorkBusy(views))
|
||||
{
|
||||
MessageBox.Show(this, "Finish or cancel the current nesting or plate action first.",
|
||||
"Machine", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
MachineSettings.AssignMachine(nest, machine);
|
||||
foreach (var view in views)
|
||||
view.Invalidate();
|
||||
}
|
||||
|
||||
private async void EditNest_Click(object sender, EventArgs e)
|
||||
@@ -100,7 +151,12 @@ namespace OpenNest.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
using var form = new SupportGridForm(nest.SupportBed, nest.Units, MachineSettings.LoadSupportGridSettings());
|
||||
var machine = MachineSettings.FindMachine(nest.Machine);
|
||||
Action<SupportGridSettings> save = machine == null
|
||||
? null
|
||||
: settings => MachineSettings.SaveSupportGridSettings(machine.Id, settings);
|
||||
using var form = new SupportGridForm(nest.SupportBed, nest.Units, MachineSettings.LoadSupportGridSettings(machine),
|
||||
machine?.Name ?? nest.Machine?.Name, save);
|
||||
if (form.ShowDialog(this) != DialogResult.OK)
|
||||
return;
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace OpenNest.Forms
|
||||
|
||||
private void NestDefaults_Click(object sender, EventArgs e)
|
||||
{
|
||||
using (var form = new NestDefaultsForm(MachineSettings.LoadSavedNestDefaults(out _)))
|
||||
using (var form = new NestDefaultsForm(MachineSettings.LoadSavedNestDefaults(out _), MachineSettings.LoadMachines()))
|
||||
{
|
||||
if (form.ShowDialog(this) == DialogResult.OK)
|
||||
form.GetDefaults().Save(NestDefaults.DefaultPath);
|
||||
@@ -183,9 +183,10 @@ namespace OpenNest.Forms
|
||||
if (activeForm == null)
|
||||
return;
|
||||
|
||||
NestDefaults
|
||||
.FromPlate(activeForm.Nest.Units, activeForm.PlateView.Plate)
|
||||
.Save(NestDefaults.DefaultPath);
|
||||
var defaults = NestDefaults.FromPlate(activeForm.Nest.Units, activeForm.PlateView.Plate);
|
||||
// The nest's machine becomes the default; a nest without one keeps the saved choice.
|
||||
defaults.MachineId = activeForm.Nest.Machine?.Id ?? MachineSettings.LoadSavedNestDefaults(out _).MachineId;
|
||||
defaults.Save(NestDefaults.DefaultPath);
|
||||
}
|
||||
|
||||
private void MachineConfig_Click(object sender, EventArgs e)
|
||||
|
||||
+40
-14
@@ -47,6 +47,8 @@ namespace OpenNest.Forms
|
||||
this.edgeTopBox = new OpenNest.Controls.NumericUpDown();
|
||||
this.quadrantLabel = new System.Windows.Forms.Label();
|
||||
this.quadrantSelect1 = new OpenNest.Controls.QuadrantSelect();
|
||||
this.machineLabel = new System.Windows.Forms.Label();
|
||||
this.machineCombo = new System.Windows.Forms.ComboBox();
|
||||
this.saveButton = new System.Windows.Forms.Button();
|
||||
this.cancelButton = new System.Windows.Forms.Button();
|
||||
((System.ComponentModel.ISupportInitialize)(this.widthBox)).BeginInit();
|
||||
@@ -82,19 +84,22 @@ namespace OpenNest.Forms
|
||||
this.tableLayoutPanel1.Controls.Add(this.edgeTopBox, 1, 7);
|
||||
this.tableLayoutPanel1.Controls.Add(this.quadrantLabel, 0, 8);
|
||||
this.tableLayoutPanel1.Controls.Add(this.quadrantSelect1, 1, 8);
|
||||
this.tableLayoutPanel1.Controls.Add(this.machineLabel, 0, 9);
|
||||
this.tableLayoutPanel1.Controls.Add(this.machineCombo, 1, 9);
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(12, 12);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 9;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(410, 260);
|
||||
this.tableLayoutPanel1.RowCount = 10;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(410, 288);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// unitsLabel
|
||||
@@ -286,11 +291,30 @@ namespace OpenNest.Forms
|
||||
this.quadrantSelect1.Size = new System.Drawing.Size(120, 28);
|
||||
this.quadrantSelect1.TabIndex = 17;
|
||||
//
|
||||
// machineLabel
|
||||
//
|
||||
this.machineLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.machineLabel.AutoSize = true;
|
||||
this.machineLabel.Location = new System.Drawing.Point(3, 263);
|
||||
this.machineLabel.Name = "machineLabel";
|
||||
this.machineLabel.Size = new System.Drawing.Size(100, 16);
|
||||
this.machineLabel.TabIndex = 18;
|
||||
this.machineLabel.Text = "Machine:";
|
||||
//
|
||||
// machineCombo
|
||||
//
|
||||
this.machineCombo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.machineCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.machineCombo.Location = new System.Drawing.Point(109, 259);
|
||||
this.machineCombo.Name = "machineCombo";
|
||||
this.machineCombo.Size = new System.Drawing.Size(298, 24);
|
||||
this.machineCombo.TabIndex = 19;
|
||||
//
|
||||
// saveButton
|
||||
//
|
||||
this.saveButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.saveButton.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.saveButton.Location = new System.Drawing.Point(243, 285);
|
||||
this.saveButton.Location = new System.Drawing.Point(243, 313);
|
||||
this.saveButton.Name = "saveButton";
|
||||
this.saveButton.Size = new System.Drawing.Size(90, 28);
|
||||
this.saveButton.TabIndex = 1;
|
||||
@@ -301,7 +325,7 @@ namespace OpenNest.Forms
|
||||
//
|
||||
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.cancelButton.Location = new System.Drawing.Point(339, 285);
|
||||
this.cancelButton.Location = new System.Drawing.Point(339, 313);
|
||||
this.cancelButton.Name = "cancelButton";
|
||||
this.cancelButton.Size = new System.Drawing.Size(90, 28);
|
||||
this.cancelButton.TabIndex = 2;
|
||||
@@ -313,7 +337,7 @@ namespace OpenNest.Forms
|
||||
this.AcceptButton = this.saveButton;
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||
this.CancelButton = this.cancelButton;
|
||||
this.ClientSize = new System.Drawing.Size(434, 322);
|
||||
this.ClientSize = new System.Drawing.Size(434, 350);
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.Controls.Add(this.saveButton);
|
||||
this.Controls.Add(this.cancelButton);
|
||||
@@ -358,6 +382,8 @@ namespace OpenNest.Forms
|
||||
private OpenNest.Controls.NumericUpDown edgeTopBox;
|
||||
private System.Windows.Forms.Label quadrantLabel;
|
||||
private OpenNest.Controls.QuadrantSelect quadrantSelect1;
|
||||
private System.Windows.Forms.Label machineLabel;
|
||||
private System.Windows.Forms.ComboBox machineCombo;
|
||||
private System.Windows.Forms.Button saveButton;
|
||||
private System.Windows.Forms.Button cancelButton;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenNest.Data;
|
||||
using OpenNest.Geometry;
|
||||
@@ -11,10 +13,26 @@ namespace OpenNest.Forms
|
||||
/// </summary>
|
||||
public partial class NestDefaultsForm : Form
|
||||
{
|
||||
public NestDefaultsForm(NestDefaults defaults)
|
||||
private sealed record MachineChoice(MachineConfig Machine)
|
||||
{
|
||||
public override string ToString() => Machine.Name;
|
||||
}
|
||||
|
||||
private readonly Guid? savedMachineId;
|
||||
|
||||
/// <param name="machines">The machines new nests can be assigned.</param>
|
||||
public NestDefaultsForm(NestDefaults defaults, IEnumerable<MachineConfig> machines)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
savedMachineId = defaults.MachineId;
|
||||
var sorted = machines.OrderBy(m => m.Name, StringComparer.CurrentCultureIgnoreCase).ToList();
|
||||
foreach (var machine in sorted)
|
||||
machineCombo.Items.Add(new MachineChoice(machine));
|
||||
var selected = MachineSettings.DefaultMachine(defaults, sorted);
|
||||
machineCombo.SelectedItem = machineCombo.Items.Cast<MachineChoice>().FirstOrDefault(c => c.Machine == selected);
|
||||
machineCombo.Enabled = machineCombo.Items.Count > 0;
|
||||
|
||||
unitsCombo.SelectedIndex = defaults.Units == Units.Millimeters ? 1 : 0;
|
||||
widthBox.Value = Clamp(widthBox, defaults.Size.Width);
|
||||
lengthBox.Value = Clamp(lengthBox, defaults.Size.Length);
|
||||
@@ -42,6 +60,8 @@ namespace OpenNest.Forms
|
||||
(double)edgeRightBox.Value,
|
||||
(double)edgeTopBox.Value
|
||||
),
|
||||
// With no machines on file there is nothing to choose, so keep the saved choice.
|
||||
MachineId = (machineCombo.SelectedItem as MachineChoice)?.Machine.Id ?? savedMachineId,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ using OpenNest.Properties;
|
||||
namespace OpenNest.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates File > New nests: machine defaults and clamps, then the year's next name
|
||||
/// Creates File > New nests: nest defaults, clamps, the default machine and its support grid, then the year's next name
|
||||
/// (<see cref="NestNames"/>). In Database mode the nest server allocates the number so
|
||||
/// every PC shares one sequence; when it cannot, <see cref="Settings.NestNumber"/> is the
|
||||
/// local fallback, kept above every number the server handed out and reset each year.
|
||||
@@ -39,9 +39,9 @@ namespace OpenNest.Forms
|
||||
var nest = new Nest();
|
||||
var defaults = MachineSettings.LoadNestDefaults();
|
||||
(units is { } converted ? defaults.ConvertedTo(converted) : defaults).ApplyTo(nest);
|
||||
// After the defaults so the rail is converted to the new nest's units.
|
||||
// After the defaults so the rail and grid are converted to the new nest's units.
|
||||
MachineSettings.LoadClampSettings(owner).ApplyToNewNest(nest);
|
||||
MachineSettings.LoadSupportGridSettings().ApplyToNewNest(nest);
|
||||
MachineSettings.AssignMachine(nest, MachineSettings.DefaultMachine(defaults, MachineSettings.LoadMachines()));
|
||||
return nest;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,13 +11,13 @@ namespace OpenNest.Forms;
|
||||
/// Nest > Support Grid...: edits the laser grid of contact points every sheet of the current
|
||||
/// nest rests on, used to judge whether cut parts stay level and where support tabs go (see
|
||||
/// docs/support-tabs.md). OK applies it to the nest; Cancel discards the edits. Save as Machine
|
||||
/// Defaults writes support-grid.json immediately and is not undone by Cancel.
|
||||
/// Defaults writes the grid to the nest's machine configuration immediately and is not undone by Cancel.
|
||||
/// </summary>
|
||||
public sealed class SupportGridForm : Form
|
||||
{
|
||||
private readonly Units units;
|
||||
private readonly SupportGridSettings machineDefaults;
|
||||
private readonly string settingsPath;
|
||||
private readonly Action<SupportGridSettings> saveMachineDefaults;
|
||||
private readonly CheckBox useGridBox;
|
||||
private readonly NumericUpDown pitchXBox;
|
||||
private readonly NumericUpDown pitchYBox;
|
||||
@@ -28,11 +28,16 @@ public sealed class SupportGridForm : Form
|
||||
private readonly CheckBox applyToNewNestsBox;
|
||||
private readonly Label savedLabel;
|
||||
|
||||
public SupportGridForm(SupportBed bed, Units units, SupportGridSettings machineDefaults, string settingsPath = null)
|
||||
/// <param name="machineName">The nest's machine, or null when none is assigned.</param>
|
||||
/// <param name="saveMachineDefaults">
|
||||
/// Saves the grid as that machine's; null disables saving, when the nest has no machine on file.
|
||||
/// </param>
|
||||
public SupportGridForm(SupportBed bed, Units units, SupportGridSettings machineDefaults, string machineName,
|
||||
Action<SupportGridSettings> saveMachineDefaults)
|
||||
{
|
||||
this.units = units;
|
||||
this.machineDefaults = machineDefaults ?? new SupportGridSettings();
|
||||
this.settingsPath = settingsPath ?? SupportGridSettings.DefaultPath;
|
||||
this.saveMachineDefaults = saveMachineDefaults;
|
||||
var grid = bed as SupportGrid;
|
||||
// A nest without a grid starts from the machine defaults, so enabling it is one click.
|
||||
var initial = grid != null
|
||||
@@ -86,7 +91,12 @@ public sealed class SupportGridForm : Form
|
||||
AddRow(values, "Stability margin:", marginBox, unit);
|
||||
layout.Controls.Add(values);
|
||||
|
||||
var defaultsGroup = new GroupBox { Text = "Machine defaults (support-grid.json)", AutoSize = true, Padding = new Padding(8) };
|
||||
var defaultsGroup = new GroupBox
|
||||
{
|
||||
Text = string.IsNullOrEmpty(machineName) ? "Machine defaults (no machine assigned)" : $"Machine defaults ({machineName})",
|
||||
AutoSize = true,
|
||||
Padding = new Padding(8),
|
||||
};
|
||||
var defaultsLayout = new FlowLayoutPanel
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
@@ -96,7 +106,7 @@ public sealed class SupportGridForm : Form
|
||||
};
|
||||
applyToNewNestsBox = new CheckBox
|
||||
{
|
||||
Text = "Give new nests this grid",
|
||||
Text = "Give nests on this machine this grid",
|
||||
AutoSize = true,
|
||||
Checked = this.machineDefaults.Enabled,
|
||||
};
|
||||
@@ -109,8 +119,12 @@ public sealed class SupportGridForm : Form
|
||||
{
|
||||
AutoSize = true,
|
||||
MaximumSize = new Size(410, 0),
|
||||
Text = "Save as Machine Defaults writes the file immediately; Cancel below does not undo it.",
|
||||
Text = saveMachineDefaults == null
|
||||
? "Assign this nest a machine on file in Nest > Machine to save its grid."
|
||||
: "Save as Machine Defaults writes the machine configuration immediately; Cancel below does not undo it.",
|
||||
};
|
||||
applyToNewNestsBox.Enabled = saveMachineDefaults != null;
|
||||
saveDefaultsButton.Enabled = saveMachineDefaults != null;
|
||||
defaultsLayout.Controls.Add(applyToNewNestsBox);
|
||||
defaultsLayout.Controls.Add(defaultsButtons);
|
||||
defaultsLayout.Controls.Add(savedLabel);
|
||||
@@ -172,14 +186,14 @@ public sealed class SupportGridForm : Form
|
||||
var settings = Read();
|
||||
try
|
||||
{
|
||||
settings.Save(settingsPath);
|
||||
saveMachineDefaults(settings);
|
||||
savedLabel.Text = settings.Enabled
|
||||
? $"Saved {DateTime.Now:t}: new nests get this grid. Cancel does not undo this."
|
||||
: $"Saved {DateTime.Now:t}: new nests get no grid. Cancel does not undo this.";
|
||||
? $"Saved {DateTime.Now:t}: nests on this machine get this grid. Cancel does not undo this."
|
||||
: $"Saved {DateTime.Now:t}: nests on this machine get no grid. Cancel does not undo this.";
|
||||
}
|
||||
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or ArgumentException)
|
||||
{
|
||||
MessageBox.Show(this, $"The machine defaults could not be saved:\n{settingsPath}\n\n{ex.Message}",
|
||||
MessageBox.Show(this, $"The machine defaults could not be saved:\n\n{ex.Message}",
|
||||
Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,12 @@ Status and made-by are additive: files written before them load as Quote with an
|
||||
empty maker, and an unrecognized status value likewise falls back to Quote. Builds
|
||||
before `Draft` therefore open a Draft nest as Quote, and saving it there keeps Quote.
|
||||
|
||||
`machine` optionally names the machine the nest is cut on: `id` (its machine
|
||||
configuration's GUID) and `name` (the configuration's name when assigned, so the nest
|
||||
still says what it was made for on a PC without that configuration). The key is omitted
|
||||
when no machine is assigned. A non-object, a missing, non-string, unparseable or empty
|
||||
`id` loads as no machine; a missing or non-string `name` loads as empty.
|
||||
|
||||
## Programs and placements
|
||||
|
||||
- `programs/program-N` is drawing N's clean G-code program; optional
|
||||
|
||||
@@ -23,9 +23,14 @@ Every bed also carries:
|
||||
|
||||
The bed belongs to the nest (`Nest.SetSupportBed`); every plate follows it, including plates
|
||||
added later. It is display, analysis and tab placement only: never material, spacing or a
|
||||
keep-out. Nest > Support Grid... edits it; Save as Machine Defaults writes
|
||||
`%APPDATA%\OpenNest\support-grid.json`, which new nests receive while it is enabled. The
|
||||
nest file stores it in `plateDefaults.supportBed` (see [nest file format](nest-file-format.md)).
|
||||
keep-out. Nest > Support Grid... edits it; Save as Machine Defaults writes it to the nest's
|
||||
machine configuration (`MachineConfig.SupportGrid`), which nests assigned that machine receive
|
||||
while it is enabled: File > New and BOM import assign the Tools > Nest Defaults machine (the
|
||||
first by name when none is chosen), and Nest > Machine reassigns a nest and replaces its grid
|
||||
with the new machine's (none when that machine gives nests no grid). A machine with no grid
|
||||
saved yet uses the legacy shared `%APPDATA%\OpenNest\support-grid.json`. The nest file stores
|
||||
the bed in `plateDefaults.supportBed` and the machine in `machine` (see
|
||||
[nest file format](nest-file-format.md)).
|
||||
|
||||
## The support check
|
||||
|
||||
|
||||
Reference in new issue
Block a user