using System.Drawing; using System.Runtime.ExceptionServices; using System.Windows.Forms; using OpenNest.CNC; using OpenNest.Controls; using OpenNest.Diagnostics; using OpenNest.Forms; using OpenNest.Geometry; namespace OpenNest.WinForms.Tests.Forms; public class ValidateNestFormTests { [Fact] public void RapidContactCrosshairIsDrawnAtContactAndClearedWithFinding() { RunSta(() => { using var view = new PlateView(); view.ShowValidationFinding(new PostVerificationFinding(PostVerificationKind.RapidCrossing, 1, 2, 1, "crossing") { RapidStart = new Vector(-1, 0), RapidEnd = new Vector(1, 0), ContactPoints = Array.AsReadOnly(new[] { Vector.Zero }) }); using var bitmap = new Bitmap(120, 120); using var graphics = Graphics.FromImage(bitmap); graphics.TranslateTransform(60, 60); graphics.Clear(Color.Black); view.ValidationOverlay.Draw(graphics); // Off the horizontal rapid, on the contact's vertical crosshair. var pixel = bitmap.GetPixel(60, 65); Assert.True(pixel.R > 150 && pixel.B > 50 && pixel.G < 100); view.ClearValidationFinding(); graphics.Clear(Color.Black); view.ValidationOverlay.Draw(graphics); Assert.Equal(Color.Black.ToArgb(), bitmap.GetPixel(60, 65).ToArgb()); }); } #pragma warning disable xUnit1031 // Completed tasks on a dedicated STA thread. [Fact] public void GridNavigatesMainViewAndRestoresViewportOnDisposal() { RunSta(() => { var nest = new Nest("interactive inspection"); var program = new CNC.Program(); program.MoveTo(0, 0); program.LineTo(5, 0); program.LineTo(5, 5); program.LineTo(0, 5); program.LineTo(0, 0); nest.CreatePlate().Parts.Add(new Part(new Drawing("first", program))); var second = nest.CreatePlate(); second.Parts.Add(new Part(new Drawing("second", program))); second.Parts.Add(new Part(second.Parts[0].BaseDrawing) { Location = new Vector(2, 2) }); using var editor = new EditNestForm(nest); editor.Show(); editor.PlateManager.LoadAt(0); var view = editor.PlateView; view.ZoomToArea(-10, -10, 40, 40); var viewport = view.CaptureViewport(); view.OverlapDisplay = OverlapDisplayMode.Centroids; using (var form = new ValidateNestForm(editor, (value, token) => Task.FromResult(PostVerificationAnalyzer.Analyze(value, token)))) { form.Show(editor); form.ValidateAsync().GetAwaiter().GetResult(); Assert.True(form.TopLevel); Assert.False(form.Modal); Assert.True(editor.Enabled); Assert.True(view.Enabled); Assert.True(view.InspectionOnly); var grid = Find(form, "warningGrid"); Assert.True(grid.ReadOnly); Assert.Equal(DataGridViewSelectionMode.FullRowSelect, grid.SelectionMode); var row = grid.Rows.Cast().Single(row => row.Tag is PostVerificationFinding { Kind: PostVerificationKind.Overlap }); grid.CurrentCell = row.Cells[0]; Assert.Same(second, view.Plate); Assert.Equal(1, editor.PlateManager.CurrentIndex); Assert.NotNull(view.ValidationOverlay.Finding.Overlap); Assert.True(view.ValidationOverlay.IsAnimating); using var bitmap = new Bitmap(view.Width, view.Height); view.DrawToBitmap(bitmap, view.ClientRectangle); Assert.Contains("centroid", Find(form, "reportBox").Text); view.SelectAll(); var scale = view.ViewScale; Invoke(view, "OnMouseWheel", new MouseEventArgs(MouseButtons.None, 0, 100, 100, 120)); Assert.True(view.ViewScale > scale); var pan = view.CaptureViewport(); Invoke(view, "OnMouseMove", new MouseEventArgs(MouseButtons.Middle, 0, 120, 110, 0)); Assert.NotEqual(pan.Origin, view.CaptureViewport().Origin); Invoke(view, "OnKeyDown", new KeyEventArgs(Keys.Delete)); Invoke(view, "ProcessDialogKey", Keys.Right); Invoke(view, "OnMouseDown", new MouseEventArgs(MouseButtons.Middle, 1, 120, 110, 0)); Invoke(view, "OnMouseUp", new MouseEventArgs(MouseButtons.Middle, 1, 120, 110, 0)); Assert.Equal(2, second.Parts.Count); Assert.All(second.Parts, part => Assert.Equal(0, part.Rotation)); } Assert.Same(nest.Plates[0], view.Plate); Assert.Equal(viewport, view.CaptureViewport()); Assert.Equal(OverlapDisplayMode.Centroids, view.OverlapDisplay); Assert.Null(view.ValidationOverlay.Finding); Assert.False(view.ValidationOverlay.IsAnimating); Assert.False(view.InspectionOnly); Assert.Equal(new Vector(2, 2), second.Parts[1].Location); }); } [Fact] public void ModelessCancellationKeepsEditingLockedUntilWorkerStops() { RunSta(() => { var pending = new TaskCompletionSource(); using var editor = new EditNestForm(new Nest("inspection")); editor.Show(); using var form = new ValidateNestForm(editor, (_, _) => pending.Task); form.Show(editor); var validation = form.ValidateAsync(); Assert.False(validation.IsCompleted); Assert.True(editor.Enabled); Assert.True(editor.PlateView.Enabled); Assert.True(editor.PlateView.InspectionOnly); form.Close(); Assert.True(form.Visible); Assert.True(editor.PlateView.InspectionOnly); pending.SetCanceled(); var timeout = System.Diagnostics.Stopwatch.StartNew(); while (!form.IsDisposed && timeout.Elapsed < TimeSpan.FromSeconds(5)) Application.DoEvents(); Assert.True(form.IsDisposed); Assert.False(editor.PlateView.InspectionOnly); }); } [Fact] public void PlateSwitchClearsAnimation() { RunSta(() => { using var view = new PlateView(); view.ShowValidationFinding(new PostVerificationFinding(PostVerificationKind.MissingLeadIn, 1, 1, null, "missing") { Location = new Vector(3, 4) }); Assert.True(view.ValidationOverlay.IsAnimating); view.Plate = new Plate(); Assert.False(view.ValidationOverlay.IsAnimating); Assert.Null(view.ValidationOverlay.Finding); }); } [Fact] public void ChecksAllPlatesWithoutChangingProgramsOrPlacements() { RunSta(() => { var nest = new Nest("PEP inspection"); var program = new CNC.Program(); program.Codes.Add(new RapidMove(0, 0)); program.Codes.Add(new LinearMove(5, 0)); program.Codes.Add(new LinearMove(5, 5)); program.Codes.Add(new LinearMove(0, 5)); program.Codes.Add(new LinearMove(0, 0)); var first = new Part(new Drawing("square", program)); var second = new Part(first.BaseDrawing); nest.CreatePlate().Parts.Add(first); nest.CreatePlate().Parts.Add(second); var firstProgram = first.Program; var secondProgram = second.Program; var firstCodes = firstProgram.Codes.ToArray(); var location = first.Location; var rotation = first.Rotation; using var form = new ValidateNestForm(nest, (value, token) => Task.FromResult(PostVerificationAnalyzer.Analyze(value, token))); form.ValidateAsync().GetAwaiter().GetResult(); var report = Find(form, "reportBox"); Assert.True(report.ReadOnly); Assert.Contains("Plate 1, part 1", report.Text); Assert.Contains("Plate 2, part 1", report.Text); Assert.DoesNotContain("Post processor", report.Text); Assert.Contains("Warnings found", Find