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; /// /// Кастомный контейнер, преобразующий иерархию узлов Lattice в визуальные элементы WinUI 3. /// public class LayoutPanel : Grid { private readonly LatticeDockHost _host; /// /// Создает новый экземпляр панели компоновки. /// /// Корневой хост, управляющий макетом. public LayoutPanel(LatticeDockHost host) { _host = host; } /// /// Выполняет рекурсивную отрисовку дерева узлов. /// 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); } }