122 lines
3.9 KiB
C#
122 lines
3.9 KiB
C#
using Lattice.Core.Models;
|
|
using Lattice.Core.Models.Enums;
|
|
using Lattice.UI.Controls;
|
|
using Microsoft.UI.Xaml;
|
|
using Microsoft.UI.Xaml.Controls;
|
|
|
|
namespace Lattice.UI.Primitives;
|
|
|
|
/// <summary>
|
|
/// Кастомный контейнер, преобразующий иерархию узлов Lattice в визуальные элементы WinUI 3.
|
|
/// </summary>
|
|
public class LayoutPanel : Grid
|
|
{
|
|
private readonly LatticeDockHost _host;
|
|
|
|
/// <summary>
|
|
/// Создает новый экземпляр панели компоновки.
|
|
/// </summary>
|
|
/// <param name="host">Корневой хост, управляющий макетом.</param>
|
|
public LayoutPanel(LatticeDockHost host)
|
|
{
|
|
_host = host;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Выполняет рекурсивную отрисовку дерева узлов.
|
|
/// </summary>
|
|
public void Build(LayoutNode node)
|
|
{
|
|
this.Children.Clear();
|
|
this.ColumnDefinitions.Clear();
|
|
this.RowDefinitions.Clear();
|
|
|
|
if (node is SplitContainerNode splitContainer)
|
|
{
|
|
RenderSplit(splitContainer);
|
|
}
|
|
else if (node is ContentNode contentNode)
|
|
{
|
|
RenderContent(contentNode);
|
|
}
|
|
}
|
|
|
|
private void RenderSplit(SplitContainerNode container)
|
|
{
|
|
for (int i = 0; i < container.Children.Count; i++)
|
|
{
|
|
var child = container.Children[i];
|
|
var childPresenter = new LayoutPanel(_host);
|
|
|
|
if (container.Orientation == SplitOrientation.Horizontal)
|
|
{
|
|
this.ColumnDefinitions.Add(new ColumnDefinition
|
|
{
|
|
Width = child.IsWidthStar ? new GridLength(child.WidthValue, GridUnitType.Star) : new GridLength(child.WidthValue)
|
|
});
|
|
Grid.SetColumn(childPresenter, this.ColumnDefinitions.Count - 1);
|
|
}
|
|
else
|
|
{
|
|
this.RowDefinitions.Add(new RowDefinition
|
|
{
|
|
Height = child.IsHeightStar ? new GridLength(child.HeightValue, GridUnitType.Star) : new GridLength(child.HeightValue)
|
|
});
|
|
Grid.SetRow(childPresenter, this.RowDefinitions.Count - 1);
|
|
}
|
|
|
|
this.Children.Add(childPresenter);
|
|
childPresenter.Build(child);
|
|
|
|
// Добавляем сплиттер между элементами (кроме последнего)
|
|
if (i < container.Children.Count - 1)
|
|
{
|
|
AddSplitter(container, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void AddSplitter(SplitContainerNode container, int index)
|
|
{
|
|
var splitter = new LatticeSplitter
|
|
{
|
|
LeftNode = container.Children[index],
|
|
RightNode = container.Children[index + 1],
|
|
Orientation = container.Orientation,
|
|
};
|
|
|
|
double thickness = (double)Application.Current.Resources["LatticeSplitterThickness"];
|
|
|
|
if (container.Orientation == SplitOrientation.Horizontal)
|
|
{
|
|
// Сплиттер занимает очень узкую колонку между основными
|
|
this.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(thickness) });
|
|
Grid.SetColumn(splitter, this.ColumnDefinitions.Count - 1);
|
|
}
|
|
else
|
|
{
|
|
this.RowDefinitions.Add(new RowDefinition { Height = new GridLength(thickness) });
|
|
Grid.SetRow(splitter, this.RowDefinitions.Count - 1);
|
|
}
|
|
|
|
this.Children.Add(splitter);
|
|
}
|
|
|
|
private void RenderContent(ContentNode node)
|
|
{
|
|
var pane = new LatticePane
|
|
{
|
|
Title = node.Name,
|
|
Content = node.Component,
|
|
DataContext = node,
|
|
};
|
|
|
|
pane.CloseClick += (s, e) =>
|
|
{
|
|
_host.Service?.Remove(node);
|
|
};
|
|
|
|
this.Children.Add(pane);
|
|
}
|
|
}
|