using OpenNest.Engine.Fill; using OpenNest.Geometry; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; namespace OpenNest.Controls { internal class SelectionManager { private readonly PlateView view; private readonly List selectedParts = new List(); private readonly List selectedCutOffs = new List(); public SelectionManager(PlateView view) { this.view = view; } public List SelectedParts => selectedParts; public List SelectedCutOffs => selectedCutOffs; public event EventHandler SelectionChanged; public void DeselectAll() { selectedParts.ForEach(p => p.IsSelected = false); selectedParts.Clear(); selectedCutOffs.Clear(); SelectionChanged?.Invoke(view, EventArgs.Empty); } public void DeselectParts() { selectedParts.ForEach(p => p.IsSelected = false); selectedParts.Clear(); SelectionChanged?.Invoke(view, EventArgs.Empty); } public void DeselectCutOffs() { selectedCutOffs.Clear(); view.Invalidate(); } public void SelectAll() { var parts = view.LayoutParts; parts.ForEach(p => p.IsSelected = true); selectedParts.AddRange(parts); SelectionChanged?.Invoke(view, EventArgs.Empty); } public void NotifySelectionChanged() { SelectionChanged?.Invoke(view, EventArgs.Empty); } public void DeleteSelected() { if (selectedCutOffs.Count > 0) { foreach (var cutOff in selectedCutOffs) view.Plate.CutOffs.Remove(cutOff); selectedCutOffs.Clear(); view.Plate.RegenerateCutOffs(view.CutOffSettings); view.Invalidate(); } else { RemoveSelectedParts(); } } public void RemoveSelectedParts() { foreach (var part in selectedParts) view.Plate.Parts.Remove(part.BasePart); DeselectAll(); view.Invalidate(); } public void AlignSelected(AlignType alignType) { if (selectedParts.Count == 0) return; AlignSelected(alignType, selectedParts[0]); } public void AlignSelected(AlignType alignType, LayoutPart fixedPart) { switch (alignType) { case AlignType.Bottom: Align.Bottom(fixedPart.BasePart, selectedParts.Select(p => p.BasePart).ToList()); break; case AlignType.Horizontally: Align.Horizontally(fixedPart.BasePart, selectedParts.Select(p => p.BasePart).ToList()); break; case AlignType.Left: Align.Left(fixedPart.BasePart, selectedParts.Select(p => p.BasePart).ToList()); break; case AlignType.Right: Align.Right(fixedPart.BasePart, selectedParts.Select(p => p.BasePart).ToList()); break; case AlignType.Top: Align.Top(fixedPart.BasePart, selectedParts.Select(p => p.BasePart).ToList()); break; case AlignType.Vertically: Align.Vertically(fixedPart.BasePart, selectedParts.Select(p => p.BasePart).ToList()); break; case AlignType.EvenlySpaceHorizontally: Align.EvenlyDistributeHorizontally(selectedParts.Select(p => p.BasePart).ToList()); break; case AlignType.EvenlySpaceVertically: Align.EvenlyDistributeVertically(selectedParts.Select(p => p.BasePart).ToList()); break; default: return; } selectedParts.ForEach(p => p.IsDirty = true); view.Invalidate(); } public void RotateSelectedParts(double angle) { var parts = selectedParts.Select(p => p.BasePart).ToList(); var bounds = parts.GetBoundingBox(); var center = bounds.Center; var anchor = bounds.Location; for (var i = 0; i < selectedParts.Count; ++i) selectedParts[i].BasePart.Rotate(angle, center); var diff = anchor - parts.GetBoundingBox().Location; for (var i = 0; i < selectedParts.Count; ++i) selectedParts[i].Offset(diff); if (view.Plate.CutOffs.Count > 0) view.Plate.RegenerateCutOffs(view.CutOffSettings); } public void PushSelected(PushDirection direction) { var movingParts = selectedParts.Select(p => p.BasePart).ToList(); Compactor.Push(movingParts, view.Plate, direction); selectedParts.ForEach(p => p.IsDirty = true); view.Invalidate(); } public LayoutPart GetPartAtControlPoint(Point pt) { var pt2 = view.PointControlToGraph(pt); return GetPartAtGraphPoint(pt2); } public LayoutPart GetPartAtGraphPoint(PointF pt) { var parts = view.LayoutParts; for (var i = parts.Count - 1; i >= 0; --i) { if (parts[i].Path.IsVisible(pt)) return parts[i]; } return null; } public LayoutPart GetPartAtPoint(Vector pt) { var pt2 = view.PointWorldToGraph(pt); return GetPartAtGraphPoint(pt2); } public IList GetPartsFromWindow(RectangleF rect, SelectionType selectionType) { var list = new List(); var parts = view.LayoutParts; if (selectionType == SelectionType.Intersect) { for (var i = 0; i < parts.Count; ++i) { var part = parts[i]; var region = new Region(part.Path); if (region.IsVisible(rect)) list.Add(part); region.Dispose(); } } else { for (var i = 0; i < parts.Count; ++i) { var part = parts[i]; var bounds = part.Path.GetBounds(); if (rect.Contains(bounds)) list.Add(part); } } return list; } public void Clear() { selectedParts.Clear(); selectedCutOffs.Clear(); } } }