using System; using System.Collections.Generic; using OpenNest.CNC; namespace OpenNest; /// /// Captures drawing program text before an edit and rebuilds only the parts whose /// drawing program changed. Drawing keys use reference identity because names are editable. /// public sealed class DrawingProgramSnapshot { private readonly Dictionary programs; private readonly Func fingerprint; private DrawingProgramSnapshot( Dictionary programs, Func fingerprint) { this.programs = programs; this.fingerprint = fingerprint; } /// /// Capture before handing drawings to an editor, including its load operation: /// programs can be edited in place. The callback must include both the main /// program text and its hole sub-programs, and must not mutate the program. /// public static DrawingProgramSnapshot Capture( IEnumerable drawings, Func fingerprint) { ArgumentNullException.ThrowIfNull(drawings); ArgumentNullException.ThrowIfNull(fingerprint); var programs = new Dictionary(ReferenceEqualityComparer.Instance); foreach (var drawing in drawings) { if (!drawing.IsCutOff && !programs.ContainsKey(drawing)) programs.Add(drawing, fingerprint(drawing.Program)); } return new DrawingProgramSnapshot(programs, fingerprint); } /// /// Complete the captured edit by rebuilding changed drawings' parts across all plates. /// Part.Update preserves the placement and clears obsolete lead-ins, tabs and locks. /// Unchanged and uncaptured drawings' parts retain their program instances and state. /// Returns the rebuilt parts so a UI can invalidate just their graphics. /// public IReadOnlyList UpdateChangedParts(IEnumerable plates) { ArgumentNullException.ThrowIfNull(plates); var changed = new HashSet(ReferenceEqualityComparer.Instance); foreach (var entry in programs) { if (!entry.Key.IsCutOff && !string.Equals(entry.Value, fingerprint(entry.Key.Program), StringComparison.Ordinal)) changed.Add(entry.Key); } var updated = new List(); foreach (var plate in plates) { foreach (var part in plate.Parts) { if (!changed.Contains(part.BaseDrawing)) continue; part.Update(); updated.Add(part); } } return updated; } }