mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-30 04:21:06 -04:00
feat(cutoff): tell users Space turns the manual cut-off line
Issue #13 asked whether a Sheet Cut-Off can be rotated; Space already toggles vertical/horizontal, but nothing said so. The tool now shows a "Space: turn horizontal" tag by the pointer, spells out its keys in the status bar, and F1 opens a new sheet-cutoff help topic while it is active (actions can now supply a status hint and a help topic). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
41460481d6
commit
a1d20bdeb5
7 files changed
+93
-5
No files matched your search
@@ -0,0 +1,33 @@
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using OpenNest.Actions;
|
||||
using OpenNest.Controls;
|
||||
using OpenNest.Help;
|
||||
|
||||
namespace OpenNest.WinForms.Tests.Actions;
|
||||
|
||||
/// <summary>The manual cut-off tool says how to turn its line and where its help is.</summary>
|
||||
public class ActionCutOffHintTests
|
||||
{
|
||||
private static void PressKey(PlateView view, Keys key) =>
|
||||
typeof(Control).GetMethod("OnKeyDown", BindingFlags.Instance | BindingFlags.NonPublic)!
|
||||
.Invoke(view, new object[] { new KeyEventArgs(key) });
|
||||
|
||||
[Fact]
|
||||
public void StatusNamesTheAxisAndSpaceTurnsIt() => StaTestThread.Run(() =>
|
||||
{
|
||||
using var view = new PlateView { Plate = new Plate(48, 120) };
|
||||
|
||||
view.SetAction(typeof(ActionCutOff));
|
||||
Assert.Equal(
|
||||
"Sheet Cut-Off: click to add a vertical line, Space turns it horizontal, Esc finishes, F1 for help",
|
||||
view.Status);
|
||||
Assert.Equal(HelpTopics.SheetCutOff, view.ActionHelpTopic);
|
||||
|
||||
PressKey(view, Keys.Space);
|
||||
Assert.StartsWith("Sheet Cut-Off: click to add a horizontal line, Space turns it vertical", view.Status);
|
||||
|
||||
view.SetAction(typeof(ActionSelect));
|
||||
Assert.Null(view.ActionHelpTopic);
|
||||
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
|
||||
}
|
||||
@@ -33,6 +33,12 @@ namespace OpenNest.Actions
|
||||
/// </summary>
|
||||
public virtual bool ResumeOnEscape => true;
|
||||
|
||||
/// <summary>Status bar guidance shown after the action's name, or null for the name alone.</summary>
|
||||
public virtual string Hint => null;
|
||||
|
||||
/// <summary>The help topic F1 opens while this action is active, or null for the general help.</summary>
|
||||
public virtual string HelpTopic => null;
|
||||
|
||||
public virtual void OnPlateChanged() { }
|
||||
|
||||
public virtual void ConnectEvents() { }
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Windows.Forms;
|
||||
using OpenNest.CNC;
|
||||
using OpenNest.Controls;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Help;
|
||||
|
||||
namespace OpenNest.Actions
|
||||
{
|
||||
@@ -50,6 +51,17 @@ namespace OpenNest.Actions
|
||||
|
||||
public override bool IsBusy() => false;
|
||||
|
||||
public override string Hint =>
|
||||
$"click to add a {AxisName(lockedAxis)} line, Space turns it {AxisName(OtherAxis(lockedAxis))}, Esc finishes, F1 for help";
|
||||
|
||||
public override string HelpTopic => HelpTopics.SheetCutOff;
|
||||
|
||||
private static CutOffAxis OtherAxis(CutOffAxis axis) =>
|
||||
axis == CutOffAxis.Vertical ? CutOffAxis.Horizontal : CutOffAxis.Vertical;
|
||||
|
||||
private static string AxisName(CutOffAxis axis) =>
|
||||
axis == CutOffAxis.Vertical ? "vertical" : "horizontal";
|
||||
|
||||
private void OnMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
var pt = plateView.CurrentPoint;
|
||||
@@ -78,8 +90,8 @@ namespace OpenNest.Actions
|
||||
{
|
||||
if (e.KeyCode == Keys.Space)
|
||||
{
|
||||
lockedAxis =
|
||||
lockedAxis == CutOffAxis.Vertical ? CutOffAxis.Horizontal : CutOffAxis.Vertical;
|
||||
lockedAxis = OtherAxis(lockedAxis);
|
||||
plateView.RefreshActionStatus();
|
||||
|
||||
if (previewCutOff != null)
|
||||
{
|
||||
@@ -126,6 +138,22 @@ namespace OpenNest.Actions
|
||||
e.Graphics.DrawLine(pen, pt1, pt2);
|
||||
}
|
||||
}
|
||||
|
||||
DrawRotateTag(e.Graphics);
|
||||
}
|
||||
|
||||
// The status bar is easy to miss, so the cursor says how to turn the line.
|
||||
private void DrawRotateTag(Graphics g)
|
||||
{
|
||||
var text = $"Space: turn {AxisName(OtherAxis(lockedAxis))}";
|
||||
var cursor = plateView.PointWorldToGraph(plateView.CurrentPoint);
|
||||
var size = g.MeasureString(text, plateView.Font);
|
||||
var rect = new RectangleF(cursor.X + 16f, cursor.Y + 16f, size.Width + 6, size.Height + 4);
|
||||
|
||||
using (var background = new SolidBrush(Color.FromArgb(230, Color.White)))
|
||||
g.FillRectangle(background, rect);
|
||||
g.DrawRectangle(Pens.DimGray, rect.X, rect.Y, rect.Width, rect.Height);
|
||||
g.DrawString(text, plateView.Font, Brushes.Black, rect.X + 3, rect.Y + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ namespace OpenNest.Controls
|
||||
}
|
||||
|
||||
currentAction = action;
|
||||
view.Status = GetDisplayName(type);
|
||||
RefreshStatus();
|
||||
}
|
||||
|
||||
public void SetAction(Type type, params object[] args)
|
||||
@@ -63,7 +63,7 @@ namespace OpenNest.Controls
|
||||
return;
|
||||
|
||||
currentAction = action;
|
||||
view.Status = GetDisplayName(type);
|
||||
RefreshStatus();
|
||||
}
|
||||
|
||||
public void ProcessEscapeKey()
|
||||
@@ -98,7 +98,7 @@ namespace OpenNest.Controls
|
||||
action.ConnectEvents();
|
||||
currentAction = action;
|
||||
|
||||
view.Status = GetDisplayName(action.GetType());
|
||||
RefreshStatus();
|
||||
}
|
||||
|
||||
public void OnPlateChanged()
|
||||
@@ -119,6 +119,14 @@ namespace OpenNest.Controls
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Shows the current action's name and hint in the status bar.</summary>
|
||||
public void RefreshStatus()
|
||||
{
|
||||
var name = GetDisplayName(currentAction.GetType());
|
||||
var hint = currentAction.Hint;
|
||||
view.Status = string.IsNullOrEmpty(hint) ? name : $"{name}: {hint}";
|
||||
}
|
||||
|
||||
private string GetDisplayName(Type type)
|
||||
{
|
||||
var attributes = type.GetCustomAttributes(true);
|
||||
|
||||
@@ -866,6 +866,12 @@ namespace OpenNest.Controls
|
||||
public void SetAction(Type type, params object[] args) =>
|
||||
actionManager.SetAction(type, args);
|
||||
|
||||
/// <summary>Shows the current action's name and hint again after the hint changed.</summary>
|
||||
public void RefreshActionStatus() => actionManager.RefreshStatus();
|
||||
|
||||
/// <summary>The help topic for the current action, or null when it has none.</summary>
|
||||
public string ActionHelpTopic => actionManager.CurrentAction?.HelpTopic;
|
||||
|
||||
public void AlignSelected(AlignType alignType) => selection.AlignSelected(alignType);
|
||||
|
||||
public void AlignSelected(AlignType alignType, LayoutPart fixedPart) =>
|
||||
|
||||
@@ -99,6 +99,12 @@ namespace OpenNest.Forms
|
||||
}
|
||||
if (ProcessUndoKeys(keyData))
|
||||
return true;
|
||||
// F1 opens the active tool's topic before the Help menu's general help.
|
||||
if (keyData == Keys.F1 && activeForm?.PlateView?.ActionHelpTopic is { } topic)
|
||||
{
|
||||
HelpTopics.Show(this, topic);
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.ProcessCmdKey(ref msg, keyData);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace OpenNest.Help
|
||||
public const string AutoNest = "auto-nest";
|
||||
public const string Post = "post";
|
||||
public const string SupportGrid = "support-grid";
|
||||
public const string SheetCutOff = "sheet-cutoff";
|
||||
|
||||
/// <summary>Overrides the help folder, e.g. a local opennest-help <c>site/</c> build.</summary>
|
||||
public const string DirectoryVariable = "OPENNEST_HELP_DIR";
|
||||
|
||||
Reference in new issue
Block a user