using Lattice.Core.Docking.Abstractions; using Lattice.Core.Docking.Models; namespace Lattice.Core.Docking.Engine; /// /// Статический движок для манипуляции иерархией дерева компоновки. /// Содержит чистые алгоритмы трансформации графа. /// public static class DockOperations { /// /// Извлекает элемент из дерева. Если родительская группа остается с одним ребенком, /// она удаляется, а ребенок занимает её место. /// /// Элемент для удаления. /// Текущий корень дерева. /// Новый корень дерева после оптимизации. public static IDockElement? Remove(IDockElement element, IDockElement root) { if (element == root) return null; var parent = element.Parent as DockGroup; if (parent == null) return root; // Определяем "выжившего" соседа var sibling = (parent.First == element) ? parent.Second : parent.First; var grandParent = parent.Parent as DockGroup; if (grandParent != null) { // Переподключаем соседа напрямую к дедушке if (grandParent.First == parent) grandParent.First = sibling; else grandParent.Second = sibling; sibling.Parent = grandParent; return root; } // Если дедушки нет, сосед становится новым корнем sibling.Parent = null; return sibling; } /// /// Вставляет элемент в дерево, создавая новую группу разделения или объединяя контент. /// public static IDockElement Insert(IDockElement target, IDockElement source, DockPosition pos, IDockElement root) { // Случай 1: Объединение вкладок в центре if (pos == DockPosition.Center) { if (target is IDockContainer targetContainer && source is IDockContainer sourceContainer) { var items = new List(sourceContainer.Children); foreach (var item in items) { sourceContainer.RemoveContent(item); targetContainer.AddContent(item); } } return root; } // Случай 2: Разделение (Split) var direction = (pos == DockPosition.Left || pos == DockPosition.Right) ? SplitDirection.Horizontal : SplitDirection.Vertical; bool sourceIsFirst = (pos == DockPosition.Left || pos == DockPosition.Top); var oldParent = target.Parent; // Создаем новую группу. Источник и цель делят пространство 50/50 var newGroup = sourceIsFirst ? new DockGroup(source, target, direction) { SplitRatio = 0.5 } : new DockGroup(target, source, direction) { SplitRatio = 0.5 }; if (oldParent is DockGroup gp) { if (gp.First == target) gp.First = newGroup; else gp.Second = newGroup; newGroup.Parent = gp; return root; } newGroup.Parent = null; return newGroup; // Новая группа стала корнем } }