From 1ed66bbf20994a9c8842f0167a4f03c3a024a6c5 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Mon, 19 Oct 2026 12:15:40 -0400 Subject: [PATCH] fix(ui): point operator messages at commands that exist Pinned-lead and locked-lead warnings named a Drawing Pins Off command and a Clear Lead-ins command that the desktop does not have; name Plate > Remove Lead-ins and spacing instead. Closing Plan Cutting no longer claims nothing changed after lead-ins or cut-offs were cleared, the no-stock reason no longer says the part is larger than every sheet when only the usable area at the checked rotations is too small, and the console says whole-job engines. --- OpenNest.Console/Program.cs | 2 +- OpenNest.Core/CNC/CuttingPlanning/FixedLeadReview.cs | 4 ++-- OpenNest.Engine/CuttingPlanning/DrawingPinCapture.cs | 2 +- OpenNest.Engine/CuttingPlanning/FixedLeadWarnings.cs | 2 +- OpenNest.Engine/Jobs/NestUnplacedPart.cs | 2 +- OpenNest.Tests/CuttingPlanning/DrawingPinCaptureTests.cs | 2 +- OpenNest.Tests/CuttingPlanning/PinnedLeadWarningTests.cs | 4 ++-- OpenNest/Forms/CuttingInspectionPanel.cs | 2 +- docs/cutting-planner.md | 7 ++++--- 9 files changed, 14 insertions(+), 13 deletions(-) diff --git a/OpenNest.Console/Program.cs b/OpenNest.Console/Program.cs index c8f35f42..0a1fd5c1 100644 --- a/OpenNest.Console/Program.cs +++ b/OpenNest.Console/Program.cs @@ -111,7 +111,7 @@ static class NestConsole Console.Error.WriteLine( engine.IsJobEngine ? $"Error: engine '{engine.Name}' is a whole-job engine; single-plate fill supports: {string.Join(", ", PlateFillService.BuiltInStrategies)}. Use --autonest for whole-job engines." - : $"Error: unknown engine '{engine.Name}'. Fill strategies: {string.Join(", ", PlateFillService.BuiltInStrategies)} (jobs engines such as StockLadder require --autonest)" + : $"Error: unknown engine '{engine.Name}'. Fill strategies: {string.Join(", ", PlateFillService.BuiltInStrategies)} (whole-job engines such as StockLadder require --autonest)" ); return 1; } diff --git a/OpenNest.Core/CNC/CuttingPlanning/FixedLeadReview.cs b/OpenNest.Core/CNC/CuttingPlanning/FixedLeadReview.cs index e9c6d6f4..5d62d7f3 100644 --- a/OpenNest.Core/CNC/CuttingPlanning/FixedLeadReview.cs +++ b/OpenNest.Core/CNC/CuttingPlanning/FixedLeadReview.cs @@ -77,8 +77,8 @@ internal static class FixedLeadReview if (part.LeadInsLocked) { if (part.HasActiveDrawingPins) - NotApplied(index, "the part's locked lead-ins override them. Clear Lead-ins and plan cutting " - + "to apply the pins."); + NotApplied(index, "the part's locked lead-ins override them. Use Plate > Remove Lead-ins, " + + "then Plan Cutting, to apply the pins."); } else { diff --git a/OpenNest.Engine/CuttingPlanning/DrawingPinCapture.cs b/OpenNest.Engine/CuttingPlanning/DrawingPinCapture.cs index c9888b1e..a41a9a32 100644 --- a/OpenNest.Engine/CuttingPlanning/DrawingPinCapture.cs +++ b/OpenNest.Engine/CuttingPlanning/DrawingPinCapture.cs @@ -41,7 +41,7 @@ internal static class DrawingPinCapture /// internal static CuttingPlanFinding NotApplied(Part source, int ordinal) => new(ordinal, source, null, null, PostVerificationKind.FixedLead, source.LeadInsLocked - ? $"Locked lead-ins override drawing pins on part {ordinal + 1}; Clear Lead-ins to apply the pins." + ? $"Locked lead-ins override drawing pins on part {ordinal + 1}; use Plate > Remove Lead-ins, then Plan Cutting, to apply the pins." : $"Drawing pins on part {ordinal + 1} are not applied: the part is not regenerated.") { FixedLead = new(null, null, null) }; diff --git a/OpenNest.Engine/CuttingPlanning/FixedLeadWarnings.cs b/OpenNest.Engine/CuttingPlanning/FixedLeadWarnings.cs index c0c7cdf2..0b2f9419 100644 --- a/OpenNest.Engine/CuttingPlanning/FixedLeadWarnings.cs +++ b/OpenNest.Engine/CuttingPlanning/FixedLeadWarnings.cs @@ -16,7 +16,7 @@ internal static class FixedLeadWarnings + "unlock this part's lead-ins and replan."; private const string PinnedAdvice = "The pinned contour is cut exactly as its drawing says. Increase spacing " - + "or switch off drawing pins for this part (right-click > Drawing Pins Off)."; + + "or move this part away from the part it meets, then replan."; /// A replay-checker finding (rapid crossing or retention) inside the fixed emission. internal static CuttingPlanFinding FromChecker(CuttingPlanSnapshot snapshot, FixedProgramPlacement source, diff --git a/OpenNest.Engine/Jobs/NestUnplacedPart.cs b/OpenNest.Engine/Jobs/NestUnplacedPart.cs index c468f80d..8d690351 100644 --- a/OpenNest.Engine/Jobs/NestUnplacedPart.cs +++ b/OpenNest.Engine/Jobs/NestUnplacedPart.cs @@ -36,7 +36,7 @@ public sealed record NestUnplacedPart(string PartId, Drawing Drawing, int Count, public static string Describe(NestUnplacedReason reason) => reason switch { NestUnplacedReason.ProposalNotKeepable => "the proposal cannot be kept", - NestUnplacedReason.NoStockFits => "larger than every offered sheet", + NestUnplacedReason.NoStockFits => "does not fit the usable area of any offered sheet at the rotations checked", NestUnplacedReason.FrameUnplaced => "reserved inside a cutout of a frame that was not placed", NestUnplacedReason.StockExhausted => "no sheets left", NestUnplacedReason.PlateLimitReached => "sheet limit reached", diff --git a/OpenNest.Tests/CuttingPlanning/DrawingPinCaptureTests.cs b/OpenNest.Tests/CuttingPlanning/DrawingPinCaptureTests.cs index ab2131ae..5477f82b 100644 --- a/OpenNest.Tests/CuttingPlanning/DrawingPinCaptureTests.cs +++ b/OpenNest.Tests/CuttingPlanning/DrawingPinCaptureTests.cs @@ -48,7 +48,7 @@ public class DrawingPinCaptureTests Assert.True(planned.HasOnlyFixedLeadWarnings); var warning = Assert.Single(planned.Result.Findings); Assert.Equal(PostVerificationKind.FixedLead, warning.Kind); - Assert.Equal("Locked lead-ins override drawing pins on part 1; Clear Lead-ins to apply the pins.", warning.Message); + Assert.Equal("Locked lead-ins override drawing pins on part 1; use Plate > Remove Lead-ins, then Plan Cutting, to apply the pins.", warning.Message); Assert.False(Assert.Single(planned.Result.ProposedOrder).IsRegenerated); Assert.Equal(CuttingCommitStatus.Applied, proposal.Apply(acceptWarnings: true).Status); Assert.Same(program, part.Program); diff --git a/OpenNest.Tests/CuttingPlanning/PinnedLeadWarningTests.cs b/OpenNest.Tests/CuttingPlanning/PinnedLeadWarningTests.cs index 6d50a2b6..65643da8 100644 --- a/OpenNest.Tests/CuttingPlanning/PinnedLeadWarningTests.cs +++ b/OpenNest.Tests/CuttingPlanning/PinnedLeadWarningTests.cs @@ -28,8 +28,8 @@ public class PinnedLeadWarningTests Assert.Same(neighbour, warning.OtherSourcePart); Assert.Equal(new FixedLeadWarning(1, 1, 1), warning.FixedLead); Assert.Equal("Drawing pin 1 lead on cutting contour 1 contacts or enters another part's material. " - + "The pinned contour is cut exactly as its drawing says. Increase spacing or switch off drawing pins " - + "for this part (right-click > Drawing Pins Off).", warning.Message); + + "The pinned contour is cut exactly as its drawing says. Increase spacing or move this part away " + + "from the part it meets, then replan.", warning.Message); // The search never relocates the pinned entry, and the neighbour is planned normally. var proposed = planned.Result.ProposedOrder; var placement = Assert.Single(proposed, p => ReferenceEquals(p.SourcePart, pinned)); diff --git a/OpenNest/Forms/CuttingInspectionPanel.cs b/OpenNest/Forms/CuttingInspectionPanel.cs index 46a2cc34..da095fac 100644 --- a/OpenNest/Forms/CuttingInspectionPanel.cs +++ b/OpenNest/Forms/CuttingInspectionPanel.cs @@ -1248,7 +1248,7 @@ internal sealed class CuttingInspectionPanel : UserControl ClearResult(); SetPlanning(true); cancelButton.Enabled = false; - SetStatus(Tone.Neutral, "Closing… nothing has changed."); + SetStatus(Tone.Neutral, "Closing… the preview was not applied."); validationCancellation?.Cancel(); inspection.RequestClose(); if (!IsPlanning) diff --git a/docs/cutting-planner.md b/docs/cutting-planner.md index bd2cfe14..53535ec0 100644 --- a/docs/cutting-planner.md +++ b/docs/cutting-planner.md @@ -425,8 +425,8 @@ clean contours with `CutPinResolver` and prepares them with - A pinned contour's lead-in, cut, lead-out and tab are a fixed emission like a locked program (see [fixed emissions](#fixed-emissions-warn)): a pinned lead that meets another part's material or its own part's (an already-cut hole included) is a `FixedLead` warning naming - the part, cutting contour, pin and the part hit, with the advice "Increase spacing or switch - off drawing pins for this part (right-click > Drawing Pins Off)". The entry is never moved + the part, cutting contour, pin and the part hit, with the advice "Increase spacing or move + this part away from the part it meets, then replan". The entry is never moved and the lead never shortened to fit; the feasibility precheck accepts it as given. The rapids between contours, including the one into a pinned contour, stay strict. Plan Cutting does not model clamps, for pinned leads or any other. @@ -435,7 +435,8 @@ clean contours with `CutPinResolver` and prepares them with is the shared test for "pins apply here". - A pinned part is regenerated like any unlocked part, whatever lead-ins or settings it carried before. A locked part keeps its exact locked program and warns "Locked lead-ins - override drawing pins on part N; Clear Lead-ins to apply the pins." It is not refused. An + override drawing pins on part N; use Plate > Remove Lead-ins, then Plan Cutting, to apply the + pins." It is not refused. An unlocked part a caller left ineligible warns that its pins are not applied. - The plate state compared by `Apply` includes each drawing's pin list (reference and exact content, `StateFingerprint.Of(pins)`) and each part's pins-off flag, so changing either