Files
Lattice/Lattice.Core.Docking/Engine/DockOperations.cs
2026-01-18 16:33:35 +03:00

89 lines
3.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Lattice.Core.Docking.Abstractions;
using Lattice.Core.Docking.Models;
namespace Lattice.Core.Docking.Engine;
/// <summary>
/// Статический движок для манипуляции иерархией дерева компоновки.
/// Содержит чистые алгоритмы трансформации графа.
/// </summary>
public static class DockOperations
{
/// <summary>
/// Извлекает элемент из дерева. Если родительская группа остается с одним ребенком,
/// она удаляется, а ребенок занимает её место.
/// </summary>
/// <param name="element">Элемент для удаления.</param>
/// <param name="root">Текущий корень дерева.</param>
/// <returns>Новый корень дерева после оптимизации.</returns>
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;
}
/// <summary>
/// Вставляет элемент в дерево, создавая новую группу разделения или объединяя контент.
/// </summary>
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<IDockContent>(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; // Новая группа стала корнем
}
}