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;
}
}