DragAndDrop core
This commit is contained in:
89
Lattice.Core.Docking/Engine/DockOperations.cs
Normal file
89
Lattice.Core.Docking/Engine/DockOperations.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
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; // Новая группа стала корнем
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user