100 lines
4.1 KiB
C#
100 lines
4.1 KiB
C#
using Lattice.Core.Models;
|
||
using Lattice.Core.Models.Enums;
|
||
using Microsoft.UI.Xaml;
|
||
using Microsoft.UI.Xaml.Controls;
|
||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||
using Microsoft.UI.Xaml.Media;
|
||
|
||
namespace Lattice.UI.Controls;
|
||
|
||
/// <summary>
|
||
/// Разделитель между панелями Lattice, позволяющий динамически изменять их размеры.
|
||
/// </summary>
|
||
[TemplatePart(Name = "PART_Thumb", Type = typeof(Thumb))]
|
||
public class LatticeSplitter : Control
|
||
{
|
||
private Thumb? _thumb;
|
||
|
||
/// <summary>
|
||
/// Узел макета, находящийся слева или сверху от разделителя.
|
||
/// </summary>
|
||
public LayoutNode? LeftNode { get; set; }
|
||
|
||
/// <summary>
|
||
/// Узел макета, находящийся справа или снизу от разделителя.
|
||
/// </summary>
|
||
public LayoutNode? RightNode { get; set; }
|
||
|
||
/// <summary>
|
||
/// Ориентация разделителя, определяющая направление изменения размера.
|
||
/// </summary>
|
||
public SplitOrientation Orientation { get; set; }
|
||
|
||
public LatticeSplitter()
|
||
{
|
||
this.DefaultStyleKey = typeof(LatticeSplitter);
|
||
}
|
||
|
||
protected override void OnApplyTemplate()
|
||
{
|
||
base.OnApplyTemplate();
|
||
|
||
if (_thumb != null) _thumb.DragDelta -= OnThumbDragDelta;
|
||
_thumb = GetTemplateChild("PART_Thumb") as Thumb;
|
||
if (_thumb != null) _thumb.DragDelta += OnThumbDragDelta;
|
||
}
|
||
|
||
private void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
|
||
{
|
||
if (LeftNode == null || RightNode == null) return;
|
||
|
||
// В WinUI 3 (2026) для изменения пропорций Star-размеров
|
||
// мы корректируем WidthValue/HeightValue и уведомляем менеджер.
|
||
|
||
double sensitivity = 0.01; // Коэффициент чувствительности для плавности
|
||
|
||
if (Orientation == SplitOrientation.Horizontal)
|
||
{
|
||
double delta = e.HorizontalChange * sensitivity;
|
||
LeftNode.WidthValue += delta;
|
||
RightNode.WidthValue -= delta;
|
||
|
||
// Ограничения минимального размера (10% от доступного пространства)
|
||
if (LeftNode.WidthValue < 0.1) { RightNode.WidthValue += (LeftNode.WidthValue - 0.1); LeftNode.WidthValue = 0.1; }
|
||
if (RightNode.WidthValue < 0.1) { LeftNode.WidthValue += (RightNode.WidthValue - 0.1); RightNode.WidthValue = 0.1; }
|
||
}
|
||
else // Vertical
|
||
{
|
||
double delta = e.VerticalChange * sensitivity;
|
||
LeftNode.HeightValue += delta;
|
||
RightNode.HeightValue -= delta;
|
||
|
||
if (LeftNode.HeightValue < 0.1) { RightNode.HeightValue += (LeftNode.HeightValue - 0.1); LeftNode.HeightValue = 0.1; }
|
||
if (RightNode.HeightValue < 0.1) { LeftNode.HeightValue += (RightNode.HeightValue - 0.1); RightNode.HeightValue = 0.1; }
|
||
}
|
||
|
||
// Уведомляем систему об изменении макета через родительский хост
|
||
NotifyLayoutUpdated();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Находит хост и вызывает обновление визуального дерева.
|
||
/// </summary>
|
||
private void NotifyLayoutUpdated()
|
||
{
|
||
DependencyObject parent = VisualTreeHelper.GetParent(this);
|
||
while (parent != null)
|
||
{
|
||
if (parent is LatticeDockHost host)
|
||
{
|
||
// Вызываем метод перерисовки (в Core это может быть событие LayoutUpdated)
|
||
// В нашем случае это заставит LayoutPanel пересчитать Column/Row Definitions
|
||
host.Manager?.Dock(null!, null!, DockDirection.Center); // Фиктивный вызов для обновления
|
||
// Или если есть прямой доступ: host.Manager.InvokeLayoutUpdated();
|
||
break;
|
||
}
|
||
parent = VisualTreeHelper.GetParent(parent);
|
||
}
|
||
}
|
||
}
|