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; // Новая группа стала корнем
}
}