DragAndDrop core
This commit is contained in:
78
Lattice.Layout.UI.WinUI/Docking/DockZoneHitTester.cs
Normal file
78
Lattice.Layout.UI.WinUI/Docking/DockZoneHitTester.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using Lattice.Layout.UI.Docking;
|
||||
using Lattice.Layout.UI.WinUI.Controls;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace Lattice.Layout.UI.WinUI.Docking;
|
||||
|
||||
/// <summary>
|
||||
/// Выполняет hit-test для определения зоны докинга в WinUI.
|
||||
/// </summary>
|
||||
public static class DockZoneHitTester
|
||||
{
|
||||
/// <summary>
|
||||
/// Выполняет hit-test по экранной точке и возвращает цель докинга.
|
||||
/// </summary>
|
||||
/// <param name="host">WinUI-хост раскладки.</param>
|
||||
/// <param name="screenPoint">Точка в координатах окна.</param>
|
||||
public static DockTarget? HitTest(WinUILayoutHost host, Point screenPoint)
|
||||
{
|
||||
if (host is null)
|
||||
throw new ArgumentNullException(nameof(host));
|
||||
|
||||
// Предполагаем, что LayoutLayer — основной слой, в котором живёт визуальное дерево.
|
||||
var layoutLayer = host.LayoutLayer;
|
||||
if (layoutLayer is null)
|
||||
return null;
|
||||
|
||||
// Переводим координаты в систему координат layoutLayer.
|
||||
var elements = VisualTreeHelper.FindElementsInHostCoordinates(screenPoint, host.LayoutLayer);
|
||||
|
||||
var firstElement = elements.FirstOrDefault();
|
||||
|
||||
if (firstElement is null)
|
||||
return null;
|
||||
|
||||
// Ищем ближайший IWinUIVisual.
|
||||
var visual = FindVisual(firstElement);
|
||||
if (visual is null)
|
||||
return null;
|
||||
|
||||
if (visual is not ILayoutVisual layoutVisual)
|
||||
return null;
|
||||
|
||||
// Вычисляем зону докинга для найденного контрола.
|
||||
var control = visual.Control;
|
||||
|
||||
var bounds = control.TransformToVisual(layoutLayer)
|
||||
.TransformBounds(new Rect(0, 0, control.ActualWidth, control.ActualHeight));
|
||||
|
||||
var localX = screenPoint.X - bounds.X;
|
||||
var localY = screenPoint.Y - bounds.Y;
|
||||
|
||||
var zone = DockingUtils.GetZone(localX, localY, bounds.Width, bounds.Height);
|
||||
|
||||
return new DockTarget(layoutVisual, zone);
|
||||
}
|
||||
|
||||
private static IWinUIVisual? FindVisual(UIElement element)
|
||||
{
|
||||
DependencyObject? current = element;
|
||||
|
||||
while (current is not null)
|
||||
{
|
||||
if (current is FrameworkElement fe && fe.DataContext is IWinUIVisual ctxVisual)
|
||||
return ctxVisual;
|
||||
|
||||
if (current is IWinUIVisual winuiVisual)
|
||||
return winuiVisual;
|
||||
|
||||
current = VisualTreeHelper.GetParent(current);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user