feat(ui): make RunAutoNest_Click async with progress and cancellation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+101
-22
@@ -1,8 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using OpenNest.Actions;
|
using OpenNest.Actions;
|
||||||
using OpenNest.Collections;
|
using OpenNest.Collections;
|
||||||
@@ -18,6 +21,8 @@ namespace OpenNest.Forms
|
|||||||
{
|
{
|
||||||
private EditNestForm activeForm;
|
private EditNestForm activeForm;
|
||||||
private bool clickUpdateLocation;
|
private bool clickUpdateLocation;
|
||||||
|
private bool nestingInProgress;
|
||||||
|
private CancellationTokenSource nestingCts;
|
||||||
|
|
||||||
private const float ZoomInFactor = 1.5f;
|
private const float ZoomInFactor = 1.5f;
|
||||||
private const float ZoomOutFactor = 1.0f / ZoomInFactor;
|
private const float ZoomOutFactor = 1.0f / ZoomInFactor;
|
||||||
@@ -165,6 +170,25 @@ namespace OpenNest.Forms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetNestingLockout(bool locked)
|
||||||
|
{
|
||||||
|
nestingInProgress = locked;
|
||||||
|
|
||||||
|
// Disable nesting-related menus while running
|
||||||
|
mnuNest.Enabled = !locked;
|
||||||
|
mnuPlate.Enabled = !locked;
|
||||||
|
|
||||||
|
// Lock plate navigation
|
||||||
|
mnuNestPreviousPlate.Enabled = !locked && activeForm != null && !activeForm.IsFirstPlate();
|
||||||
|
btnPreviousPlate.Enabled = mnuNestPreviousPlate.Enabled;
|
||||||
|
mnuNestNextPlate.Enabled = !locked && activeForm != null && !activeForm.IsLastPlate();
|
||||||
|
btnNextPlate.Enabled = mnuNestNextPlate.Enabled;
|
||||||
|
mnuNestFirstPlate.Enabled = !locked && activeForm != null && activeForm.PlateCount > 0 && !activeForm.IsFirstPlate();
|
||||||
|
btnFirstPlate.Enabled = mnuNestFirstPlate.Enabled;
|
||||||
|
mnuNestLastPlate.Enabled = !locked && activeForm != null && activeForm.PlateCount > 0 && !activeForm.IsLastPlate();
|
||||||
|
btnLastPlate.Enabled = mnuNestLastPlate.Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateLocationStatus()
|
private void UpdateLocationStatus()
|
||||||
{
|
{
|
||||||
if (activeForm == null)
|
if (activeForm == null)
|
||||||
@@ -689,7 +713,7 @@ namespace OpenNest.Forms
|
|||||||
activeForm.LoadNextPlate();
|
activeForm.LoadNextPlate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunAutoNest_Click(object sender, EventArgs e)
|
private async void RunAutoNest_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var form = new AutoNestForm(activeForm.Nest);
|
var form = new AutoNestForm(activeForm.Nest);
|
||||||
form.AllowPlateCreation = true;
|
form.AllowPlateCreation = true;
|
||||||
@@ -699,41 +723,96 @@ namespace OpenNest.Forms
|
|||||||
|
|
||||||
var items = form.GetNestItems();
|
var items = form.GetNestItems();
|
||||||
|
|
||||||
while (items.Any(it => it.Quantity > 0))
|
if (!items.Any(it => it.Quantity > 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
nestingCts = new CancellationTokenSource();
|
||||||
|
var token = nestingCts.Token;
|
||||||
|
|
||||||
|
var progressForm = new NestProgressForm(nestingCts, showPlateRow: true);
|
||||||
|
var plateNumber = 1;
|
||||||
|
|
||||||
|
var progress = new Progress<NestProgress>(p =>
|
||||||
{
|
{
|
||||||
var plate = activeForm.PlateView.Plate.Parts.Count > 0
|
progressForm.UpdateProgress(p);
|
||||||
? activeForm.Nest.CreatePlate()
|
activeForm.PlateView.SetTemporaryParts(p.BestParts);
|
||||||
: activeForm.PlateView.Plate;
|
});
|
||||||
|
|
||||||
var engine = new NestEngine(plate);
|
progressForm.Show(this);
|
||||||
var filled = false;
|
SetNestingLockout(true);
|
||||||
|
|
||||||
foreach (var item in items)
|
try
|
||||||
|
{
|
||||||
|
while (items.Any(it => it.Quantity > 0))
|
||||||
{
|
{
|
||||||
if (item.Quantity <= 0)
|
if (token.IsCancellationRequested)
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
if (engine.Fill(item))
|
var plate = activeForm.PlateView.Plate.Parts.Count > 0
|
||||||
filled = true;
|
? activeForm.Nest.CreatePlate()
|
||||||
}
|
: activeForm.PlateView.Plate;
|
||||||
|
|
||||||
if (!filled)
|
// If a new plate was created, switch to it
|
||||||
break;
|
if (plate != activeForm.PlateView.Plate)
|
||||||
|
activeForm.LoadLastPlate();
|
||||||
|
|
||||||
// Decrement requested quantities by counting parts actually
|
var engine = new NestEngine(plate) { PlateNumber = plateNumber };
|
||||||
// placed on this plate, grouped by drawing.
|
var filled = false;
|
||||||
foreach (var group in plate.Parts.GroupBy(p => p.BaseDrawing))
|
|
||||||
{
|
|
||||||
var placed = group.Count();
|
|
||||||
|
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
if (item.Drawing == group.Key)
|
if (item.Quantity <= 0)
|
||||||
item.Quantity -= placed;
|
continue;
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Run the engine on a background thread
|
||||||
|
var parts = await Task.Run(() =>
|
||||||
|
engine.Fill(item, plate.WorkArea(), progress, token));
|
||||||
|
|
||||||
|
if (parts.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
filled = true;
|
||||||
|
|
||||||
|
// Count parts per drawing before accepting (for quantity tracking)
|
||||||
|
foreach (var group in parts.GroupBy(p => p.BaseDrawing))
|
||||||
|
{
|
||||||
|
var placed = group.Count();
|
||||||
|
|
||||||
|
foreach (var ni in items)
|
||||||
|
{
|
||||||
|
if (ni.Drawing == group.Key)
|
||||||
|
ni.Quantity -= placed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept the preview parts into the real plate
|
||||||
|
activeForm.PlateView.AcceptTemporaryParts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!filled)
|
||||||
|
break;
|
||||||
|
|
||||||
|
plateNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
activeForm.Nest.UpdateDrawingQuantities();
|
activeForm.Nest.UpdateDrawingQuantities();
|
||||||
|
progressForm.ShowCompleted();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
activeForm.PlateView.ClearTemporaryParts();
|
||||||
|
MessageBox.Show($"Nesting error: {ex.Message}", "Error",
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
progressForm.Close();
|
||||||
|
SetNestingLockout(false);
|
||||||
|
nestingCts.Dispose();
|
||||||
|
nestingCts = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user