using Lattice.Layout.Abstractions;
using Lattice.Layout.UI.Docking;
using Lattice.Layout.UI.WinUI.Docking;
using Lattice.Layout.UI.WinUI.Rendering;
using Lattice.Layout.UI.WinUI.Visuals;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
namespace Lattice.Layout.UI.WinUI.Controls;
///
/// WinUI-контрол, отображающий дерево раскладки.
/// Оборачивает LayoutRenderer и размещает визуальное дерево внутри себя.
///
public sealed class WinUILayoutHost : UserControl, ILayoutView
{
///
/// Слой, в котором размещается визуальное дерево раскладки.
///
public Grid LayoutLayer { get; }
///
/// Слой для отображения подсветки зон докинга.
///
public DockOverlayHost OverlayLayer { get; }
private readonly LayoutRenderer _renderer;
private readonly WinUIVisualFactory _factory;
///
/// Функция, возвращающая UI-содержимое по ContentId.
/// Используется визуальными элементами для подстановки реального контрола.
///
public Func? ContentResolver { get; set; }
///
/// Корневой элемент раскладки, который необходимо отобразить.
///
public ILayoutRoot? Root
{
get => (ILayoutRoot?)GetValue(RootProperty);
set => SetValue(RootProperty, value);
}
///
/// Свойство зависимости для .
///
public static readonly DependencyProperty RootProperty =
DependencyProperty.Register(
nameof(Root),
typeof(ILayoutRoot),
typeof(WinUILayoutHost),
new PropertyMetadata(null, OnRootChanged));
private static void OnRootChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is WinUILayoutHost host)
{
host.Refresh();
}
}
///
/// Создаёт новый экземпляр .
///
public WinUILayoutHost()
{
LayoutLayer = new Grid();
OverlayLayer = new DockOverlayHost();
var rootGrid = new Grid();
rootGrid.Children.Add(LayoutLayer);
rootGrid.Children.Add(OverlayLayer);
Content = rootGrid;
_factory = new WinUIVisualFactory();
_renderer = new LayoutRenderer(_factory);
}
///
/// Выполняет полную перерисовку визуального дерева.
///
public void Refresh()
{
LayoutLayer.Children.Clear();
if (Root?.Child is null)
return;
var visual = _renderer.Build(Root.Child);
visual.Attach();
switch (visual)
{
case WinUISplitVisual splitVisual:
LayoutLayer.Children.Add(splitVisual.Control);
break;
case WinUIGroupVisual groupVisual:
LayoutLayer.Children.Add(groupVisual.Control);
break;
case WinUIItemVisual itemVisual:
LayoutLayer.Children.Add(itemVisual.Control);
break;
}
}
///
/// Показывает подсветку зоны докинга для указанной цели.
///
public void ShowDockOverlay(DockTarget target)
{
if (target.Visual is not IWinUIVisual winuiVisual)
return;
var control = winuiVisual.Control;
var bounds = control.TransformToVisual(LayoutLayer)
.TransformBounds(new Windows.Foundation.Rect(0, 0, control.ActualWidth, control.ActualHeight));
OverlayLayer.ShowOverlay(target, bounds);
}
///
/// Скрывает подсветку зон докинга.
///
public void HideDockOverlay()
{
OverlayLayer.HideOverlay();
}
}