From 9f2ece37ed673d3baedbf318bd059cf2445fec9a Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Tue, 13 Oct 2026 20:39:43 -0400 Subject: [PATCH] feat(desktop): add automatic cut-offs, existing-work banner and clear button to the cutting planner --- .../Forms/CuttingInspectionPanelTests.cs | 106 ++++++++++ OpenNest/Forms/CuttingInspectionPanel.cs | 188 +++++++++++++++++- docs/cutting-planner.md | 13 ++ 3 files changed, 303 insertions(+), 4 deletions(-) diff --git a/OpenNest.WinForms.Tests/Forms/CuttingInspectionPanelTests.cs b/OpenNest.WinForms.Tests/Forms/CuttingInspectionPanelTests.cs index 5f11154e..18478437 100644 --- a/OpenNest.WinForms.Tests/Forms/CuttingInspectionPanelTests.cs +++ b/OpenNest.WinForms.Tests/Forms/CuttingInspectionPanelTests.cs @@ -436,6 +436,112 @@ public class CuttingInspectionPanelTests panel.RequestClose(); }); + [Fact] + public void AutomaticCutOffsAreStagedForThePlanAndRemovedOnCancelOrUntick() => RunSta(() => + { + using var editor = Editor(); + editor.Show(); + editor.PlateManager.LoadAt(0); + var plate = editor.PlateView.Plate; + var original = plate.Parts.ToArray(); + editor.OpenCuttingInspection(); + var panel = editor.CuttingInspection!; + PumpUntil(() => panel.Proposal != null && !panel.IsPlanning); + Assert.Empty(plate.CutOffs); + + Field(panel, "autoCutOffsCheckBox").Checked = true; + PumpUntil(() => panel.Proposal != null && !panel.IsPlanning); + + Assert.NotNull(panel.StagedCutOffs); + Assert.NotEmpty(plate.CutOffs); + Assert.Equal(plate.CutOffs.Count, plate.Parts.Count(p => p.BaseDrawing.IsCutOff)); + Assert.Equal(plate.CutOffs.Count, panel.Proposal.Plates[0].Result.ProposedOrder.Count(p => p.IsCutOff)); + Assert.False(Field(panel, "existingWorkBanner").Visible); // Staged lines are not "existing". + + Field(panel, "autoCutOffsCheckBox").Checked = false; + PumpUntil(() => panel.Proposal != null && !panel.IsPlanning); + Assert.Null(panel.StagedCutOffs); + Assert.Empty(plate.CutOffs); + Assert.Equal(original, plate.Parts); + + Field(panel, "autoCutOffsCheckBox").Checked = true; + PumpUntil(() => panel.Proposal != null && !panel.IsPlanning); + Assert.NotEmpty(plate.CutOffs); + panel.RequestClose(); + Assert.Null(editor.CuttingInspection); + Assert.Empty(plate.CutOffs); + Assert.Equal(original, plate.Parts); + Assert.All(plate.Parts, part => Assert.False(part.HasManualLeadIns)); + }); + + [Fact] + public void ApplyKeepsTheStagedAutomaticCutOffsInThePlannedOrder() => RunSta(() => + { + using var editor = Editor(); + editor.Show(); + editor.PlateManager.LoadAt(0); + var plate = editor.PlateView.Plate; + editor.OpenCuttingInspection(); + var panel = editor.CuttingInspection!; + PumpUntil(() => panel.Proposal != null && !panel.IsPlanning); + Field(panel, "autoCutOffsCheckBox").Checked = true; + PumpUntil(() => panel.Proposal != null && !panel.IsPlanning); + var staged = panel.StagedCutOffs!.Definitions.ToArray(); + var planned = panel.Proposal.Plates[0].Result.ProposedOrder.Select(p => p.SourcePart).ToArray(); + + Field