feat(ui): centralize retained window lifecycle
This commit is contained in:
parent
4bb37e302e
commit
6e9e10367f
12 changed files with 778 additions and 57 deletions
115
src/AcDream.App/UI/RetailWindowHandle.cs
Normal file
115
src/AcDream.App/UI/RetailWindowHandle.cs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
|
||||
namespace AcDream.App.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Typed ownership handle for one named retained window. Geometry and opacity
|
||||
/// mutations flow through this handle so lifecycle observers see the same state
|
||||
/// regardless of whether a change came from input, restore, or controller logic.
|
||||
/// </summary>
|
||||
public sealed class RetailWindowHandle
|
||||
{
|
||||
private readonly RetailWindowManager _owner;
|
||||
private bool _notifiedVisible;
|
||||
private bool _closedSinceShown;
|
||||
private bool _disposed;
|
||||
|
||||
internal RetailWindowHandle(
|
||||
RetailWindowManager owner,
|
||||
string name,
|
||||
UiElement outerFrame,
|
||||
UiElement contentRoot,
|
||||
IRetainedPanelController? controller)
|
||||
{
|
||||
_owner = owner;
|
||||
Name = name;
|
||||
OuterFrame = outerFrame;
|
||||
ContentRoot = contentRoot;
|
||||
Controller = controller;
|
||||
_notifiedVisible = outerFrame.Visible;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public UiElement OuterFrame { get; }
|
||||
public UiElement ContentRoot { get; }
|
||||
public IRetainedPanelController? Controller { get; }
|
||||
public bool IsRegistered => !_disposed;
|
||||
public bool IsVisible => OuterFrame.Visible;
|
||||
public bool IsLocked => _owner.IsLocked;
|
||||
public float Left => OuterFrame.Left;
|
||||
public float Top => OuterFrame.Top;
|
||||
public float Width => OuterFrame.Width;
|
||||
public float Height => OuterFrame.Height;
|
||||
public float Opacity => OuterFrame.Opacity;
|
||||
|
||||
public event Action<RetailWindowHandle>? Shown;
|
||||
public event Action<RetailWindowHandle>? Hidden;
|
||||
public event Action<RetailWindowHandle>? Moved;
|
||||
public event Action<RetailWindowHandle>? Resized;
|
||||
public event Action<RetailWindowHandle>? Closed;
|
||||
public event Action<RetailWindowHandle, bool>? LockChanged;
|
||||
public event Action<RetailWindowHandle, UiElement?>? DescendantFocusChanged;
|
||||
public event Action<RetailWindowHandle, UiElement?>? DescendantCaptureChanged;
|
||||
|
||||
public bool Show() => IsRegistered && _owner.Show(Name);
|
||||
public bool Hide() => IsRegistered && _owner.Hide(Name);
|
||||
public bool Close() => IsRegistered && _owner.Close(Name);
|
||||
public bool MoveTo(float left, float top)
|
||||
=> IsRegistered && _owner.MoveTo(Name, left, top);
|
||||
public bool ResizeTo(float width, float height)
|
||||
=> IsRegistered && _owner.ResizeTo(Name, width, height);
|
||||
public bool SetOpacity(float opacity)
|
||||
=> IsRegistered && _owner.SetOpacity(Name, opacity);
|
||||
|
||||
internal void NotifyInitialState()
|
||||
{
|
||||
if (_notifiedVisible)
|
||||
Controller?.OnShown();
|
||||
}
|
||||
|
||||
internal void NotifyVisibility(bool visible)
|
||||
{
|
||||
if (_notifiedVisible == visible) return;
|
||||
_notifiedVisible = visible;
|
||||
|
||||
if (visible)
|
||||
{
|
||||
_closedSinceShown = false;
|
||||
Controller?.OnShown();
|
||||
Shown?.Invoke(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Controller?.OnHidden();
|
||||
Hidden?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyMoved() => Moved?.Invoke(this);
|
||||
internal void NotifyResized() => Resized?.Invoke(this);
|
||||
|
||||
internal void NotifyClosed()
|
||||
{
|
||||
if (_closedSinceShown) return;
|
||||
_closedSinceShown = true;
|
||||
Closed?.Invoke(this);
|
||||
}
|
||||
|
||||
internal void NotifyLockChanged(bool locked) => LockChanged?.Invoke(this, locked);
|
||||
|
||||
internal void NotifyDescendantFocusChanged(UiElement? focusedDescendant)
|
||||
{
|
||||
Controller?.OnDescendantFocusChanged(focusedDescendant);
|
||||
DescendantFocusChanged?.Invoke(this, focusedDescendant);
|
||||
}
|
||||
|
||||
internal void NotifyDescendantCaptureChanged(UiElement? capturedDescendant)
|
||||
=> DescendantCaptureChanged?.Invoke(this, capturedDescendant);
|
||||
|
||||
internal void DisposeController()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
Controller?.Dispose();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue