mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-08 00:52:33 -04:00
fix(ui): detach disposed plate views and keep repeated layout parts
A disposed PlateView stayed subscribed to its plate, so a plate that outlived the view kept rebuilding the disposed view's layout and raising its events; Dispose now detaches the part added, removed and reordered handlers. ObservableList.Reorder keeps repeated references, but the reorder handler mapped each part to one layout, so [a, a, b] collapsed to one shared layout for both occurrences of a. It now reuses each existing layout once and creates one only when none is left.
This commit is contained in:
1 parent
8590f21c9c
commit
faf3c9bcc4
2 files changed
+58
-3
No files matched your search
@@ -29,6 +29,47 @@ public class PlateViewReorderTests
|
||||
Assert.Empty(view.LayoutParts);
|
||||
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
|
||||
|
||||
[Fact]
|
||||
public void KeepsOneLayoutPerOccurrenceOfARepeatedPart() => StaTestThread.Run(() =>
|
||||
{
|
||||
var plate = new Plate(100, 100);
|
||||
var repeated = new Part(new Drawing("repeated", Square()), new Vector(1, 1));
|
||||
var other = new Part(new Drawing("other", Square()), new Vector(12, 1));
|
||||
plate.Parts.Add(repeated);
|
||||
plate.Parts.Add(repeated);
|
||||
plate.Parts.Add(other);
|
||||
using var view = new PlateView { Plate = plate };
|
||||
var before = view.LayoutParts.ToArray();
|
||||
|
||||
plate.Parts.Reorder(new[] { other, repeated, repeated });
|
||||
|
||||
var after = view.LayoutParts;
|
||||
Assert.Equal(new[] { other, repeated, repeated }, after.Select(layout => layout.BasePart));
|
||||
Assert.Same(before[2], after[0]);
|
||||
Assert.Equal(3, after.Distinct().Count());
|
||||
Assert.Equal(before.ToHashSet(), after.ToHashSet());
|
||||
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
|
||||
|
||||
[Fact]
|
||||
public void DisposedViewIgnoresItsRetainedPlate() => StaTestThread.Run(() =>
|
||||
{
|
||||
var plate = new Plate(100, 100);
|
||||
foreach (var x in new[] { 1.0, 12.0 })
|
||||
plate.Parts.Add(new Part(new Drawing($"part {x}", Square()), new Vector(x, 1)));
|
||||
var parts = plate.Parts.ToArray();
|
||||
var view = new PlateView { Plate = plate };
|
||||
var raised = 0;
|
||||
view.PartsReordered += (_, _) => raised++;
|
||||
var layouts = view.LayoutParts.ToArray();
|
||||
|
||||
view.Dispose();
|
||||
plate.Parts.Reorder(new[] { parts[1], parts[0] });
|
||||
plate.Parts.Add(new Part(new Drawing("late", Square()), new Vector(23, 1)));
|
||||
|
||||
Assert.Equal(0, raised);
|
||||
Assert.Equal(layouts, view.LayoutParts);
|
||||
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
|
||||
|
||||
private static CNC.Program Square()
|
||||
{
|
||||
var program = new CNC.Program();
|
||||
|
||||
@@ -627,6 +627,13 @@ namespace OpenNest.Controls
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// A plate can outlive its view; stop it calling back into a disposed one.
|
||||
if (plate != null)
|
||||
{
|
||||
plate.PartAdded -= plate_PartAdded;
|
||||
plate.PartRemoved -= plate_PartRemoved;
|
||||
plate.PartsReordered -= plate_PartsReordered;
|
||||
}
|
||||
overlapOverlay?.Dispose();
|
||||
hoverTimer?.Dispose();
|
||||
hoverTimer = null;
|
||||
@@ -830,11 +837,18 @@ namespace OpenNest.Controls
|
||||
{
|
||||
// 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);
|
||||
// A reorder keeps repeated references, so reuse each existing layout once.
|
||||
var layouts = new Dictionary<Part, Queue<LayoutPart>>(ReferenceEqualityComparer.Instance);
|
||||
foreach (var layout in parts)
|
||||
layouts.TryAdd(layout.BasePart, layout);
|
||||
{
|
||||
if (!layouts.TryGetValue(layout.BasePart, out var queue))
|
||||
layouts.Add(layout.BasePart, queue = new Queue<LayoutPart>());
|
||||
queue.Enqueue(layout);
|
||||
}
|
||||
var reordered = plate.Parts
|
||||
.Select(part => layouts.TryGetValue(part, out var layout) ? layout : LayoutPart.Create(part, this))
|
||||
.Select(part => layouts.TryGetValue(part, out var queue) && queue.Count > 0
|
||||
? queue.Dequeue()
|
||||
: LayoutPart.Create(part, this))
|
||||
.ToList();
|
||||
parts.Clear();
|
||||
parts.AddRange(reordered);
|
||||
|
||||
Reference in new issue
Block a user