acdream/src/AcDream.App/UI/UiCollapsibleFrame.cs

47 lines
2.2 KiB
C#

using System;
using System.Collections.Generic;
namespace AcDream.App.UI;
/// <summary>
/// A toolbar-frame variant that snaps its height between two stops — collapsed (row 2 hidden) and
/// expanded (row 2 shown) — and toggles a set of "second-row" elements to match. Resized via the
/// bottom edge (the mount sets <see cref="UiElement.ResizableEdges"/> = Bottom); each tick it resolves
/// the dragged height to the nearer stop so the frame always rests collapsed or expanded — never a
/// half-row. Toolkit UX (keystone.dll has no decomp; the dat stacks both rows always) — see IA-17.
/// </summary>
public sealed class UiCollapsibleFrame : UiNineSlicePanel, IRetainedWindowStateController
{
public UiCollapsibleFrame(Func<uint, (uint, int, int)> resolve) : base(resolve) { }
public float CollapsedHeight { get; set; }
public float ExpandedHeight { get; set; }
/// <summary>Elements shown only when expanded (the row-2 slot lists). Hidden when collapsed.</summary>
public IReadOnlyList<UiElement> SecondRow { get; set; } = Array.Empty<UiElement>();
/// <summary>True when the frame is at (or nearer) the expanded stop.</summary>
public bool IsExpanded => Height >= (CollapsedHeight + ExpandedHeight) * 0.5f;
protected override void OnTick(double deltaSeconds)
{
base.OnTick(deltaSeconds);
if (ExpandedHeight <= CollapsedHeight) return; // not configured yet — no snap
bool expanded = IsExpanded;
Height = expanded ? ExpandedHeight : CollapsedHeight; // snap the dragged height to a stop
for (int i = 0; i < SecondRow.Count; i++) SecondRow[i].Visible = expanded;
}
/// <summary>Test hook — OnTick is protected. Drives one snap+visibility reconcile.</summary>
internal void TickForTest(double dt) => OnTick(dt);
public RetainedWindowState CaptureWindowState()
=> new(Collapsed: !IsExpanded);
public void RestoreWindowState(RetainedWindowState state)
{
if (ExpandedHeight <= CollapsedHeight) return;
Height = state.Collapsed ? CollapsedHeight : ExpandedHeight;
for (int i = 0; i < SecondRow.Count; i++)
SecondRow[i].Visible = !state.Collapsed;
}
}