7.1 KiB
NestProgressForm Redesign
Problem
The current NestProgressForm is a flat list of label/value pairs with no visual hierarchy, no progress indicator, and default WinForms styling. It's functional but looks basic and gives no sense of where the engine is in its process.
Solution
Redesign the form with three changes:
- A custom-drawn phase stepper control showing which nesting phases have been visited
- Grouped sections separating results from status information
- Modern styling — Segoe UI fonts, subtle background contrast, better spacing
Phase Stepper Control
New file: OpenNest/Controls/PhaseStepperControl.cs
A custom UserControl that draws 4 circles with labels beneath, connected by lines:
●━━━━━━━●━━━━━━━○━━━━━━━○
Linear BestFit Pairs Remainder
Non-sequential design
The engine does not execute phases in a fixed order. FindBestFill runs Pairs → Linear → BestFit → Remainder, while the group fill path runs Linear → BestFit → Pairs → Remainder. Some phases may not execute at all (e.g., multi-part fills only run Linear).
The stepper therefore tracks which phases have been visited, not a left-to-right progression. Each circle independently lights up when its phase reports progress, regardless of position. The connecting lines between circles are purely decorative (always light gray) — they do not indicate sequential flow.
Visual States
- Completed/visited: Filled circle with accent color, bold label — the phase has reported at least one progress update
- Active: Filled circle with accent color and slightly larger radius, bold label — the phase currently executing
- Pending: Hollow circle with border only, dimmed label text — the phase has not yet reported progress
- Skipped: Same as Pending — phases that never execute simply remain hollow. No special "skipped" visual needed.
- All complete: All 4 circles filled (used when
ShowCompleted()is called) - Initial state (before first
UpdateProgress): All 4 circles in Pending (hollow) state
Implementation
- Single
OnPaintoverride. Circles evenly spaced across control width. Connecting lines drawn between circle centers in light gray. - Colors and fonts defined as
static readonlyfields at the top of the class. Fonts are cached (not created per paint call) to avoid GDI handle leaks during frequent progress updates. - Tracks state via a
HashSet<NestPhase> VisitedPhasesand aNestPhase? ActivePhaseproperty. WhenActivePhaseis set, it is added toVisitedPhasesandInvalidate()is called. Abool IsCompleteproperty marks all phases as done. DoubleBuffered = trueto prevent flicker on repaint.- Fixed height (~60px), docks to fill width.
- Namespace:
OpenNest.Controls(follows existing convention, e.g.,QuadrantSelect).
Form Layout
Three vertical zones using DockStyle.Top stacking:
┌─────────────────────────────────────┐
│ ●━━━━━━━●━━━━━━━○━━━━━━━○ │ Phase stepper
│ Linear BestFit Pairs Remainder │
├─────────────────────────────────────┤
│ Results │ Results group
│ Parts: 156 │
│ Density: 68.3% │
│ Nested: 24.1 x 36.0 (867.6 sq in)│
│ Unused: 43.2 sq in │
├─────────────────────────────────────┤
│ Status │ Status group
│ Plate: 2 │
│ Elapsed: 1:24 │
│ Detail: Trying 45° rotation... │
├─────────────────────────────────────┤
│ [ Stop ] │ Button bar
└─────────────────────────────────────┘
Group Panels
Each group is a Panel containing:
- A header label (Segoe UI 9pt bold) at the top
- A
TableLayoutPanelwith label/value rows beneath
Group panels use Color.White (or very light gray) BackColor against the form's SystemColors.Control background to create visual separation without borders. Small padding/margins between groups.
Typography
- All fonts: Segoe UI (replaces MS Sans Serif)
- Group headers: 9pt bold
- Row labels: 8.25pt bold
- Row values: 8.25pt regular
- Value labels use
ForeColor = SystemColors.ControlText
Sizing
- Width: ~450px (slightly wider than current 425px for breathing room)
- Height: fixed
ClientSizecalculated to fit stepper (~60px) + results group (~110px) + status group (~90px) + button bar (~45px) + padding. The form usesFixedToolWindowwhich does not auto-resize, so the height is set explicitly in the designer. FormBorderStyle.FixedToolWindow,StartPosition.CenterParent,ShowInTaskbar = false
Plate Row Visibility
The Plate row in the Status group is hidden when showPlateRow: false is passed to the constructor (same as current behavior).
Phase description text
The current form's FormatPhase() method produces friendly text like "Trying rotations..." which was displayed in the Phase row. Since the phase stepper replaces the Phase row visually, this descriptive text moves to the Detail row. UpdateProgress writes FormatPhase(progress.Phase) to the Detail value when progress.Description is empty, and writes progress.Description when it's set (the engine's per-iteration descriptions like "Linear: 3/12 angles" take precedence).
Public API
No signature changes. The form remains a drop-in replacement.
Constructor
NestProgressForm(CancellationTokenSource cts, bool showPlateRow = true) — unchanged.
UpdateProgress(NestProgress progress)
Same as today, plus:
- Sets
phaseStepperControl.ActivePhase = progress.Phaseto update the stepper - Writes
FormatPhase(progress.Phase)to the Detail row as a fallback whenprogress.Descriptionis empty
ShowCompleted()
Same as today (stops timer, changes button to "Close"), plus sets phaseStepperControl.IsComplete = true to fill all circles.
Note: MainForm.FillArea_Click currently calls progressForm.Close() without calling ShowCompleted() first. This is existing behavior and is fine — the form closes immediately so the "all complete" visual is not needed in that path.
No External Changes
NestProgressandNestPhaseare unchanged.- All callers (
MainForm,PlateView.FillWithProgress) continue callingUpdateProgressandShowCompletedwith no code changes. - The form file paths remain the same — this is a modification, not a new form.
Files Touched
| File | Change |
|---|---|
OpenNest/Controls/PhaseStepperControl.cs |
New — custom-drawn phase stepper control |
OpenNest/Forms/NestProgressForm.cs |
Rewritten — grouped layout, stepper integration |
OpenNest/Forms/NestProgressForm.Designer.cs |
Rewritten — new control layout |