diff --git a/OpenNest.WinForms.Tests/Controls/ActionSequenceByPathTests.cs b/OpenNest.WinForms.Tests/Controls/ActionSequenceByPathTests.cs
new file mode 100644
index 00000000..a05b7929
--- /dev/null
+++ b/OpenNest.WinForms.Tests/Controls/ActionSequenceByPathTests.cs
@@ -0,0 +1,60 @@
+using OpenNest.Actions;
+using OpenNest.CNC;
+using OpenNest.Controls;
+using OpenNest.Geometry;
+
+namespace OpenNest.WinForms.Tests.Controls;
+
+///
+/// Sequence by Path mutes every part until a line reaches it, however the tool is started.
+///
+public class ActionSequenceByPathTests
+{
+ private static PlateView View()
+ {
+ var drawing = new Drawing("square", Square());
+ var plate = new Plate(48, 48);
+ plate.Parts.Add(new Part(drawing, new Vector(2, 2)));
+ plate.Parts.Add(new Part(drawing, new Vector(20, 2)));
+ var view = new PlateView { Plate = plate, Size = new System.Drawing.Size(600, 600) };
+ view.ZoomToFit();
+ return view;
+ }
+
+ private static Program Square()
+ {
+ var program = new Program();
+ program.Codes.Add(new RapidMove(0, 0));
+ program.Codes.Add(new LinearMove(4, 0));
+ program.Codes.Add(new LinearMove(4, 4));
+ program.Codes.Add(new LinearMove(0, 4));
+ program.Codes.Add(new LinearMove(0, 0));
+ return program;
+ }
+
+ [Fact]
+ public void StartingTheToolMutesEveryPart() => StaTestThread.Run(() =>
+ {
+ using var view = View();
+
+ view.SetAction(typeof(ActionSequenceByPath));
+
+ Assert.All(view.Plate.Parts, part => Assert.Contains(part, view.MutedParts!));
+ view.SetAction(typeof(ActionSelect));
+ Assert.Null(view.MutedParts);
+ }, TimeSpan.FromMinutes(1), "The STA test did not complete.");
+
+ [Fact]
+ public void RestartingTheToolKeepsEveryPartMuted() => StaTestThread.Run(() =>
+ {
+ using var view = View();
+
+ view.SetAction(typeof(ActionSequenceByPath));
+ view.SetAction(typeof(ActionSequenceByPath));
+
+ Assert.NotNull(view.MutedParts);
+ Assert.All(view.Plate.Parts, part => Assert.Contains(part, view.MutedParts!));
+ view.SetAction(typeof(ActionSelect));
+ Assert.Null(view.MutedParts);
+ }, TimeSpan.FromMinutes(1), "The STA test did not complete.");
+}
diff --git a/OpenNest/Actions/ActionSequenceByPath.cs b/OpenNest/Actions/ActionSequenceByPath.cs
index be0a481f..366afc10 100644
--- a/OpenNest/Actions/ActionSequenceByPath.cs
+++ b/OpenNest/Actions/ActionSequenceByPath.cs
@@ -38,6 +38,11 @@ namespace OpenNest.Actions
};
private List drawing;
private bool disconnecting;
+ private IReadOnlySet muted;
+
+ // Starting the tool again builds the new one before this one is cancelled and
+ // disconnected, so this one must leave the view's muting to its successor.
+ private bool OwnsView => ReferenceEquals(plateView.MutedParts, muted);
public override bool ResumeOnEscape => false;
@@ -69,6 +74,7 @@ namespace OpenNest.Actions
plateView.KeyDown += plateView_KeyDown;
plateView.Paint += plateView_Paint;
UpdateMuted(lines);
+ plateView.Invalidate();
}
private void plateView_MouseDown(object sender, MouseEventArgs e)
@@ -182,13 +188,14 @@ namespace OpenNest.Actions
/// Mutes the parts the lines do not reach, so what is left to sequence stands out.
private void UpdateMuted(IReadOnlyList> paths)
{
- var muted = new HashSet(ReferenceEqualityComparer.Instance);
+ var unreached = new HashSet(ReferenceEqualityComparer.Instance);
foreach (var part in plateView.Plate.Parts)
{
if (!DrawnPathSequencing.Reaches(paths, part))
- muted.Add(part);
+ unreached.Add(part);
}
- plateView.MutedParts = muted;
+ muted = unreached;
+ plateView.MutedParts = unreached;
}
private void plateView_Paint(object sender, PaintEventArgs e)
@@ -230,8 +237,11 @@ namespace OpenNest.Actions
plateView.MouseUp -= plateView_MouseUp;
plateView.KeyDown -= plateView_KeyDown;
plateView.Paint -= plateView_Paint;
- plateView.PreviewSequence = null;
- plateView.MutedParts = null;
+ if (OwnsView)
+ {
+ plateView.PreviewSequence = null;
+ plateView.MutedParts = null;
+ }
form.Close();
form.Dispose();
linePen.Dispose();
@@ -246,6 +256,8 @@ namespace OpenNest.Actions
public override void CancelAction()
{
drawing = null;
+ if (!OwnsView)
+ return;
plateView.PreviewSequence = null;
UpdateMuted(lines);
plateView.Invalidate();