feat(ui): show both horizontal and vertical fill previews side by side
Replace single preview PlateView with two stacked previews showing horizontal and vertical FillLinear results. Each has a label showing the part count. Apply uses the direction with more parts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,10 @@ namespace OpenNest.Forms
|
||||
{
|
||||
private readonly Nest nest;
|
||||
private readonly PlateView cellView;
|
||||
private readonly PlateView previewView;
|
||||
private readonly PlateView hPreview;
|
||||
private readonly PlateView vPreview;
|
||||
private readonly Label hLabel;
|
||||
private readonly Label vLabel;
|
||||
|
||||
public PatternTileResult Result { get; private set; }
|
||||
|
||||
@@ -43,14 +46,44 @@ namespace OpenNest.Forms
|
||||
cellView.Dock = DockStyle.Fill;
|
||||
splitContainer.Panel1.Controls.Add(cellView);
|
||||
|
||||
// Tile preview — plate visible, read-only
|
||||
previewView = new PlateView();
|
||||
previewView.Plate.Quantity = 0; // prevent Drawing.Quantity.Nested side-effects
|
||||
previewView.AllowSelect = false;
|
||||
previewView.AllowDrop = false;
|
||||
previewView.DrawBounds = false;
|
||||
previewView.Dock = DockStyle.Fill;
|
||||
splitContainer.Panel2.Controls.Add(previewView);
|
||||
// Right side: vertical split with horizontal and vertical preview
|
||||
var previewSplit = new SplitContainer
|
||||
{
|
||||
Dock = DockStyle.Fill,
|
||||
Orientation = Orientation.Horizontal,
|
||||
SplitterDistance = 250
|
||||
};
|
||||
splitContainer.Panel2.Controls.Add(previewSplit);
|
||||
|
||||
hLabel = new Label
|
||||
{
|
||||
Dock = DockStyle.Top,
|
||||
Height = 20,
|
||||
Text = "Horizontal — 0 parts",
|
||||
TextAlign = System.Drawing.ContentAlignment.MiddleLeft,
|
||||
Font = new System.Drawing.Font("Segoe UI", 9f, System.Drawing.FontStyle.Bold),
|
||||
ForeColor = System.Drawing.Color.FromArgb(80, 80, 80),
|
||||
Padding = new Padding(4, 0, 0, 0)
|
||||
};
|
||||
|
||||
hPreview = CreatePreviewView();
|
||||
previewSplit.Panel1.Controls.Add(hPreview);
|
||||
previewSplit.Panel1.Controls.Add(hLabel);
|
||||
|
||||
vLabel = new Label
|
||||
{
|
||||
Dock = DockStyle.Top,
|
||||
Height = 20,
|
||||
Text = "Vertical — 0 parts",
|
||||
TextAlign = System.Drawing.ContentAlignment.MiddleLeft,
|
||||
Font = new System.Drawing.Font("Segoe UI", 9f, System.Drawing.FontStyle.Bold),
|
||||
ForeColor = System.Drawing.Color.FromArgb(80, 80, 80),
|
||||
Padding = new Padding(4, 0, 0, 0)
|
||||
};
|
||||
|
||||
vPreview = CreatePreviewView();
|
||||
previewSplit.Panel2.Controls.Add(vPreview);
|
||||
previewSplit.Panel2.Controls.Add(vLabel);
|
||||
|
||||
// Populate drawing dropdowns
|
||||
var drawings = nest.Drawings.OrderBy(d => d.Name).ToList();
|
||||
@@ -192,32 +225,71 @@ namespace OpenNest.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private static PlateView CreatePreviewView()
|
||||
{
|
||||
var view = new PlateView();
|
||||
view.Plate.Quantity = 0;
|
||||
view.AllowSelect = false;
|
||||
view.AllowDrop = false;
|
||||
view.DrawBounds = false;
|
||||
view.Dock = DockStyle.Fill;
|
||||
return view;
|
||||
}
|
||||
|
||||
private void UpdatePreviewPlateSize()
|
||||
{
|
||||
if (TryGetPlateSize(out var size))
|
||||
previewView.Plate.Size = size;
|
||||
if (!TryGetPlateSize(out var size))
|
||||
return;
|
||||
|
||||
hPreview.Plate.Size = size;
|
||||
vPreview.Plate.Size = size;
|
||||
}
|
||||
|
||||
private Pattern BuildCellPattern()
|
||||
{
|
||||
var cellParts = cellView.Plate.Parts.ToList();
|
||||
if (cellParts.Count == 0)
|
||||
return null;
|
||||
|
||||
var pattern = new Pattern();
|
||||
foreach (var part in cellParts)
|
||||
pattern.Parts.Add(part);
|
||||
pattern.UpdateBounds();
|
||||
return pattern;
|
||||
}
|
||||
|
||||
private void RebuildPreview()
|
||||
{
|
||||
previewView.Plate.Parts.Clear();
|
||||
hPreview.Plate.Parts.Clear();
|
||||
vPreview.Plate.Parts.Clear();
|
||||
|
||||
if (!TryGetPlateSize(out var plateSize))
|
||||
return;
|
||||
|
||||
previewView.Plate.Size = plateSize;
|
||||
previewView.Plate.PartSpacing = PartSpacing;
|
||||
hPreview.Plate.Size = plateSize;
|
||||
hPreview.Plate.PartSpacing = PartSpacing;
|
||||
vPreview.Plate.Size = plateSize;
|
||||
vPreview.Plate.PartSpacing = PartSpacing;
|
||||
|
||||
var cellParts = cellView.Plate.Parts.ToList();
|
||||
if (cellParts.Count == 0)
|
||||
var pattern = BuildCellPattern();
|
||||
if (pattern == null)
|
||||
return;
|
||||
|
||||
var tiled = Engine.PatternTiler.Tile(cellParts, plateSize, PartSpacing);
|
||||
var workArea = new Box(0, 0, plateSize.Width, plateSize.Length);
|
||||
var filler = new FillLinear(workArea, PartSpacing);
|
||||
|
||||
foreach (var part in tiled)
|
||||
previewView.Plate.Parts.Add(part);
|
||||
var hParts = filler.Fill(pattern, NestDirection.Horizontal);
|
||||
foreach (var part in hParts)
|
||||
hPreview.Plate.Parts.Add(part);
|
||||
hLabel.Text = $"Horizontal — {hParts.Count} parts";
|
||||
hPreview.ZoomToFit();
|
||||
|
||||
previewView.ZoomToFit();
|
||||
var vFiller = new FillLinear(workArea, PartSpacing);
|
||||
var vParts = vFiller.Fill(pattern, NestDirection.Vertical);
|
||||
foreach (var part in vParts)
|
||||
vPreview.Plate.Parts.Add(part);
|
||||
vLabel.Text = $"Vertical — {vParts.Count} parts";
|
||||
vPreview.ZoomToFit();
|
||||
}
|
||||
|
||||
private void OnAutoArrangeClick(object sender, EventArgs e)
|
||||
@@ -277,14 +349,29 @@ namespace OpenNest.Forms
|
||||
|
||||
private void OnApplyClick(object sender, EventArgs e)
|
||||
{
|
||||
if (previewView.Plate.Parts.Count == 0)
|
||||
var hCount = hPreview.Plate.Parts.Count;
|
||||
var vCount = vPreview.Plate.Parts.Count;
|
||||
|
||||
if (hCount == 0 && vCount == 0)
|
||||
return;
|
||||
|
||||
if (!TryGetPlateSize(out var plateSize))
|
||||
return;
|
||||
|
||||
// Pick which direction to apply — use the one with more parts,
|
||||
// or ask if they're equal and both > 0
|
||||
NestDirection applyDirection;
|
||||
|
||||
if (hCount > vCount)
|
||||
applyDirection = NestDirection.Horizontal;
|
||||
else if (vCount > hCount)
|
||||
applyDirection = NestDirection.Vertical;
|
||||
else
|
||||
applyDirection = NestDirection.Horizontal; // tie-break
|
||||
|
||||
var choice = MessageBox.Show(
|
||||
"Apply pattern to current plate?\n\nYes = Current plate (clears existing parts)\nNo = New plate",
|
||||
$"Apply {applyDirection} pattern ({(applyDirection == NestDirection.Horizontal ? hCount : vCount)} parts) to current plate?" +
|
||||
"\n\nYes = Current plate (clears existing parts)\nNo = New plate",
|
||||
"Apply Pattern",
|
||||
MessageBoxButtons.YesNoCancel,
|
||||
MessageBoxIcon.Question);
|
||||
@@ -293,8 +380,12 @@ namespace OpenNest.Forms
|
||||
return;
|
||||
|
||||
// Rebuild a fresh set of tiled parts for the caller
|
||||
var cellParts = cellView.Plate.Parts.ToList();
|
||||
var tiledParts = Engine.PatternTiler.Tile(cellParts, plateSize, PartSpacing);
|
||||
var pattern = BuildCellPattern();
|
||||
if (pattern == null)
|
||||
return;
|
||||
|
||||
var filler = new FillLinear(new Box(0, 0, plateSize.Width, plateSize.Length), PartSpacing);
|
||||
var tiledParts = filler.Fill(pattern, applyDirection);
|
||||
|
||||
Result = new PatternTileResult
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user