From afdf196754be235232b2b1e7713114e0d9f33d4f Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Thu, 29 Oct 2026 14:33:07 -0400 Subject: [PATCH] fix(help): let F1 set a placed part instead of opening help The Help menu's F1 shortcut took the key before the plate view, so F1 in Clone/Add Part opened help rather than setting the part in place as it always has. Actions can now claim F1; Clone does, and MainForm lets the key through to the plate view while it is active. Co-Authored-By: Claude Opus 5.5 --- .../Controls/ActionCloneTests.cs | 17 +++++++++++++++++ OpenNest/Actions/Action.cs | 3 +++ OpenNest/Actions/ActionClone.cs | 3 +++ OpenNest/Controls/PlateView.cs | 3 +++ OpenNest/Forms/MainForm.cs | 4 ++++ 5 files changed, 30 insertions(+) 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) {