From c6f544c5d789c679468b12bf7dae3d377f3101a9 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Wed, 15 Apr 2026 06:12:54 -0400 Subject: [PATCH] feat(ui): populate material combobox from post processors Replaces the material textbox on EditNestInfoForm with a combobox whose items are aggregated from every loaded post processor that implements the new IMaterialProvidingPostProcessor interface. CincinnatiPostProcessor exposes its configured MaterialLibraries entries. Free-text entry still works so custom materials remain usable. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../IMaterialProvidingPostProcessor.cs | 9 ++++++ .../CincinnatiPostProcessor.cs | 12 +++++++- OpenNest/Forms/EditNestInfoForm.Designer.cs | 7 +++-- OpenNest/Forms/EditNestInfoForm.cs | 3 ++ OpenNest/Forms/MainForm.cs | 6 ++++ OpenNest/PostProcessorMaterials.cs | 30 +++++++++++++++++++ 6 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 OpenNest.Core/IMaterialProvidingPostProcessor.cs create mode 100644 OpenNest/PostProcessorMaterials.cs diff --git a/OpenNest.Core/IMaterialProvidingPostProcessor.cs b/OpenNest.Core/IMaterialProvidingPostProcessor.cs new file mode 100644 index 0000000..85fcf33 --- /dev/null +++ b/OpenNest.Core/IMaterialProvidingPostProcessor.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace OpenNest +{ + public interface IMaterialProvidingPostProcessor + { + IEnumerable GetMaterialNames(); + } +} diff --git a/OpenNest.Posts.Cincinnati/CincinnatiPostProcessor.cs b/OpenNest.Posts.Cincinnati/CincinnatiPostProcessor.cs index 0699b05..0567c28 100644 --- a/OpenNest.Posts.Cincinnati/CincinnatiPostProcessor.cs +++ b/OpenNest.Posts.Cincinnati/CincinnatiPostProcessor.cs @@ -9,7 +9,7 @@ using OpenNest.CNC; namespace OpenNest.Posts.Cincinnati { - public sealed class CincinnatiPostProcessor : IConfigurablePostProcessor + public sealed class CincinnatiPostProcessor : IConfigurablePostProcessor, IMaterialProvidingPostProcessor { private static readonly JsonSerializerOptions JsonOptions = new() { @@ -25,6 +25,16 @@ namespace OpenNest.Posts.Cincinnati object IConfigurablePostProcessor.Config => Config; + public IEnumerable GetMaterialNames() + { + if (Config?.MaterialLibraries == null) + return System.Array.Empty(); + + return Config.MaterialLibraries + .Select(e => e.Material) + .Where(s => !string.IsNullOrWhiteSpace(s)); + } + public CincinnatiPostProcessor() { var configPath = GetConfigPath(); diff --git a/OpenNest/Forms/EditNestInfoForm.Designer.cs b/OpenNest/Forms/EditNestInfoForm.Designer.cs index aa4d802..bc86cf7 100644 --- a/OpenNest/Forms/EditNestInfoForm.Designer.cs +++ b/OpenNest/Forms/EditNestInfoForm.Designer.cs @@ -63,7 +63,7 @@ this.textBox2 = new System.Windows.Forms.TextBox(); this.label5 = new System.Windows.Forms.Label(); this.labelMaterial = new System.Windows.Forms.Label(); - this.materialBox = new System.Windows.Forms.TextBox(); + this.materialBox = new System.Windows.Forms.ComboBox(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.tabPage3 = new System.Windows.Forms.TabPage(); this.notesBox = new System.Windows.Forms.TextBox(); @@ -516,9 +516,10 @@ // materialBox // this.materialBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.materialBox.FormattingEnabled = true; this.materialBox.Location = new System.Drawing.Point(135, 159); this.materialBox.Name = "materialBox"; - this.materialBox.Size = new System.Drawing.Size(224, 22); + this.materialBox.Size = new System.Drawing.Size(224, 24); this.materialBox.TabIndex = 11; // // label3 @@ -729,6 +730,6 @@ private System.Windows.Forms.RadioButton radioButton2; private System.Windows.Forms.Label label5; private System.Windows.Forms.Label labelMaterial; - private System.Windows.Forms.TextBox materialBox; + private System.Windows.Forms.ComboBox materialBox; } } \ No newline at end of file diff --git a/OpenNest/Forms/EditNestInfoForm.cs b/OpenNest/Forms/EditNestInfoForm.cs index 63a5d03..e82c066 100644 --- a/OpenNest/Forms/EditNestInfoForm.cs +++ b/OpenNest/Forms/EditNestInfoForm.cs @@ -15,6 +15,9 @@ namespace OpenNest.Forms { InitializeComponent(); + foreach (var name in PostProcessorMaterials.Names) + materialBox.Items.Add(name); + timer = new Timer { SynchronizingObject = this, diff --git a/OpenNest/Forms/MainForm.cs b/OpenNest/Forms/MainForm.cs index 4f4d5b4..9bbe050 100644 --- a/OpenNest/Forms/MainForm.cs +++ b/OpenNest/Forms/MainForm.cs @@ -351,6 +351,9 @@ namespace OpenNest.Forms postProcessorMenuItem.Tag = postProcessor; postProcessorMenuItem.Click += PostProcessor_Click; mnuNestPost.DropDownItems.Add(postProcessorMenuItem); + + if (postProcessor is IMaterialProvidingPostProcessor materialProvider) + PostProcessorMaterials.AddFrom(materialProvider); } } } @@ -1157,6 +1160,9 @@ namespace OpenNest.Forms if (postProcessor == null) return; + if (postProcessor is IPostProcessorNestAware nestAware) + nestAware.PrepareForNest(activeForm.Nest); + if (postProcessor is IConfigurablePostProcessor configurable) { using var configForm = new PostProcessorConfigForm(configurable); diff --git a/OpenNest/PostProcessorMaterials.cs b/OpenNest/PostProcessorMaterials.cs new file mode 100644 index 0000000..beadcee --- /dev/null +++ b/OpenNest/PostProcessorMaterials.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace OpenNest +{ + public static class PostProcessorMaterials + { + private static readonly List materials = new(); + + public static IReadOnlyList Names => materials; + + public static void AddFrom(IMaterialProvidingPostProcessor provider) + { + if (provider == null) + return; + + foreach (var name in provider.GetMaterialNames()) + { + if (!string.IsNullOrWhiteSpace(name) + && !materials.Contains(name, StringComparer.OrdinalIgnoreCase)) + { + materials.Add(name); + } + } + + materials.Sort(StringComparer.OrdinalIgnoreCase); + } + } +}