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();