diff --git a/OpenNest.WinForms.Tests/Controls/ActionCloneTests.cs b/OpenNest.WinForms.Tests/Controls/ActionCloneTests.cs
index 77ee4e84..a43f684e 100644
--- a/OpenNest.WinForms.Tests/Controls/ActionCloneTests.cs
+++ b/OpenNest.WinForms.Tests/Controls/ActionCloneTests.cs
@@ -60,4 +60,21 @@ public class ActionCloneTests
Assert.Empty(plate.Parts);
Assert.True(Assert.Single(view.SelectedParts).IsSelected);
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
+
+ [Fact]
+ public void F1SetsThePartInPlaceInsteadOfOpeningHelp() => StaTestThread.Run(() =>
+ {
+ var plate = new Plate(48, 96);
+ using var view = new PlateView { Plate = plate, Size = new System.Drawing.Size(600, 600) };
+ view.ZoomToFit();
+ view.SetAction(typeof(ActionClone), Square("new"));
+
+ Assert.True(view.ActionHandlesF1);
+ Raise(view, "OnKeyDown", new KeyEventArgs(Keys.F1));
+
+ Assert.Single(plate.Parts);
+
+ view.SetAction(typeof(ActionSelect));
+ Assert.False(view.ActionHandlesF1);
+ }, TimeSpan.FromMinutes(1), "The STA test did not complete.");
}
diff --git a/OpenNest/Actions/Action.cs b/OpenNest/Actions/Action.cs
index 5679e3a4..3a2bb6cc 100644
--- a/OpenNest/Actions/Action.cs
+++ b/OpenNest/Actions/Action.cs
@@ -39,6 +39,9 @@ namespace OpenNest.Actions
/// The help topic F1 opens while this action is active, or null for the general help.
public virtual string HelpTopic => null;
+ /// Whether the action uses F1 itself, so F1 reaches the plate view instead of opening help.
+ public virtual bool HandlesF1 => false;
+
public virtual void OnPlateChanged() { }
public virtual void ConnectEvents() { }
diff --git a/OpenNest/Actions/ActionClone.cs b/OpenNest/Actions/ActionClone.cs
index c3605ce7..eeeabaa0 100644
--- a/OpenNest/Actions/ActionClone.cs
+++ b/OpenNest/Actions/ActionClone.cs
@@ -110,6 +110,9 @@ namespace OpenNest.Actions
public override bool SurvivesPlateChange => true;
+ // F1 sets the part in place, as it always has; help stays on the Help menu.
+ public override bool HandlesF1 => true;
+
public override void OnPlateChanged() => SelectPreviews();
public override void ConnectEvents()
diff --git a/OpenNest/Controls/PlateView.cs b/OpenNest/Controls/PlateView.cs
index 68297236..be5d3438 100644
--- a/OpenNest/Controls/PlateView.cs
+++ b/OpenNest/Controls/PlateView.cs
@@ -883,6 +883,9 @@ namespace OpenNest.Controls
/// The help topic for the current action, or null when it has none.
public string ActionHelpTopic => actionManager.CurrentAction?.HelpTopic;
+ /// Whether the current action takes F1 for itself instead of help.
+ public bool ActionHandlesF1 => actionManager.CurrentAction?.HandlesF1 == true;
+
public void AlignSelected(AlignType alignType) => selection.AlignSelected(alignType);
public void AlignSelected(AlignType alignType, LayoutPart fixedPart) =>
diff --git a/OpenNest/Forms/MainForm.cs b/OpenNest/Forms/MainForm.cs
index 7a76dca7..50c3542d 100644
--- a/OpenNest/Forms/MainForm.cs
+++ b/OpenNest/Forms/MainForm.cs
@@ -99,6 +99,10 @@ namespace OpenNest.Forms
}
if (ProcessUndoKeys(keyData))
return true;
+ // A tool that uses F1 itself (Clone sets the part) gets it before help: skip the
+ // Help menu shortcut so the key reaches the plate view.
+ if (keyData == Keys.F1 && activeForm?.PlateView?.ActionHandlesF1 == true)
+ return false;
// F1 opens the active tool's topic before the Help menu's general help.
if (keyData == Keys.F1 && activeForm?.PlateView?.ActionHelpTopic is { } topic)
{