Files
OpenNest/OpenNest.Desktop/Forms/EngineSelection.cs
T
ajandClaude Opus 5.5 44372d129e feat(ui): rename the Fill engine to Lattice and describe engines
"Fill" said nothing about what the engine does, since every engine fills.
It is now Lattice, and Fill stays an alias, so saved selections, scripts
and API requests keep working. Engine descriptions are rewritten in plain
language and shown beside each name in the desktop engine lists; the main
toolbar's tooltip also says when Fill Area falls back to Lattice.

Docs also cover the leftover placement from the previous commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 21:17:16 -05:00

92 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using OpenNest.Data;
using OpenNest.Engine.Jobs;
using OpenNest.Engine.Jobs.Placement;
namespace OpenNest.Forms
{
/// <summary>
/// App-scoped nesting-engine selection. The selected name addresses a whole-job
/// INestingEngine resolved through NestingEngineRegistry at call time; single-plate
/// interactive fill uses FillStrategy, which maps a built-in engine to its placement
/// strategy and falls back to Fill for jobs-only engines and plug-ins.
/// </summary>
public static class EngineSelection
{
public const string DefaultEngineName = EngineSelectionSettings.DefaultEngineName;
private static string engineName = DefaultEngineName;
/// <summary>Current selection. User changes are persisted for the next launch.</summary>
public static string EngineName
{
get { return engineName; }
set
{
engineName = string.IsNullOrWhiteSpace(value)
? DefaultEngineName
: value.Trim();
try
{
new EngineSelectionSettings { EngineName = engineName }
.Save(EngineSelectionSettings.DefaultPath);
}
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
{
// A read-only profile must not prevent selecting an engine for this session.
Debug.WriteLine($"[EngineSelection] Could not save engine selection: {ex.Message}");
}
}
}
/// <summary>
/// Call after NestingEngineRegistry.LoadPlugins and before populating the desktop combo.
/// Returns a status-bar warning when the saved engine is unavailable, otherwise empty.
/// Loading never saves the fallback over a temporarily missing plug-in preference.
/// </summary>
public static string LoadSavedSelection()
{
var settings = EngineSelectionSettings.Load(EngineSelectionSettings.DefaultPath);
engineName = settings.Resolve(UiEngineNames, out var statusMessage, NestingEngineRegistry.ResolveName);
return statusMessage ?? string.Empty;
}
/// <summary>Desktop combo contents: every registered jobs engine.</summary>
public static IEnumerable<string> UiEngineNames =>
NestingEngineRegistry.AvailableEngines.Select(e => e.Name).ToList();
/// <summary>Placement strategy for single-plate fill: the selection when it names a
/// built-in strategy, otherwise Fill.</summary>
public static string FillStrategy => IsFillStrategy(engineName) ? engineName : PlateFillService.DefaultStrategy;
public static bool IsFillStrategy(string name)
{
var resolved = NestingEngineRegistry.ResolveName(name);
return resolved != null
&& PlateFillService.BuiltInStrategies.Any(
s => s.Equals(resolved, StringComparison.OrdinalIgnoreCase)
);
}
/// <summary>The plain description shown beside an engine's name; empty for plug-ins.</summary>
public static string Description(string name) =>
NestingEngineRegistry.AvailableEngines
.FirstOrDefault(e => e.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
?.Description ?? string.Empty;
/// <summary>The description plus what Fill Area uses, for a tooltip on the selection.</summary>
public static string ToolTip(string name)
{
var description = Description(name);
return IsFillStrategy(name)
? description
: $"{description}\nFill Area uses {PlateFillService.DefaultStrategy} with this engine.".TrimStart();
}
}
}