merge: integrate refactor/menubar-reorg

Brings in the Plate menu reorganization, Database-mode drag-and-drop
open, the SavedNestsForm look fixes and the Irregular block-fill work
budget fix.

Conflicts:
- MainForm.Designer.cs: keep the branch's Plate menu order (Arrange
  submenu, View in CAD last) and add master's Plan Cutting item ahead
  of the lead-in commands.
- SavedNestsForm.cs: keep master's browser rewrite (details, preview,
  columns) and apply the branch's intent to it: open maximized with
  MaximizedBounds clear of the taskbar, the lighter grid palette on all
  three grids, and B/KB/MB/GB file sizes.
This commit is contained in:
aj committed 2026-10-06 06:39:41 -04:00
commit bc061488ee
8 files changed
+279 -176

No files matched your search

@@ -19,7 +19,7 @@ public class IrregularBlockTests
var job = Job(new[] { Part("ell", LShape(9, 7, 3), quantity, RotationPolicy.Automatic) },
new[] { Stock("sheet", 40, 60, spacing: 0.25) });
var types = PartCatalog.Build(job);
using var catalog = new BlockCatalog(0.25, types, NoPairs);
using var catalog = new BlockCatalog(0.25, types, NoPairs, new WorkCounter(), long.MaxValue);
Assert.Empty(catalog.Get(types[0], quantity, new Box(0, 0, 60, 40), CancellationToken.None));
Assert.Equal(0, catalog.PreparationCount);
}
@@ -31,7 +31,7 @@ public class IrregularBlockTests
new[] { Stock("sheet", 40, 60, spacing: 0.25) });
var types = PartCatalog.Build(job);
var original = types[0].Orientations.ToArray();
using var catalog = new BlockCatalog(0.25, types, NoPairs);
using var catalog = new BlockCatalog(0.25, types, NoPairs, new WorkCounter(), long.MaxValue);
var block = catalog.Get(types[0], 7, new Box(0, 0, 60, 40), CancellationToken.None);
Assert.Equal(7, block.Count);
Assert.Equal(original, types[0].Orientations);
@@ -79,7 +79,7 @@ public class IrregularBlockTests
var job = Job(new[] { Part("ell", LShape(9, 7, 3), 44, RotationPolicy.Automatic) }, new[] { stock });
var types = PartCatalog.Build(job);
var pairs = PairCatalog.Build(types, 0.25, 40, 30, CancellationToken.None);
using var blocks = new BlockCatalog(0.25, types, pairs);
using var blocks = new BlockCatalog(0.25, types, pairs, new WorkCounter(), long.MaxValue);
var before = new FrontierPacker(types, new NoFitCache(0.25), pairs, stock,
PackAxis.X, 1, new WorkCounter()).Fill(new[] { 44 }, CancellationToken.None);
var after = new FrontierPacker(types, new NoFitCache(0.25), pairs, stock,
@@ -97,7 +97,7 @@ public class IrregularBlockTests
var stock = Stock("sheet", 3, 3, spacing: 0.25);
var job = Job(new[] { Rectangle("box", 2, 2, 3) }, new[] { stock });
var types = PartCatalog.Build(job);
using var blocks = new BlockCatalog(0.25, types, NoPairs);
using var blocks = new BlockCatalog(0.25, types, NoPairs, new WorkCounter(), long.MaxValue);
Assert.Empty(blocks.Get(types[0], 3, new Box(0, 0, 3, 3), CancellationToken.None));
Assert.Equal(0, blocks.PreparationCount);
var fill = new FrontierPacker(types, new NoFitCache(0.25), NoPairs, stock,
@@ -158,7 +158,7 @@ public class IrregularBlockTests
{
var job = Job(new[] { Rectangle("box", 2, 2, 3) }, new[] { Stock("sheet", 10, 20) });
var types = PartCatalog.Build(job);
using var catalog = new BlockCatalog(0.25, types, NoPairs);
using var catalog = new BlockCatalog(0.25, types, NoPairs, new WorkCounter(), long.MaxValue);
Assert.Throws<OperationCanceledException>(() =>
catalog.Get(types[0], 3, new Box(0, 0, 20, 10), new CancellationToken(true)));
}
@@ -17,6 +17,8 @@ namespace OpenNest.Engine.NestingEngines.Irregular;
internal sealed class BlockCatalog : IDisposable
{
private readonly double spacing;
private readonly WorkCounter counter;
private readonly long budget;
private readonly Dictionary<int, Drawing> drawings = new();
private readonly Dictionary<int, List<Orientation>> orientations = new();
private readonly Dictionary<int, int> attempts = new();
@@ -24,9 +26,11 @@ internal sealed class BlockCatalog : IDisposable
private readonly Dictionary<(int Type, int Quantity, double Length, double Width), IReadOnlyList<Placed>> cache = new();
public BlockCatalog(double spacing, IReadOnlyList<PartType> types,
IReadOnlyDictionary<int, IReadOnlyList<PairPose>> pairs)
IReadOnlyDictionary<int, IReadOnlyList<PairPose>> pairs, WorkCounter counter, long budget)
{
this.spacing = spacing;
this.counter = counter;
this.budget = budget;
foreach (var type in types)
{
var poses = type.Orientations.ToList();
@@ -65,7 +69,7 @@ internal sealed class BlockCatalog : IDisposable
var key = (type.Index, quantity, rectangle.Length, rectangle.Width);
if (cache.TryGetValue(key, out var cached))
return cached;
if (rectangle.Area() < 3 * type.Area || attempts.GetValueOrDefault(type.Index) >= 8)
if (rectangle.Area() < 3 * type.Area || attempts.GetValueOrDefault(type.Index) >= 8 || counter.Value >= budget)
return Array.Empty<Placed>();
attempts[type.Index] = attempts.GetValueOrDefault(type.Index) + 1;
var result = Build(type, quantity, rectangle, token);
@@ -75,6 +79,11 @@ internal sealed class BlockCatalog : IDisposable
private IReadOnlyList<Placed> Build(PartType type, int quantity, Box rectangle, CancellationToken token)
{
// PrivatePlateFill.Run below is a full independent NFP-based pack whose own operations
// never touch this solve's effort meter; charge it here using the same factors - demand
// and outline complexity - that drive its real cost, so the shared budget actually sees it.
var vertices = type.Orientations.Count > 0 ? type.Orientations[0].Outline.Count : 1;
counter.Add((long)quantity * quantity * System.Math.Max(1, vertices));
if (!drawings.TryGetValue(type.Index, out var drawing))
drawings[type.Index] = drawing = DrawingJobMapper.CreateDrawing(type.Part);
try
@@ -48,7 +48,7 @@ public sealed class IrregularNestingEngine : INestingEngine
ArgumentNullException.ThrowIfNull(job);
token.ThrowIfCancellationRequested();
var types = PartCatalog.Build(job);
using var solver = new Solver(job, types, progress, token);
using var solver = new Solver(job, types, progress, token, WorkBudget);
// Pair-only orientations may fit stock even when the sampled single poses do not.
// Demand that neither a single nor a pair can fit is reported unplaced.
@@ -86,7 +86,8 @@ public sealed class IrregularNestingEngine : INestingEngine
NestJob job,
IReadOnlyList<PartType> types,
IProgress<NestJobProgress>? progress,
CancellationToken token
CancellationToken token,
long workBudget
) : IDisposable
{
public void Dispose()
@@ -104,7 +105,7 @@ public sealed class IrregularNestingEngine : INestingEngine
{
var spacing = System.Math.Max(0, stock.PartSpacing);
if (!blocks.TryGetValue(spacing, out var found))
blocks[spacing] = found = new BlockCatalog(spacing, types, PairsFor(stock));
blocks[spacing] = found = new BlockCatalog(spacing, types, PairsFor(stock), Work, workBudget);
return found;
}
+14
View File
@@ -84,6 +84,12 @@ namespace OpenNest.Controls
public event EventHandler PartsReordered;
public event EventHandler StatusChanged;
/// <summary>
/// Raised when files are dropped on the plate and something is listening (see
/// <see cref="OnDragEnter"/>); callers decide which paths to act on.
/// </summary>
public event EventHandler<string[]> FilesDropped;
public event EventHandler SelectionChanged
{
add => selection.SelectionChanged += value;
@@ -313,10 +319,18 @@ namespace OpenNest.Controls
{
if (drgevent.Data.GetData(typeof(Drawing)) != null)
drgevent.Effect = DragDropEffects.Copy;
else if (FilesDropped != null && drgevent.Data.GetDataPresent(DataFormats.FileDrop))
drgevent.Effect = DragDropEffects.Copy;
}
protected override void OnDragDrop(DragEventArgs drgevent)
{
if (drgevent.Data.GetDataPresent(DataFormats.FileDrop))
{
FilesDropped?.Invoke(this, (string[])drgevent.Data.GetData(DataFormats.FileDrop));
return;
}
var dwg = drgevent.Data.GetData(typeof(Drawing)) as Drawing;
if (dwg == null)
+166 -152
View File
@@ -73,27 +73,14 @@
mnuTools = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsMeasureArea = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsBestFitViewer = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsPatternTile = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsExpandSpacing = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsAlign = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsAlignLeft = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsAlignRight = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsAlignTop = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsAlignBottom = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem11 = new System.Windows.Forms.ToolStripSeparator();
mnuToolsAlignHorizontal = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsAlignVertically = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem8 = new System.Windows.Forms.ToolStripSeparator();
mnuToolsEvenlySpaceHorizontal = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsEvenlySpaceVertical = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem14 = new System.Windows.Forms.ToolStripSeparator();
mnuSetOffsetIncrement = new System.Windows.Forms.ToolStripMenuItem();
mnuSetRotationIncrement = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem15 = new System.Windows.Forms.ToolStripSeparator();
mnuToolsMachineConfig = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsNestDefaults = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsSaveCurrentAsDefaults = new System.Windows.Forms.ToolStripMenuItem();
mnuToolsOptions = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem15 = new System.Windows.Forms.ToolStripSeparator();
mnuSetOffsetIncrement = new System.Windows.Forms.ToolStripMenuItem();
mnuSetRotationIncrement = new System.Windows.Forms.ToolStripMenuItem();
mnuNest = new System.Windows.Forms.ToolStripMenuItem();
mnuNestEdit = new System.Windows.Forms.ToolStripMenuItem();
mnuNestImportDrawing = new System.Windows.Forms.ToolStripMenuItem();
@@ -130,20 +117,35 @@
mnuPlateRotate180 = new System.Windows.Forms.ToolStripMenuItem();
mnuResizeToFitParts = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem13 = new System.Windows.Forms.ToolStripSeparator();
mnuPlateViewInCad = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem20 = new System.Windows.Forms.ToolStripSeparator();
mnuPlateArrange = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateAlignLeft = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateAlignRight = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateAlignTop = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateAlignBottom = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem11 = new System.Windows.Forms.ToolStripSeparator();
mnuPlateAlignHorizontal = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateAlignVertically = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem8 = new System.Windows.Forms.ToolStripSeparator();
mnuPlateEvenlySpaceHorizontal = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateEvenlySpaceVertical = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem23 = new System.Windows.Forms.ToolStripSeparator();
centerPartsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem24 = new System.Windows.Forms.ToolStripSeparator();
mnuPlatePatternTile = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateExpandSpacing = new System.Windows.Forms.ToolStripMenuItem();
mnuSequenceParts = new System.Windows.Forms.ToolStripMenuItem();
autoSequenceCurrentPlateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
manualSequenceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
calculateCutTimeToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
centerPartsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateCutOff = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateAutomaticCutOff = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem21 = new System.Windows.Forms.ToolStripSeparator();
mnuPlatePlanCutting = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateAssignLeadIns = new System.Windows.Forms.ToolStripMenuItem();
mnuPlatePlaceLeadIn = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateRemoveLeadIns = new System.Windows.Forms.ToolStripMenuItem();
toolStripMenuItem20 = new System.Windows.Forms.ToolStripSeparator();
mnuPlateViewInCad = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateCutOff = new System.Windows.Forms.ToolStripMenuItem();
mnuPlateAutomaticCutOff = new System.Windows.Forms.ToolStripMenuItem();
mnuWindow = new System.Windows.Forms.ToolStripMenuItem();
mnuWindowCascade = new System.Windows.Forms.ToolStripMenuItem();
mnuWindowTileVertical = new System.Windows.Forms.ToolStripMenuItem();
@@ -494,7 +496,7 @@
//
// mnuTools
//
mnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuToolsMeasureArea, mnuToolsBestFitViewer, mnuToolsPatternTile, mnuToolsExpandSpacing, mnuToolsAlign, toolStripMenuItem14, mnuSetOffsetIncrement, mnuSetRotationIncrement, toolStripMenuItem15, mnuToolsMachineConfig, mnuToolsNestDefaults, mnuToolsSaveCurrentAsDefaults, mnuToolsOptions });
mnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuToolsMeasureArea, mnuToolsBestFitViewer, toolStripMenuItem14, mnuToolsMachineConfig, mnuToolsNestDefaults, mnuToolsSaveCurrentAsDefaults, mnuToolsOptions, toolStripMenuItem15, mnuSetOffsetIncrement, mnuSetRotationIncrement });
mnuTools.Name = "mnuTools";
mnuTools.Size = new System.Drawing.Size(47, 20);
mnuTools.Text = "&Tools";
@@ -513,93 +515,6 @@
mnuToolsBestFitViewer.Text = "Best-Fit Viewer";
mnuToolsBestFitViewer.Click += BestFitViewer_Click;
//
// mnuToolsPatternTile
//
this.mnuToolsPatternTile.Name = "mnuToolsPatternTile";
this.mnuToolsPatternTile.Size = new System.Drawing.Size(214, 22);
this.mnuToolsPatternTile.Text = "Pattern Tile";
this.mnuToolsPatternTile.Click += PatternTile_Click;
//
// mnuToolsExpandSpacing
//
this.mnuToolsExpandSpacing.Name = "mnuToolsExpandSpacing";
this.mnuToolsExpandSpacing.Size = new System.Drawing.Size(214, 22);
this.mnuToolsExpandSpacing.Text = "Expand Spacing";
this.mnuToolsExpandSpacing.Click += ExpandSpacing_Click;
//
// mnuToolsAlign
//
mnuToolsAlign.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuToolsAlignLeft, mnuToolsAlignRight, mnuToolsAlignTop, mnuToolsAlignBottom, toolStripMenuItem11, mnuToolsAlignHorizontal, mnuToolsAlignVertically, toolStripMenuItem8, mnuToolsEvenlySpaceHorizontal, mnuToolsEvenlySpaceVertical });
mnuToolsAlign.Name = "mnuToolsAlign";
mnuToolsAlign.Size = new System.Drawing.Size(214, 22);
mnuToolsAlign.Text = "Align Selected";
//
// mnuToolsAlignLeft
//
mnuToolsAlignLeft.Name = "mnuToolsAlignLeft";
mnuToolsAlignLeft.Size = new System.Drawing.Size(209, 22);
mnuToolsAlignLeft.Text = "Left";
mnuToolsAlignLeft.Click += AlignLeft_Click;
//
// mnuToolsAlignRight
//
mnuToolsAlignRight.Name = "mnuToolsAlignRight";
mnuToolsAlignRight.Size = new System.Drawing.Size(209, 22);
mnuToolsAlignRight.Text = "Right";
mnuToolsAlignRight.Click += AlignRight_Click;
//
// mnuToolsAlignTop
//
mnuToolsAlignTop.Name = "mnuToolsAlignTop";
mnuToolsAlignTop.Size = new System.Drawing.Size(209, 22);
mnuToolsAlignTop.Text = "Top";
mnuToolsAlignTop.Click += AlignTop_Click;
//
// mnuToolsAlignBottom
//
mnuToolsAlignBottom.Name = "mnuToolsAlignBottom";
mnuToolsAlignBottom.Size = new System.Drawing.Size(209, 22);
mnuToolsAlignBottom.Text = "Bottom";
mnuToolsAlignBottom.Click += AlignBottom_Click;
//
// toolStripMenuItem11
//
toolStripMenuItem11.Name = "toolStripMenuItem11";
toolStripMenuItem11.Size = new System.Drawing.Size(206, 6);
//
// mnuToolsAlignHorizontal
//
mnuToolsAlignHorizontal.Name = "mnuToolsAlignHorizontal";
mnuToolsAlignHorizontal.Size = new System.Drawing.Size(209, 22);
mnuToolsAlignHorizontal.Text = "Horizontally";
mnuToolsAlignHorizontal.Click += AlignHorizontal_Click;
//
// mnuToolsAlignVertically
//
mnuToolsAlignVertically.Name = "mnuToolsAlignVertically";
mnuToolsAlignVertically.Size = new System.Drawing.Size(209, 22);
mnuToolsAlignVertically.Text = "Vertically";
mnuToolsAlignVertically.Click += AlignVertical_Click;
//
// toolStripMenuItem8
//
toolStripMenuItem8.Name = "toolStripMenuItem8";
toolStripMenuItem8.Size = new System.Drawing.Size(206, 6);
//
// mnuToolsEvenlySpaceHorizontal
//
mnuToolsEvenlySpaceHorizontal.Name = "mnuToolsEvenlySpaceHorizontal";
mnuToolsEvenlySpaceHorizontal.Size = new System.Drawing.Size(209, 22);
mnuToolsEvenlySpaceHorizontal.Text = "Evenly Space Horizontally";
mnuToolsEvenlySpaceHorizontal.Click += EvenlySpaceHorizontally_Click;
//
// mnuToolsEvenlySpaceVertical
//
mnuToolsEvenlySpaceVertical.Name = "mnuToolsEvenlySpaceVertical";
mnuToolsEvenlySpaceVertical.Size = new System.Drawing.Size(209, 22);
mnuToolsEvenlySpaceVertical.Text = "Evenly Space Vertically";
mnuToolsEvenlySpaceVertical.Click += EvenlySpaceVertically_Click;
//
// toolStripMenuItem14
//
toolStripMenuItem14.Name = "toolStripMenuItem14";
@@ -805,8 +720,8 @@
mnuNestRemoveLeadIns.Click += NestRemoveLeadIns_Click;
//
// mnuPlate
//
mnuPlate.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuPlateEdit, mnuPlateSetAsDefault, toolStripMenuItem18, mnuPlateAdd, mnuPlateRemove, toolStripMenuItem16, mnuPlateCutOff, mnuPlateAutomaticCutOff, mnuPlateRotate, mnuResizeToFitParts, toolStripMenuItem13, mnuPlateViewInCad, toolStripMenuItem20, mnuSequenceParts, calculateCutTimeToolStripMenuItem1, centerPartsToolStripMenuItem, toolStripMenuItem21, mnuPlatePlanCutting, mnuPlateAssignLeadIns, mnuPlatePlaceLeadIn, mnuPlateRemoveLeadIns });
//
mnuPlate.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuPlateEdit, mnuPlateSetAsDefault, toolStripMenuItem18, mnuPlateAdd, mnuPlateRemove, toolStripMenuItem16, mnuPlateCutOff, mnuPlateAutomaticCutOff, mnuPlateRotate, mnuResizeToFitParts, toolStripMenuItem13, mnuPlateArrange, mnuSequenceParts, calculateCutTimeToolStripMenuItem1, toolStripMenuItem21, mnuPlatePlanCutting, mnuPlateAssignLeadIns, mnuPlatePlaceLeadIn, mnuPlateRemoveLeadIns, toolStripMenuItem20, mnuPlateViewInCad });
mnuPlate.Name = "mnuPlate";
mnuPlate.Size = new System.Drawing.Size(45, 20);
mnuPlate.Text = "&Plate";
@@ -901,64 +816,149 @@
mnuPlateRotate180.Click += Rotate180_Click;
//
// mnuResizeToFitParts
//
//
mnuResizeToFitParts.Name = "mnuResizeToFitParts";
mnuResizeToFitParts.ShortcutKeys = System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P;
mnuResizeToFitParts.Size = new System.Drawing.Size(177, 22);
mnuResizeToFitParts.Text = "Resize to Fit";
mnuResizeToFitParts.Click += ResizeToFitParts_Click;
//
//
// toolStripMenuItem13
//
//
toolStripMenuItem13.Name = "toolStripMenuItem13";
toolStripMenuItem13.Size = new System.Drawing.Size(174, 6);
//
// mnuPlateViewInCad
//
mnuPlateViewInCad.Name = "mnuPlateViewInCad";
mnuPlateViewInCad.Size = new System.Drawing.Size(177, 22);
mnuPlateViewInCad.Text = "View in CAD";
mnuPlateViewInCad.Click += OpenInExternalCad_Click;
//
// toolStripMenuItem20
//
toolStripMenuItem20.Name = "toolStripMenuItem20";
toolStripMenuItem20.Size = new System.Drawing.Size(174, 6);
//
//
// mnuPlateArrange
//
mnuPlateArrange.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuPlateAlignLeft, mnuPlateAlignRight, mnuPlateAlignTop, mnuPlateAlignBottom, toolStripMenuItem11, mnuPlateAlignHorizontal, mnuPlateAlignVertically, toolStripMenuItem8, mnuPlateEvenlySpaceHorizontal, mnuPlateEvenlySpaceVertical, toolStripMenuItem23, centerPartsToolStripMenuItem, toolStripMenuItem24, mnuPlatePatternTile, mnuPlateExpandSpacing });
mnuPlateArrange.Name = "mnuPlateArrange";
mnuPlateArrange.Size = new System.Drawing.Size(177, 22);
mnuPlateArrange.Text = "Arrange";
//
// mnuPlateAlignLeft
//
mnuPlateAlignLeft.Name = "mnuPlateAlignLeft";
mnuPlateAlignLeft.Size = new System.Drawing.Size(209, 22);
mnuPlateAlignLeft.Text = "Left";
mnuPlateAlignLeft.Click += AlignLeft_Click;
//
// mnuPlateAlignRight
//
mnuPlateAlignRight.Name = "mnuPlateAlignRight";
mnuPlateAlignRight.Size = new System.Drawing.Size(209, 22);
mnuPlateAlignRight.Text = "Right";
mnuPlateAlignRight.Click += AlignRight_Click;
//
// mnuPlateAlignTop
//
mnuPlateAlignTop.Name = "mnuPlateAlignTop";
mnuPlateAlignTop.Size = new System.Drawing.Size(209, 22);
mnuPlateAlignTop.Text = "Top";
mnuPlateAlignTop.Click += AlignTop_Click;
//
// mnuPlateAlignBottom
//
mnuPlateAlignBottom.Name = "mnuPlateAlignBottom";
mnuPlateAlignBottom.Size = new System.Drawing.Size(209, 22);
mnuPlateAlignBottom.Text = "Bottom";
mnuPlateAlignBottom.Click += AlignBottom_Click;
//
// toolStripMenuItem11
//
toolStripMenuItem11.Name = "toolStripMenuItem11";
toolStripMenuItem11.Size = new System.Drawing.Size(206, 6);
//
// mnuPlateAlignHorizontal
//
mnuPlateAlignHorizontal.Name = "mnuPlateAlignHorizontal";
mnuPlateAlignHorizontal.Size = new System.Drawing.Size(209, 22);
mnuPlateAlignHorizontal.Text = "Horizontally";
mnuPlateAlignHorizontal.Click += AlignHorizontal_Click;
//
// mnuPlateAlignVertically
//
mnuPlateAlignVertically.Name = "mnuPlateAlignVertically";
mnuPlateAlignVertically.Size = new System.Drawing.Size(209, 22);
mnuPlateAlignVertically.Text = "Vertically";
mnuPlateAlignVertically.Click += AlignVertical_Click;
//
// toolStripMenuItem8
//
toolStripMenuItem8.Name = "toolStripMenuItem8";
toolStripMenuItem8.Size = new System.Drawing.Size(206, 6);
//
// mnuPlateEvenlySpaceHorizontal
//
mnuPlateEvenlySpaceHorizontal.Name = "mnuPlateEvenlySpaceHorizontal";
mnuPlateEvenlySpaceHorizontal.Size = new System.Drawing.Size(209, 22);
mnuPlateEvenlySpaceHorizontal.Text = "Evenly Space Horizontally";
mnuPlateEvenlySpaceHorizontal.Click += EvenlySpaceHorizontally_Click;
//
// mnuPlateEvenlySpaceVertical
//
mnuPlateEvenlySpaceVertical.Name = "mnuPlateEvenlySpaceVertical";
mnuPlateEvenlySpaceVertical.Size = new System.Drawing.Size(209, 22);
mnuPlateEvenlySpaceVertical.Text = "Evenly Space Vertically";
mnuPlateEvenlySpaceVertical.Click += EvenlySpaceVertically_Click;
//
// toolStripMenuItem23
//
toolStripMenuItem23.Name = "toolStripMenuItem23";
toolStripMenuItem23.Size = new System.Drawing.Size(206, 6);
//
// centerPartsToolStripMenuItem
//
centerPartsToolStripMenuItem.Name = "centerPartsToolStripMenuItem";
centerPartsToolStripMenuItem.Size = new System.Drawing.Size(209, 22);
centerPartsToolStripMenuItem.Text = "Center Parts";
centerPartsToolStripMenuItem.Click += centerPartsToolStripMenuItem_Click;
//
// toolStripMenuItem24
//
toolStripMenuItem24.Name = "toolStripMenuItem24";
toolStripMenuItem24.Size = new System.Drawing.Size(206, 6);
//
// mnuPlatePatternTile
//
mnuPlatePatternTile.Name = "mnuPlatePatternTile";
mnuPlatePatternTile.Size = new System.Drawing.Size(209, 22);
mnuPlatePatternTile.Text = "Pattern Tile";
mnuPlatePatternTile.Click += PatternTile_Click;
//
// mnuPlateExpandSpacing
//
mnuPlateExpandSpacing.Name = "mnuPlateExpandSpacing";
mnuPlateExpandSpacing.Size = new System.Drawing.Size(209, 22);
mnuPlateExpandSpacing.Text = "Expand Spacing";
mnuPlateExpandSpacing.Click += ExpandSpacing_Click;
//
// mnuSequenceParts
//
//
mnuSequenceParts.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { autoSequenceCurrentPlateToolStripMenuItem, manualSequenceToolStripMenuItem });
mnuSequenceParts.Name = "mnuSequenceParts";
mnuSequenceParts.Size = new System.Drawing.Size(177, 22);
mnuSequenceParts.Text = "Sequence Parts";
//
//
// autoSequenceCurrentPlateToolStripMenuItem
//
//
autoSequenceCurrentPlateToolStripMenuItem.Name = "autoSequenceCurrentPlateToolStripMenuItem";
autoSequenceCurrentPlateToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
autoSequenceCurrentPlateToolStripMenuItem.Text = "Auto Sequence";
autoSequenceCurrentPlateToolStripMenuItem.Click += AutoSequenceCurrentPlate_Click;
//
//
// manualSequenceToolStripMenuItem
//
//
manualSequenceToolStripMenuItem.Name = "manualSequenceToolStripMenuItem";
manualSequenceToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
manualSequenceToolStripMenuItem.Text = "Manual Sequence";
manualSequenceToolStripMenuItem.Click += ManualSequenceParts_Click;
//
//
// calculateCutTimeToolStripMenuItem1
//
//
calculateCutTimeToolStripMenuItem1.Name = "calculateCutTimeToolStripMenuItem1";
calculateCutTimeToolStripMenuItem1.Size = new System.Drawing.Size(177, 22);
calculateCutTimeToolStripMenuItem1.Text = "Calculate Cut Time";
calculateCutTimeToolStripMenuItem1.Click += CalculatePlateCutTime_Click;
//
// centerPartsToolStripMenuItem
//
centerPartsToolStripMenuItem.Name = "centerPartsToolStripMenuItem";
centerPartsToolStripMenuItem.Size = new System.Drawing.Size(177, 22);
centerPartsToolStripMenuItem.Text = "Center Parts";
centerPartsToolStripMenuItem.Click += centerPartsToolStripMenuItem_Click;
//
// toolStripMenuItem21
//
@@ -993,6 +993,18 @@
mnuPlateRemoveLeadIns.Text = "Remove Lead-ins";
mnuPlateRemoveLeadIns.Click += PlateRemoveLeadIns_Click;
//
// toolStripMenuItem20
//
toolStripMenuItem20.Name = "toolStripMenuItem20";
toolStripMenuItem20.Size = new System.Drawing.Size(174, 6);
//
// mnuPlateViewInCad
//
mnuPlateViewInCad.Name = "mnuPlateViewInCad";
mnuPlateViewInCad.Size = new System.Drawing.Size(177, 22);
mnuPlateViewInCad.Text = "View in CAD";
mnuPlateViewInCad.Click += OpenInExternalCad_Click;
//
// mnuWindow
//
mnuWindow.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { mnuWindowCascade, mnuWindowTileVertical, mnuWindowTileHorizontal, toolStripMenuItem10, closeToolStripMenuItem, mnuCloseAll });
@@ -1394,17 +1406,19 @@
private System.Windows.Forms.ToolStripMenuItem mnuViewZoomToPlate;
private System.Windows.Forms.ToolStripMenuItem mnuViewZoomToSelected;
private System.Windows.Forms.ToolStripMenuItem mnuResizeToFitParts;
private System.Windows.Forms.ToolStripMenuItem mnuToolsAlign;
private System.Windows.Forms.ToolStripMenuItem mnuToolsAlignLeft;
private System.Windows.Forms.ToolStripMenuItem mnuToolsAlignRight;
private System.Windows.Forms.ToolStripMenuItem mnuToolsAlignTop;
private System.Windows.Forms.ToolStripMenuItem mnuToolsAlignBottom;
private System.Windows.Forms.ToolStripMenuItem mnuPlateArrange;
private System.Windows.Forms.ToolStripMenuItem mnuPlateAlignLeft;
private System.Windows.Forms.ToolStripMenuItem mnuPlateAlignRight;
private System.Windows.Forms.ToolStripMenuItem mnuPlateAlignTop;
private System.Windows.Forms.ToolStripMenuItem mnuPlateAlignBottom;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem11;
private System.Windows.Forms.ToolStripMenuItem mnuToolsAlignHorizontal;
private System.Windows.Forms.ToolStripMenuItem mnuToolsAlignVertically;
private System.Windows.Forms.ToolStripMenuItem mnuPlateAlignHorizontal;
private System.Windows.Forms.ToolStripMenuItem mnuPlateAlignVertically;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem8;
private System.Windows.Forms.ToolStripMenuItem mnuToolsEvenlySpaceHorizontal;
private System.Windows.Forms.ToolStripMenuItem mnuToolsEvenlySpaceVertical;
private System.Windows.Forms.ToolStripMenuItem mnuPlateEvenlySpaceHorizontal;
private System.Windows.Forms.ToolStripMenuItem mnuPlateEvenlySpaceVertical;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem23;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem24;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem12;
private System.Windows.Forms.ToolStripMenuItem mnuNestPost;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem13;
@@ -1440,8 +1454,8 @@
private System.Windows.Forms.ToolStripMenuItem autoSequenceAllPlatesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem mnuToolsMeasureArea;
private System.Windows.Forms.ToolStripMenuItem mnuToolsBestFitViewer;
private System.Windows.Forms.ToolStripMenuItem mnuToolsPatternTile;
private System.Windows.Forms.ToolStripMenuItem mnuToolsExpandSpacing;
private System.Windows.Forms.ToolStripMenuItem mnuPlatePatternTile;
private System.Windows.Forms.ToolStripMenuItem mnuPlateExpandSpacing;
private System.Windows.Forms.ToolStripButton btnSaveAs;
private System.Windows.Forms.ToolStripMenuItem centerPartsToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel gpuStatusLabel;
+39 -2
View File
@@ -69,6 +69,7 @@ namespace OpenNest.Forms
clickUpdateLocation = true;
this.SetBevel(false);
AllowDrop = true;
LoadPosts();
EnableCheck();
@@ -173,6 +174,7 @@ namespace OpenNest.Forms
if (remoteId != Guid.Empty)
editForm.Document.BindRemote(remoteId, serverUrl);
editForm.MdiParent = this;
editForm.PlateView.FilesDropped += (sender, paths) => OpenDroppedNestFiles(paths);
editForm.PlateChanged += (sender, e) =>
{
NavigationEnableCheck();
@@ -232,9 +234,7 @@ namespace OpenNest.Forms
mnuNest.Visible = hasValue;
mnuPlate.Visible = hasValue;
mnuWindow.Visible = hasValue;
mnuToolsAlign.Visible = hasValue;
mnuToolsMeasureArea.Visible = hasValue;
mnuToolsExpandSpacing.Visible = hasValue;
mnuToolsSaveCurrentAsDefaults.Visible = hasValue;
toolStripMenuItem14.Visible = hasValue;
@@ -554,6 +554,43 @@ namespace OpenNest.Forms
Settings.Default.Save();
}
protected override void OnDragEnter(DragEventArgs e)
{
base.OnDragEnter(e);
e.Effect = HasDroppedNestFile(e.Data) ? DragDropEffects.Copy : DragDropEffects.None;
}
protected override void OnDragDrop(DragEventArgs e)
{
base.OnDragDrop(e);
if (e.Data.GetData(DataFormats.FileDrop) is string[] paths)
OpenDroppedNestFiles(paths);
}
private static bool HasDroppedNestFile(IDataObject data) =>
data.GetData(DataFormats.FileDrop) is string[] paths
&& paths.Any(path => string.Equals(
Path.GetExtension(path), NestFormat.FileExtension, StringComparison.OrdinalIgnoreCase));
/// <summary>
/// Opens dropped .nest files locally regardless of storage mode. Loaded documents are
/// not bound to a server record, so Save/Save As follow the normal storage-mode rules
/// (File mode writes to disk; Database mode creates a new record on first save).
/// </summary>
private void OpenDroppedNestFiles(IEnumerable<string> paths)
{
foreach (var path in paths)
{
if (!string.Equals(Path.GetExtension(path), NestFormat.FileExtension, StringComparison.OrdinalIgnoreCase))
continue;
var reader = new NestReader(path);
var nest = reader.Read();
LoadNest(nest);
ShowNestWarnings(reader);
}
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
+33 -12
View File
@@ -72,6 +72,7 @@ public sealed class SavedNestsForm : Form
StartPosition = FormStartPosition.CenterParent;
ClientSize = new Size(1280, 800);
MinimumSize = new Size(800, 560);
WindowState = FormWindowState.Maximized;
MinimizeBox = false;
ShowInTaskbar = false;
@@ -277,6 +278,10 @@ public sealed class SavedNestsForm : Form
Load += (_, _) =>
{
// Keep a maximized dialog's bottom row clear of the taskbar.
var area = Screen.FromControl(Owner ?? this).WorkingArea;
MaximizedBounds = new Rectangle(area.Left, area.Top, area.Width, area.Height - 20);
// Minimum sizes are applied once the container has its real height; setting them
// on the default-sized container throws.
split.Panel1MinSize = 120;
@@ -327,23 +332,27 @@ public sealed class SavedNestsForm : Form
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
MultiSelect = false,
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None,
BackgroundColor = Color.White,
BorderStyle = BorderStyle.FixedSingle,
GridColor = Color.Silver,
BackgroundColor = SystemColors.Window,
BorderStyle = BorderStyle.None,
GridColor = Color.FromArgb(230, 230, 230),
EnableHeadersVisualStyles = false,
ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single,
RowHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single,
ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize,
RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing,
StandardTab = true,
};
grid.RowTemplate.Height = 22;
grid.DefaultCellStyle.SelectionBackColor = Color.Black;
grid.DefaultCellStyle.SelectionForeColor = Color.White;
grid.ColumnHeadersDefaultCellStyle.BackColor = SystemColors.Control;
grid.ColumnHeadersDefaultCellStyle.SelectionBackColor = SystemColors.Control;
grid.DefaultCellStyle.SelectionBackColor = Color.FromArgb(204, 228, 247);
grid.DefaultCellStyle.SelectionForeColor = Color.Black;
grid.ColumnHeadersDefaultCellStyle.BackColor = Color.FromArgb(245, 245, 245);
grid.ColumnHeadersDefaultCellStyle.ForeColor = Color.FromArgb(90, 90, 90);
grid.ColumnHeadersDefaultCellStyle.SelectionBackColor = Color.FromArgb(245, 245, 245);
grid.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
grid.RowHeadersDefaultCellStyle.BackColor = SystemColors.Control;
grid.RowHeadersDefaultCellStyle.SelectionBackColor = Color.Black;
grid.RowHeadersDefaultCellStyle.SelectionForeColor = Color.White;
grid.RowHeadersDefaultCellStyle.BackColor = Color.FromArgb(245, 245, 245);
grid.RowHeadersDefaultCellStyle.ForeColor = Color.FromArgb(90, 90, 90);
grid.RowHeadersDefaultCellStyle.SelectionBackColor = Color.FromArgb(204, 228, 247);
grid.RowHeadersDefaultCellStyle.SelectionForeColor = Color.Black;
grid.RowHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
return grid;
}
@@ -505,8 +514,20 @@ public sealed class SavedNestsForm : Form
private static string FormatDate(DateTime value) =>
value == default ? "" : value.ToString("g", CultureInfo.CurrentCulture);
private static string FormatFileSize(long bytes) =>
$"{System.Math.Ceiling(bytes / 1024.0).ToString("N0", CultureInfo.CurrentCulture)} KB";
private static readonly string[] FileSizeUnits = { "B", "KB", "MB", "GB" };
private static string FormatFileSize(long bytes)
{
double size = bytes;
var unitIndex = 0;
while (size >= 1024 && unitIndex < FileSizeUnits.Length - 1)
{
size /= 1024;
unitIndex++;
}
return unitIndex == 0 ? $"{size:0} {FileSizeUnits[unitIndex]}" : $"{size:0.#} {FileSizeUnits[unitIndex]}";
}
private Guid? SelectedNestId() =>
nestGrid.SelectedRows.Count > 0 && nestGrid.SelectedRows[0].Cells[IdColumn].Value is Guid id ? id : null;
+7
View File
@@ -26,6 +26,13 @@ The desktop app can save nests two ways:
file to share or back up. Export does not change the document's file save path
or database record association.
Dragging one or more `.nest` files onto the main window (or onto an open
plate) opens them from disk directly, in either mode — this is the only way
to open a local file while in Database mode, since Open there browses server
records instead of showing a file dialog. A document opened this way is not
bound to a server record, so a subsequent Save in Database mode creates a new
record on first save, same as any other unbound document.
The mode and server address are stored per-PC at `%APPDATA%\OpenNest\storage.json`
(`OpenNest.Data.NestStorageSettings`), defaulting to File mode so existing
installs are unaffected until an operator opts in via **File > Storage Mode...**.