refactor: extract CutOffHandler from PlateView
Move cut-off drag interaction mechanics into a dedicated CutOffHandler class, reducing PlateView complexity and following the same pattern established by SelectionManager extraction in Task 1. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
81
OpenNest/Controls/CutOffHandler.cs
Normal file
81
OpenNest/Controls/CutOffHandler.cs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
using OpenNest.CNC;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenNest.Controls
|
||||||
|
{
|
||||||
|
internal class CutOffHandler
|
||||||
|
{
|
||||||
|
private readonly PlateView view;
|
||||||
|
private Dictionary<Part, Geometry.Entity> dragPerimeterCache;
|
||||||
|
|
||||||
|
public CutOffHandler(PlateView view)
|
||||||
|
{
|
||||||
|
this.view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDragging { get; private set; }
|
||||||
|
|
||||||
|
public CutOff TryStartDrag(Vector point, double tolerance)
|
||||||
|
{
|
||||||
|
var hitCutOff = GetCutOffAtPoint(point, tolerance);
|
||||||
|
if (hitCutOff == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
IsDragging = true;
|
||||||
|
dragPerimeterCache = Plate.BuildPerimeterCache(view.Plate);
|
||||||
|
return hitCutOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateDrag(Vector currentPoint, CutOff cutOff)
|
||||||
|
{
|
||||||
|
if (!IsDragging || cutOff == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cutOff.Axis == CutOffAxis.Vertical)
|
||||||
|
cutOff.Position = new Vector(currentPoint.X, cutOff.Position.Y);
|
||||||
|
else
|
||||||
|
cutOff.Position = new Vector(cutOff.Position.X, currentPoint.Y);
|
||||||
|
|
||||||
|
cutOff.Regenerate(view.Plate, view.CutOffSettings, dragPerimeterCache);
|
||||||
|
view.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndDrag()
|
||||||
|
{
|
||||||
|
if (!IsDragging)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IsDragging = false;
|
||||||
|
dragPerimeterCache = null;
|
||||||
|
view.Plate.RegenerateCutOffs(view.CutOffSettings);
|
||||||
|
view.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CutOff GetCutOffAtPoint(Vector point, double tolerance)
|
||||||
|
{
|
||||||
|
if (view.Plate?.CutOffs == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
foreach (var cutoff in view.Plate.CutOffs)
|
||||||
|
{
|
||||||
|
var program = cutoff.Drawing?.Program;
|
||||||
|
if (program == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (var i = 0; i < program.Codes.Count - 1; i += 2)
|
||||||
|
{
|
||||||
|
if (program.Codes[i] is RapidMove rapid &&
|
||||||
|
program.Codes[i + 1] is LinearMove linear)
|
||||||
|
{
|
||||||
|
var line = new Line(rapid.EndPoint, linear.EndPoint);
|
||||||
|
if (line.ClosestPointTo(point).DistanceTo(point) <= tolerance)
|
||||||
|
return cutoff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,8 +32,7 @@ namespace OpenNest.Controls
|
|||||||
private Action previousAction;
|
private Action previousAction;
|
||||||
private CutOffSettings cutOffSettings = new CutOffSettings();
|
private CutOffSettings cutOffSettings = new CutOffSettings();
|
||||||
private SelectionManager selection;
|
private SelectionManager selection;
|
||||||
private bool draggingCutOff;
|
private CutOffHandler cutOffHandler;
|
||||||
private Dictionary<Part, Geometry.Entity> dragPerimeterCache;
|
|
||||||
protected List<LayoutPart> parts;
|
protected List<LayoutPart> parts;
|
||||||
private List<LayoutPart> stationaryParts = new List<LayoutPart>();
|
private List<LayoutPart> stationaryParts = new List<LayoutPart>();
|
||||||
private List<LayoutPart> activeParts = new List<LayoutPart>();
|
private List<LayoutPart> activeParts = new List<LayoutPart>();
|
||||||
@@ -70,6 +69,7 @@ namespace OpenNest.Controls
|
|||||||
public ReadOnlyCollection<LayoutPart> Parts => new ReadOnlyCollection<LayoutPart>(parts);
|
public ReadOnlyCollection<LayoutPart> Parts => new ReadOnlyCollection<LayoutPart>(parts);
|
||||||
|
|
||||||
internal SelectionManager Selection => selection;
|
internal SelectionManager Selection => selection;
|
||||||
|
internal CutOffHandler CutOffs => cutOffHandler;
|
||||||
|
|
||||||
public event EventHandler<ItemAddedEventArgs<Part>> PartAdded;
|
public event EventHandler<ItemAddedEventArgs<Part>> PartAdded;
|
||||||
public event EventHandler<ItemRemovedEventArgs<Part>> PartRemoved;
|
public event EventHandler<ItemRemovedEventArgs<Part>> PartRemoved;
|
||||||
@@ -93,6 +93,7 @@ namespace OpenNest.Controls
|
|||||||
origin = new PointF();
|
origin = new PointF();
|
||||||
parts = new List<LayoutPart>();
|
parts = new List<LayoutPart>();
|
||||||
selection = new SelectionManager(this);
|
selection = new SelectionManager(this);
|
||||||
|
cutOffHandler = new CutOffHandler(this);
|
||||||
|
|
||||||
redrawTimer = new Timer()
|
redrawTimer = new Timer()
|
||||||
{
|
{
|
||||||
@@ -273,17 +274,18 @@ namespace OpenNest.Controls
|
|||||||
|
|
||||||
if (e.Button == MouseButtons.Left && currentAction is ActionSelect)
|
if (e.Button == MouseButtons.Left && currentAction is ActionSelect)
|
||||||
{
|
{
|
||||||
var hitCutOff = GetCutOffAtPoint(CurrentPoint, 5.0 / ViewScale);
|
var hitCutOff = cutOffHandler.TryStartDrag(CurrentPoint, 5.0 / ViewScale);
|
||||||
if (hitCutOff != null)
|
if (hitCutOff != null)
|
||||||
{
|
{
|
||||||
SelectedCutOff = hitCutOff;
|
selection.DeselectParts();
|
||||||
draggingCutOff = true;
|
selection.SelectedCutOffs.Clear();
|
||||||
dragPerimeterCache = Plate.BuildPerimeterCache(Plate);
|
selection.SelectedCutOffs.Add(hitCutOff);
|
||||||
|
Invalidate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SelectedCutOff = null;
|
selection.DeselectCutOffs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,12 +306,9 @@ namespace OpenNest.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (draggingCutOff && SelectedCutOff != null)
|
if (cutOffHandler.IsDragging && selection.SelectedCutOffs.Count > 0)
|
||||||
{
|
{
|
||||||
draggingCutOff = false;
|
cutOffHandler.EndDrag();
|
||||||
dragPerimeterCache = null;
|
|
||||||
Plate.RegenerateCutOffs(cutOffSettings);
|
|
||||||
Invalidate();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,15 +368,9 @@ namespace OpenNest.Controls
|
|||||||
|
|
||||||
lastPoint = e.Location;
|
lastPoint = e.Location;
|
||||||
|
|
||||||
if (draggingCutOff && SelectedCutOff != null)
|
if (cutOffHandler.IsDragging && selection.SelectedCutOffs.Count > 0)
|
||||||
{
|
{
|
||||||
if (SelectedCutOff.Axis == CutOffAxis.Vertical)
|
cutOffHandler.UpdateDrag(CurrentPoint, selection.SelectedCutOffs[0]);
|
||||||
SelectedCutOff.Position = new Vector(CurrentPoint.X, SelectedCutOff.Position.Y);
|
|
||||||
else
|
|
||||||
SelectedCutOff.Position = new Vector(SelectedCutOff.Position.X, CurrentPoint.Y);
|
|
||||||
|
|
||||||
SelectedCutOff.Regenerate(Plate, cutOffSettings, dragPerimeterCache);
|
|
||||||
Invalidate();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,31 +559,7 @@ namespace OpenNest.Controls
|
|||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CutOff GetCutOffAtPoint(Vector point, double tolerance)
|
public CutOff GetCutOffAtPoint(Vector point, double tolerance) => cutOffHandler.GetCutOffAtPoint(point, tolerance);
|
||||||
{
|
|
||||||
if (Plate?.CutOffs == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
foreach (var cutoff in Plate.CutOffs)
|
|
||||||
{
|
|
||||||
var program = cutoff.Drawing?.Program;
|
|
||||||
if (program == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (var i = 0; i < program.Codes.Count - 1; i += 2)
|
|
||||||
{
|
|
||||||
if (program.Codes[i] is RapidMove rapid &&
|
|
||||||
program.Codes[i + 1] is LinearMove linear)
|
|
||||||
{
|
|
||||||
var line = new Geometry.Line(rapid.EndPoint, linear.EndPoint);
|
|
||||||
if (line.ClosestPointTo(point).DistanceTo(point) <= tolerance)
|
|
||||||
return cutoff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutPart GetPartAtControlPoint(Point pt) => selection.GetPartAtControlPoint(pt);
|
public LayoutPart GetPartAtControlPoint(Point pt) => selection.GetPartAtControlPoint(pt);
|
||||||
public LayoutPart GetPartAtGraphPoint(PointF pt) => selection.GetPartAtGraphPoint(pt);
|
public LayoutPart GetPartAtGraphPoint(PointF pt) => selection.GetPartAtGraphPoint(pt);
|
||||||
|
|||||||
Reference in New Issue
Block a user