mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-15 15:55:36 -05:00
PlateEdits ports the WinForms plate view's edits of the selection, with its undo labels and coalescing: Delete (parts and cut-offs, cut-offs regenerated once when the plate has any), Nudge by the offset increment or one repeat step, Push to contact, Rotate about the selection's centre keeping its lower-left corner (a quarter turn, or by wheel notches at 10 degrees or a tenth of that), repeated nudges and wheel turns undoing as one step. The Select tool drags the selection as one Move step. Cut-offs regenerate when a drag actually moved parts (WinForms also does it on a plain click, adding an extra undo step); the regeneration runs before the step completes, so a failure rolls the drag back, and a view that loses the pointer mid-drag ends the move as a release would, keeping the selection. A plate tool host now has to supply its undo wiring, the nest's cut-off settings and an edits lock (WinForms EditsLocked): while locked no edit runs and no press selects or starts a move.
130 lines
4.4 KiB
C#
130 lines
4.4 KiB
C#
using System;
|
|
using OpenNest.CutOffs;
|
|
using OpenNest.Desktop.Rendering;
|
|
using OpenNest.Geometry;
|
|
using OpenNest.Undo;
|
|
|
|
namespace OpenNest.Desktop.Interaction;
|
|
|
|
/// <summary>The mouse button behind a pointer event.</summary>
|
|
public enum ToolButton
|
|
{
|
|
None,
|
|
Left,
|
|
Middle,
|
|
Right,
|
|
}
|
|
|
|
/// <summary>Modifier keys held during a pointer event.</summary>
|
|
[Flags]
|
|
public enum ToolModifiers
|
|
{
|
|
None = 0,
|
|
Shift = 1,
|
|
Control = 2,
|
|
Alt = 4,
|
|
}
|
|
|
|
/// <summary>
|
|
/// A pointer event as a plate tool sees it: where it is in plate coordinates and on screen, the
|
|
/// button pressed or released (for a move, the button held), and the modifier keys.
|
|
/// </summary>
|
|
public readonly record struct ToolPointer(Vector World, ScreenPoint Screen, ToolButton Button, ToolModifiers Modifiers);
|
|
|
|
/// <summary>What a plate tool works on: the view that hosts it, in either desktop app.</summary>
|
|
public interface IPlateToolHost
|
|
{
|
|
/// <summary>The plate shown, or null.</summary>
|
|
Plate Plate { get; }
|
|
|
|
PlateSelection Selection { get; }
|
|
|
|
PlateHitTester HitTester { get; }
|
|
|
|
/// <summary>The view's world/screen mapping, for tolerances given in pixels.</summary>
|
|
ViewTransform View { get; }
|
|
|
|
/// <summary>Requests a redraw.</summary>
|
|
void Invalidate();
|
|
|
|
/// <summary>
|
|
/// Opens one undoable edit of the plate (see <see cref="NestUndoRecorder.BeginChange"/>). A
|
|
/// view without a nest history records nothing.
|
|
/// </summary>
|
|
ChangeScope BeginChange(string label, object coalesceKey = null);
|
|
|
|
/// <summary>
|
|
/// The settings cut-offs are rebuilt with after an edit moves or removes parts.
|
|
/// </summary>
|
|
CutOffSettings CutOffSettings { get; }
|
|
|
|
/// <summary>
|
|
/// True while the plate must not be edited, as the WinForms view's <c>EditsLocked</c>: the
|
|
/// nest is locked (Auto Nest is running on it; later, an inspection panel shows it). Edits
|
|
/// and drag-moves are refused; panning and zooming stay live.
|
|
/// </summary>
|
|
bool EditsLocked { get; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// One interactive plate-view tool, toolkit-neutral: the view forwards pointer events to the
|
|
/// active tool and draws what it exposes. Exactly one tool is active at a time; see
|
|
/// <see cref="PlateToolManager"/>.
|
|
/// </summary>
|
|
public abstract class PlateTool
|
|
{
|
|
protected PlateTool(IPlateToolHost host)
|
|
{
|
|
Host = host ?? throw new ArgumentNullException(nameof(host));
|
|
}
|
|
|
|
protected IPlateToolHost Host { get; }
|
|
|
|
/// <summary>The name shown in the status bar.</summary>
|
|
public abstract string Name { get; }
|
|
|
|
/// <summary>Status bar guidance shown after the name, or null for the name alone.</summary>
|
|
public virtual string Hint => null;
|
|
|
|
/// <summary>Whether the tool is mid-task, so Escape cancels that task rather than ending the tool.</summary>
|
|
public abstract bool IsBusy { get; }
|
|
|
|
/// <summary>Whether Escape from Select may bring this tool back after it ends.</summary>
|
|
public virtual bool ResumeOnEscape => true;
|
|
|
|
/// <summary>Whether the tool stays active when the view shows another plate.</summary>
|
|
public virtual bool SurvivesPlateChange => false;
|
|
|
|
/// <summary>Raised when <see cref="Hint"/> changes.</summary>
|
|
public event EventHandler HintChanged;
|
|
|
|
/// <summary>Called when the tool becomes active (again, when Escape resumes it).</summary>
|
|
public virtual void Activate() { }
|
|
|
|
/// <summary>Called when the tool stops being active, after <see cref="Cancel"/>.</summary>
|
|
public virtual void Deactivate() { }
|
|
|
|
/// <summary>Abandons the task in progress.</summary>
|
|
public abstract void Cancel();
|
|
|
|
/// <summary>Called when a tool that survives plate changes sees another plate.</summary>
|
|
public virtual void OnPlateChanged() { }
|
|
|
|
/// <returns>Whether the tool used the event.</returns>
|
|
public virtual bool PointerPressed(ToolPointer pointer) => false;
|
|
|
|
/// <returns>Whether the tool used the event.</returns>
|
|
public virtual bool PointerMoved(ToolPointer pointer) => false;
|
|
|
|
/// <returns>Whether the tool used the event.</returns>
|
|
public virtual bool PointerReleased(ToolPointer pointer) => false;
|
|
|
|
/// <summary>
|
|
/// The view lost the pointer mid-gesture (Alt+Tab during a drag, say), so no release will
|
|
/// follow: the tool ends the gesture in progress.
|
|
/// </summary>
|
|
public virtual void PointerCaptureLost() { }
|
|
|
|
protected void RaiseHintChanged() => HintChanged?.Invoke(this, EventArgs.Empty);
|
|
}
|