From 5568789902fccbb71a98a8f8790c97cbcf43ed02 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Fri, 27 Mar 2026 14:14:10 -0400 Subject: [PATCH] feat: add fill strategy enable/disable settings in options OptionsForm now shows checkboxes for each fill strategy, persisted via the new DisabledStrategies user setting. FillStrategyRegistry exposes AllStrategies and DisabledNames for the UI. MainForm applies disabled strategies on startup via OptionsForm.ApplyDisabledStrategies(). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Strategies/FillStrategyRegistry.cs | 11 +++ OpenNest/Forms/MainForm.cs | 2 + OpenNest/Forms/OptionsForm.Designer.cs | 16 ++++- OpenNest/Forms/OptionsForm.cs | 71 +++++++++++++++++-- OpenNest/Properties/Settings.Designer.cs | 12 ++++ OpenNest/Properties/Settings.settings | 3 + 6 files changed, 109 insertions(+), 6 deletions(-) diff --git a/OpenNest.Engine/Strategies/FillStrategyRegistry.cs b/OpenNest.Engine/Strategies/FillStrategyRegistry.cs index 1c1759b..1d86771 100644 --- a/OpenNest.Engine/Strategies/FillStrategyRegistry.cs +++ b/OpenNest.Engine/Strategies/FillStrategyRegistry.cs @@ -22,6 +22,17 @@ namespace OpenNest.Engine.Strategies public static IReadOnlyList Strategies => sorted ??= FilterStrategies(); + /// + /// Returns all registered strategies regardless of enabled/disabled state. + /// + public static IReadOnlyList AllStrategies => + strategies.OrderBy(s => s.Order).ToList(); + + /// + /// Returns the names of all permanently disabled strategies. + /// + public static IReadOnlyCollection DisabledNames => disabled; + private static List FilterStrategies() { var source = enabledFilter != null diff --git a/OpenNest/Forms/MainForm.cs b/OpenNest/Forms/MainForm.cs index 8fbd7e4..17b9cc5 100644 --- a/OpenNest/Forms/MainForm.cs +++ b/OpenNest/Forms/MainForm.cs @@ -58,6 +58,8 @@ namespace OpenNest.Forms var enginesDir = Path.Combine(Application.StartupPath, "Engines"); NestEngineRegistry.LoadPlugins(enginesDir); + OptionsForm.ApplyDisabledStrategies(); + foreach (var engine in NestEngineRegistry.AvailableEngines) engineComboBox.Items.Add(engine.Name); diff --git a/OpenNest/Forms/OptionsForm.Designer.cs b/OpenNest/Forms/OptionsForm.Designer.cs index c1d4776..5b69880 100644 --- a/OpenNest/Forms/OptionsForm.Designer.cs +++ b/OpenNest/Forms/OptionsForm.Designer.cs @@ -42,6 +42,7 @@ this.saveButton = new System.Windows.Forms.Button(); this.cancelButton = new System.Windows.Forms.Button(); this.bottomPanel1 = new OpenNest.Controls.BottomPanel(); + this.strategyGroupBox = new System.Windows.Forms.GroupBox(); ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); this.tableLayoutPanel1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); @@ -210,13 +211,23 @@ this.bottomPanel1.Name = "bottomPanel1"; this.bottomPanel1.Size = new System.Drawing.Size(708, 50); this.bottomPanel1.TabIndex = 1; - // + // + // strategyGroupBox + // + this.strategyGroupBox.Location = new System.Drawing.Point(12, 178); + this.strategyGroupBox.Name = "strategyGroupBox"; + this.strategyGroupBox.Size = new System.Drawing.Size(684, 180); + this.strategyGroupBox.TabIndex = 2; + this.strategyGroupBox.TabStop = false; + this.strategyGroupBox.Text = "Fill Strategies"; + // // OptionsForm - // + // this.AcceptButton = this.saveButton; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.CancelButton = this.cancelButton; this.ClientSize = new System.Drawing.Size(708, 418); + this.Controls.Add(this.strategyGroupBox); this.Controls.Add(this.tableLayoutPanel1); this.Controls.Add(this.bottomPanel1); this.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); @@ -252,5 +263,6 @@ private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Label label3; private System.Windows.Forms.Button button1; + private System.Windows.Forms.GroupBox strategyGroupBox; } } \ No newline at end of file diff --git a/OpenNest/Forms/OptionsForm.cs b/OpenNest/Forms/OptionsForm.cs index 7bb6d15..552db2a 100644 --- a/OpenNest/Forms/OptionsForm.cs +++ b/OpenNest/Forms/OptionsForm.cs @@ -1,27 +1,58 @@ -using OpenNest.Properties; +using OpenNest.Engine.Strategies; +using OpenNest.Properties; +using System; +using System.Collections.Generic; +using System.Linq; using System.Windows.Forms; namespace OpenNest.Forms { public partial class OptionsForm : Form { + private readonly List _strategyCheckBoxes = new(); + public OptionsForm() { InitializeComponent(); + BuildStrategyCheckBoxes(); } - protected override void OnLoad(System.EventArgs e) + protected override void OnLoad(EventArgs e) { base.OnLoad(e); LoadSettings(); } + private void BuildStrategyCheckBoxes() + { + var strategies = FillStrategyRegistry.AllStrategies; + var y = 20; + + foreach (var strategy in strategies) + { + var cb = new CheckBox + { + Text = strategy.Name, + Tag = strategy.Name, + AutoSize = true, + Location = new System.Drawing.Point(10, y), + }; + strategyGroupBox.Controls.Add(cb); + _strategyCheckBoxes.Add(cb); + y += 24; + } + } + private void LoadSettings() { textBox1.Text = Settings.Default.NestTemplatePath; checkBox1.Checked = Settings.Default.CreateNewNestOnOpen; numericUpDown1.Value = (decimal)Settings.Default.AutoSizePlateFactor; numericUpDown2.Value = (decimal)Settings.Default.ImportSplinePrecision; + + var disabledNames = ParseDisabledStrategies(Settings.Default.DisabledStrategies); + foreach (var cb in _strategyCheckBoxes) + cb.Checked = !disabledNames.Contains((string)cb.Tag); } private void SaveSettings() @@ -30,15 +61,47 @@ namespace OpenNest.Forms Settings.Default.CreateNewNestOnOpen = checkBox1.Checked; Settings.Default.AutoSizePlateFactor = (double)numericUpDown1.Value; Settings.Default.ImportSplinePrecision = (int)numericUpDown2.Value; + + var disabledNames = _strategyCheckBoxes + .Where(cb => !cb.Checked) + .Select(cb => (string)cb.Tag); + Settings.Default.DisabledStrategies = string.Join(",", disabledNames); + Settings.Default.Save(); + ApplyDisabledStrategies(); } - private void SaveSettings_Click(object sender, System.EventArgs e) + /// + /// Applies the DisabledStrategies setting to the FillStrategyRegistry. + /// Called on save and at startup from MainForm. + /// + public static void ApplyDisabledStrategies() + { + // Re-enable all, then disable the persisted set. + var all = FillStrategyRegistry.AllStrategies.Select(s => s.Name).ToArray(); + FillStrategyRegistry.Enable(all); + + var disabled = ParseDisabledStrategies(Settings.Default.DisabledStrategies); + if (disabled.Count > 0) + FillStrategyRegistry.Disable(disabled.ToArray()); + } + + private static HashSet ParseDisabledStrategies(string value) + { + if (string.IsNullOrWhiteSpace(value)) + return new HashSet(StringComparer.OrdinalIgnoreCase); + + return new HashSet( + value.Split(',').Select(s => s.Trim()).Where(s => s.Length > 0), + StringComparer.OrdinalIgnoreCase); + } + + private void SaveSettings_Click(object sender, EventArgs e) { SaveSettings(); } - private void BrowseNestTemplatePath_Click(object sender, System.EventArgs e) + private void BrowseNestTemplatePath_Click(object sender, EventArgs e) { var dlg = new OpenFileDialog(); dlg.Filter = "Template File|*.nstdot"; diff --git a/OpenNest/Properties/Settings.Designer.cs b/OpenNest/Properties/Settings.Designer.cs index 595021a..4d0f038 100644 --- a/OpenNest/Properties/Settings.Designer.cs +++ b/OpenNest/Properties/Settings.Designer.cs @@ -214,5 +214,17 @@ namespace OpenNest.Properties { this["LastPierceTime"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("")] + public string DisabledStrategies { + get { + return ((string)(this["DisabledStrategies"])); + } + set { + this["DisabledStrategies"] = value; + } + } } } diff --git a/OpenNest/Properties/Settings.settings b/OpenNest/Properties/Settings.settings index a699740..ad2fe61 100644 --- a/OpenNest/Properties/Settings.settings +++ b/OpenNest/Properties/Settings.settings @@ -50,5 +50,8 @@ 0 + + + \ No newline at end of file