diff --git a/OpenNest.WinForms.Tests/Actions/ActionZoomWindowTests.cs b/OpenNest.WinForms.Tests/Actions/ActionZoomWindowTests.cs
new file mode 100644
index 00000000..eb0da5b5
--- /dev/null
+++ b/OpenNest.WinForms.Tests/Actions/ActionZoomWindowTests.cs
@@ -0,0 +1,87 @@
+using System.Drawing;
+using System.Windows.Forms;
+using OpenNest.Actions;
+using OpenNest.Controls;
+using OpenNest.Geometry;
+using static OpenNest.WinForms.Tests.FormTesting;
+
+namespace OpenNest.WinForms.Tests.Actions;
+
+/// Zoom To Area is a one-shot tool: a single zoom hands the view back to Select.
+public class ActionZoomWindowTests
+{
+ private static PlateView ZoomView()
+ {
+ var view = new PlateView { Plate = new Plate(48, 120), Size = new System.Drawing.Size(900, 450) };
+ view.ZoomToFit();
+ view.SetAction(typeof(ActionZoomWindow));
+ return view;
+ }
+
+ private static Point At(PlateView view, double x, double y) => view.PointWorldToControl(new Vector(x, y));
+
+ private static void Press(PlateView view, Point p) =>
+ Raise(view, "OnMouseDown", new MouseEventArgs(MouseButtons.Left, 1, p.X, p.Y, 0));
+
+ private static void Release(PlateView view, Point p) =>
+ Raise(view, "OnMouseUp", new MouseEventArgs(MouseButtons.Left, 1, p.X, p.Y, 0));
+
+ private static void Click(PlateView view, Point p)
+ {
+ Press(view, p);
+ Release(view, p);
+ }
+
+ [Fact]
+ public void DraggingAWindowZoomsAndReturnsToSelect() => StaTestThread.Run(() =>
+ {
+ using var view = ZoomView();
+ var scale = view.ViewScale;
+
+ Press(view, At(view, 5, 5));
+ Release(view, At(view, 20, 20));
+
+ Assert.True(view.ViewScale > scale);
+ Assert.IsType(view.Actions.CurrentAction);
+ }, TimeSpan.FromMinutes(1), "The STA test did not complete.");
+
+ [Fact]
+ public void ClickingTwoCornersZoomsAndReturnsToSelect() => StaTestThread.Run(() =>
+ {
+ using var view = ZoomView();
+ var scale = view.ViewScale;
+
+ Click(view, At(view, 5, 5));
+ Assert.IsType(view.Actions.CurrentAction);
+
+ Click(view, At(view, 20, 20));
+
+ Assert.True(view.ViewScale > scale);
+ Assert.IsType(view.Actions.CurrentAction);
+ }, TimeSpan.FromMinutes(1), "The STA test did not complete.");
+
+ [Fact]
+ public void EscapeFromSelectDoesNotBringTheToolBack() => StaTestThread.Run(() =>
+ {
+ using var view = ZoomView();
+
+ Press(view, At(view, 5, 5));
+ Release(view, At(view, 20, 20));
+ view.Actions.ProcessEscapeKey();
+
+ Assert.IsType(view.Actions.CurrentAction);
+ }, TimeSpan.FromMinutes(1), "The STA test did not complete.");
+
+ [Fact]
+ public void CancellingKeepsTheToolArmed() => StaTestThread.Run(() =>
+ {
+ using var view = ZoomView();
+ var scale = view.ViewScale;
+
+ Click(view, At(view, 5, 5));
+ view.Actions.ProcessEscapeKey();
+
+ Assert.Equal(scale, view.ViewScale);
+ Assert.IsType(view.Actions.CurrentAction);
+ }, TimeSpan.FromMinutes(1), "The STA test did not complete.");
+}
diff --git a/OpenNest/Actions/ActionZoomWindow.cs b/OpenNest/Actions/ActionZoomWindow.cs
index e2bf210f..b95df713 100644
--- a/OpenNest/Actions/ActionZoomWindow.cs
+++ b/OpenNest/Actions/ActionZoomWindow.cs
@@ -1,4 +1,4 @@
-using System.ComponentModel;
+using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using OpenNest.Controls;
@@ -17,6 +17,9 @@ namespace OpenNest.Actions
private Status status;
+ // One zoom ends this tool; Escape from Select must not bring it back.
+ public override bool ResumeOnEscape => false;
+
public ActionZoomWindow(PlateView plateView)
: base(plateView)
{
@@ -96,22 +99,22 @@ namespace OpenNest.Actions
var distance2 = plateView.LengthWorldToGui(distance1);
if (distance2 > 40)
- {
- ZoomWindow();
- CancelAction();
- }
+ ZoomAndFinish();
else
- {
status = Status.SetSecondPoint;
- }
}
else if (status == Status.SetSecondPoint)
{
- ZoomWindow();
- CancelAction();
+ ZoomAndFinish();
}
}
+ private void ZoomAndFinish()
+ {
+ ZoomWindow();
+ plateView.SetAction(typeof(ActionSelect));
+ }
+
private void plateView_Paint(object sender, PaintEventArgs e)
{
if (!Point1.IsValid() || !Point2.IsValid())