mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-06 13:02:11 -04:00
feat(ui): redraw the plate view when its plate is reordered
PlateView now follows Plate.PartsReordered, which an applied cutting plan raises once per changed plate: it puts its layout parts in the plate's order (the drawn part numbers are the cutting order), marks them dirty so new programs are redrawn, and raises its own PartsReordered. The overlap overlay treats a reorder like any other part change and marks its report out of date.
This commit is contained in:
1 parent
9a4f73b924
commit
a0ac7e5756
3 files changed
+72
No files matched your search
@@ -0,0 +1,42 @@
|
||||
using OpenNest.Controls;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.WinForms.Tests.Controls;
|
||||
|
||||
public class PlateViewReorderTests
|
||||
{
|
||||
[Fact]
|
||||
public void FollowsAnInPlaceReorderOfItsCurrentPlateOnly() => StaTestThread.Run(() =>
|
||||
{
|
||||
var plate = new Plate(100, 100);
|
||||
foreach (var x in new[] { 1.0, 12.0, 23.0 })
|
||||
plate.Parts.Add(new Part(new Drawing($"part {x}", Square()), new Vector(x, 1)));
|
||||
using var view = new PlateView { Plate = plate };
|
||||
var parts = plate.Parts.ToArray();
|
||||
var raised = 0;
|
||||
view.PartsReordered += (_, _) => raised++;
|
||||
|
||||
plate.Parts.Reorder(new[] { parts[2], parts[0], parts[1] });
|
||||
|
||||
// Part numbers are drawn from the layout order, so it must follow the plate.
|
||||
Assert.Equal(1, raised);
|
||||
Assert.Equal(new[] { parts[2], parts[0], parts[1] }, view.LayoutParts.Select(layout => layout.BasePart));
|
||||
Assert.All(view.LayoutParts, layout => Assert.True(layout.IsDirty));
|
||||
|
||||
view.Plate = new Plate(60, 120);
|
||||
plate.Parts.Reorder(parts);
|
||||
Assert.Equal(1, raised);
|
||||
Assert.Empty(view.LayoutParts);
|
||||
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
|
||||
|
||||
private static CNC.Program Square()
|
||||
{
|
||||
var program = new CNC.Program();
|
||||
program.MoveTo(0, 0);
|
||||
program.LineTo(0, 10);
|
||||
program.LineTo(10, 10);
|
||||
program.LineTo(10, 0);
|
||||
program.LineTo(0, 0);
|
||||
return program;
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,7 @@ internal sealed class OverlapOverlayController : IDisposable
|
||||
observedParts.ItemAdded += PartAdded;
|
||||
observedParts.ItemRemoved += PartRemoved;
|
||||
observedParts.ItemChanged += PartChanged;
|
||||
observedParts.ItemsReordered += PartsReordered;
|
||||
}
|
||||
NotifyChanged();
|
||||
}
|
||||
@@ -333,6 +334,7 @@ internal sealed class OverlapOverlayController : IDisposable
|
||||
private void PartAdded(object sender, ItemAddedEventArgs<Part> e) => Invalidate();
|
||||
private void PartRemoved(object sender, ItemRemovedEventArgs<Part> e) => Invalidate();
|
||||
private void PartChanged(object sender, ItemChangedEventArgs<Part> e) => Invalidate();
|
||||
private void PartsReordered(object sender, EventArgs e) => Invalidate();
|
||||
|
||||
private void Unsubscribe()
|
||||
{
|
||||
@@ -341,6 +343,7 @@ internal sealed class OverlapOverlayController : IDisposable
|
||||
observedParts.ItemAdded -= PartAdded;
|
||||
observedParts.ItemRemoved -= PartRemoved;
|
||||
observedParts.ItemChanged -= PartChanged;
|
||||
observedParts.ItemsReordered -= PartsReordered;
|
||||
observedParts = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,12 @@ namespace OpenNest.Controls
|
||||
|
||||
public event EventHandler<ItemAddedEventArgs<Part>> PartAdded;
|
||||
public event EventHandler<ItemRemovedEventArgs<Part>> PartRemoved;
|
||||
|
||||
/// <summary>
|
||||
/// Raised after the plate's parts were reordered in place, for example by an applied cutting
|
||||
/// plan that also installed new programs. The view has already redrawn its parts in the new order.
|
||||
/// </summary>
|
||||
public event EventHandler PartsReordered;
|
||||
public event EventHandler StatusChanged;
|
||||
|
||||
public event EventHandler SelectionChanged
|
||||
@@ -200,6 +206,7 @@ namespace OpenNest.Controls
|
||||
{
|
||||
plate.PartAdded -= plate_PartAdded;
|
||||
plate.PartRemoved -= plate_PartRemoved;
|
||||
plate.PartsReordered -= plate_PartsReordered;
|
||||
parts.Clear();
|
||||
previewManager.Clear();
|
||||
selection.Clear();
|
||||
@@ -208,6 +215,7 @@ namespace OpenNest.Controls
|
||||
plate = p;
|
||||
plate.PartAdded += plate_PartAdded;
|
||||
plate.PartRemoved += plate_PartRemoved;
|
||||
plate.PartsReordered += plate_PartsReordered;
|
||||
|
||||
foreach (var part in plate.Parts)
|
||||
parts.Add(LayoutPart.Create(part, this));
|
||||
@@ -818,6 +826,25 @@ namespace OpenNest.Controls
|
||||
parts.RemoveAll(p => p.BasePart == e.Item);
|
||||
}
|
||||
|
||||
private void plate_PartsReordered(object sender, EventArgs e)
|
||||
{
|
||||
// Part numbers are drawn from the layout order, and an applied cutting plan can also
|
||||
// replace programs, so follow the plate's order and rebuild every part's graphics.
|
||||
var layouts = new Dictionary<Part, LayoutPart>(ReferenceEqualityComparer.Instance);
|
||||
foreach (var layout in parts)
|
||||
layouts.TryAdd(layout.BasePart, layout);
|
||||
var reordered = plate.Parts
|
||||
.Select(part => layouts.TryGetValue(part, out var layout) ? layout : LayoutPart.Create(part, this))
|
||||
.ToList();
|
||||
parts.Clear();
|
||||
parts.AddRange(reordered);
|
||||
foreach (var layout in parts)
|
||||
layout.IsDirty = true;
|
||||
|
||||
PartsReordered?.Invoke(this, EventArgs.Empty);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
public void DeselectAll() => selection.DeselectAll();
|
||||
|
||||
public void SelectAll() => selection.SelectAll();
|
||||
|
||||
Reference in new issue
Block a user