135 lines
4.2 KiB
C#
135 lines
4.2 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// WinUI-контрол, отображающий дерево раскладки.
|
|
/// Оборачивает LayoutRenderer и размещает визуальное дерево внутри себя.
|
|
/// </summary>
|
|
public sealed class WinUILayoutHost : UserControl, ILayoutView
|
|
{
|
|
/// <summary>
|
|
/// Слой, в котором размещается визуальное дерево раскладки.
|
|
/// </summary>
|
|
public Grid LayoutLayer { get; }
|
|
|
|
/// <summary>
|
|
/// Слой для отображения подсветки зон докинга.
|
|
/// </summary>
|
|
public DockOverlayHost OverlayLayer { get; }
|
|
|
|
private readonly LayoutRenderer _renderer;
|
|
private readonly WinUIVisualFactory _factory;
|
|
|
|
/// <summary>
|
|
/// Функция, возвращающая UI-содержимое по ContentId.
|
|
/// Используется визуальными элементами для подстановки реального контрола.
|
|
/// </summary>
|
|
public Func<string, UIElement>? ContentResolver { get; set; }
|
|
|
|
/// <summary>
|
|
/// Корневой элемент раскладки, который необходимо отобразить.
|
|
/// </summary>
|
|
public ILayoutRoot? Root
|
|
{
|
|
get => (ILayoutRoot?)GetValue(RootProperty);
|
|
set => SetValue(RootProperty, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Свойство зависимости для <see cref="Root"/>.
|
|
/// </summary>
|
|
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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Создаёт новый экземпляр <see cref="WinUILayoutHost"/>.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Выполняет полную перерисовку визуального дерева.
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Показывает подсветку зоны докинга для указанной цели.
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Скрывает подсветку зон докинга.
|
|
/// </summary>
|
|
public void HideDockOverlay()
|
|
{
|
|
OverlayLayer.HideOverlay();
|
|
}
|
|
}
|