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