using AcDream.App.UI; using AcDream.App.UI.Layout; using DatReaderWriter; namespace AcDream.App.Studio; /// Which kind of source the studio is currently previewing. public enum LayoutSourceKind { DatLayout, Markup } /// /// Wraps the two ways the UI Studio can load a panel to preview: /// a LayoutDesc dat id, or a KSML markup file path (Task 6 — unsupported now). /// /// Call with the current to /// import the layout and get the root . The result is also /// cached in so can re-run the same /// source without re-reading the options. /// public sealed class LayoutSource { private readonly DatCollection _dats; private readonly Func _resolve; private readonly UiDatFont? _datFont; private readonly Func? _fontResolve; public LayoutSourceKind Kind { get; private set; } public uint? LayoutId { get; private set; } public string? MarkupPath { get; private set; } public string? LastError { get; private set; } public ImportedLayout? CurrentLayout { get; private set; } /// /// Create a LayoutSource. /// /// Optional per-element font resolver: FontDid → /// (null when the font isn't in the dats). When supplied, /// elements with a non-zero FontDid receive their own dat font at build time /// instead of the shared global. Controllers that /// explicitly set after /// still override the build-time value. /// Pass null (default) for the original single-font behavior — the live /// path passes null so it is provably unchanged. public LayoutSource( DatCollection dats, Func resolve, UiDatFont? datFont, Func? fontResolve = null) { _dats = dats ?? throw new ArgumentNullException(nameof(dats)); _resolve = resolve ?? throw new ArgumentNullException(nameof(resolve)); _datFont = datFont; _fontResolve = fontResolve; } /// /// Load the layout described by . For a dat layout /// ( is non-null) calls /// . For a markup path sets /// and returns null (Task 6, not yet implemented). /// /// Returns the root on success, or null on failure /// (check ). /// public UiElement? Load(StudioOptions opts) { LastError = null; CurrentLayout = null; if (opts.MarkupPath is not null) { Kind = LayoutSourceKind.Markup; MarkupPath = opts.MarkupPath; LastError = "markup unsupported (Task 6)"; return null; } if (opts.LayoutId is null) { LastError = "ui-studio: no layout id or markup path specified."; return null; } Kind = LayoutSourceKind.DatLayout; LayoutId = opts.LayoutId; return LoadDat(opts.LayoutId.Value); } /// Re-run the most-recently-configured source without re-reading options. public UiElement? Reload() { LastError = null; CurrentLayout = null; if (Kind == LayoutSourceKind.Markup) { LastError = "markup unsupported (Task 6)"; return null; } if (LayoutId is null) { LastError = "ui-studio: no layout id to reload."; return null; } return LoadDat(LayoutId.Value); } // ── Private ────────────────────────────────────────────────────────────────── private UiElement? LoadDat(uint layoutId) { var imported = LayoutImporter.Import(_dats, layoutId, _resolve, _datFont, _fontResolve); if (imported is null) { LastError = $"ui-studio: LayoutDesc 0x{layoutId:X8} not found in dats."; return null; } CurrentLayout = imported; return imported.Root; } }