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 { /// /// 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. /// public static class EngineSelection { public const string DefaultEngineName = EngineSelectionSettings.DefaultEngineName; private static string engineName = DefaultEngineName; /// Current selection. User changes are persisted for the next launch. 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}"); } } } /// /// 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. /// public static string LoadSavedSelection() { var settings = EngineSelectionSettings.Load(EngineSelectionSettings.DefaultPath); engineName = settings.Resolve(UiEngineNames, out var statusMessage, NestingEngineRegistry.ResolveName); return statusMessage ?? string.Empty; } /// Desktop combo contents: every registered jobs engine. public static IEnumerable UiEngineNames => NestingEngineRegistry.AvailableEngines.Select(e => e.Name).ToList(); /// Placement strategy for single-plate fill: the selection when it names a /// built-in strategy, otherwise Fill. public static string FillStrategy => IsFillStrategy(engineName) ? engineName : PlateFillService.DefaultStrategy; public static bool IsFillStrategy(string name) => !string.IsNullOrWhiteSpace(name) && PlateFillService.BuiltInStrategies.Any( s => s.Equals(name.Trim(), StringComparison.OrdinalIgnoreCase) ); } }