using Lattice.Core.DragDrop.Services;
using Lattice.UI.DragDrop.Abstractions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
namespace Lattice.UI.DragDrop.WinUI.Services;
///
/// Сервис интеграции Drag & Drop с WinUI приложением.
///
public class WinUIDragDropIntegrationService : IDisposable
{
private readonly IDragDropService _dragDropService;
private readonly IDragVisualProvider _dragVisualProvider;
private readonly Canvas _overlayCanvas;
private readonly Window _window;
private object? _currentDragVisual;
private bool _disposed;
///
/// Инициализирует новый экземпляр класса .
///
public WinUIDragDropIntegrationService(
Window window,
IDragDropService dragDropService,
IDragVisualProvider dragVisualProvider)
{
_window = window ?? throw new ArgumentNullException(nameof(window));
_dragDropService = dragDropService ?? throw new ArgumentNullException(nameof(dragDropService));
_dragVisualProvider = dragVisualProvider ?? throw new ArgumentNullException(nameof(dragVisualProvider));
// Создаем оверлейный Canvas для визуальных элементов
_overlayCanvas = new Canvas
{
IsHitTestVisible = false,
Background = null
};
// Подписываемся на события перетаскивания
SubscribeToEvents();
}
///
/// Встраивает оверлей в указанный контейнер.
///
public void AttachToContainer(Panel container)
{
if (container == null)
throw new ArgumentNullException(nameof(container));
// Убеждаемся, что оверлей находится поверх всех элементов
Canvas.SetZIndex(_overlayCanvas, int.MaxValue);
container.Children.Add(_overlayCanvas);
}
private void SubscribeToEvents()
{
_dragDropService.DragStarted += OnDragStarted;
_dragDropService.DragUpdated += OnDragUpdated;
_dragDropService.DragCompleted += OnDragCompleted;
_dragDropService.DragCancelled += OnDragCancelled;
}
private void UnsubscribeFromEvents()
{
_dragDropService.DragStarted -= OnDragStarted;
_dragDropService.DragUpdated -= OnDragUpdated;
_dragDropService.DragCompleted -= OnDragCompleted;
_dragDropService.DragCancelled -= OnDragCancelled;
}
private void OnDragStarted(object? sender, DragStartedEventArgs e)
{
// Создаем визуальное представление
_currentDragVisual = _dragVisualProvider.CreateDragVisual(
e.DragInfo,
e.StartPosition);
// Добавляем на оверлей
if (_currentDragVisual is UIElement element)
{
_overlayCanvas.Children.Add(element);
}
}
private void OnDragUpdated(object? sender, DragUpdatedEventArgs e)
{
if (_currentDragVisual != null)
{
_dragVisualProvider.UpdateDragVisualPosition(_currentDragVisual, e.Position);
}
}
private void OnDragCompleted(object? sender, DragCompletedEventArgs e)
{
CleanupDragVisual();
}
private void OnDragCancelled(object? sender, DragCancelledEventArgs e)
{
CleanupDragVisual();
}
private void CleanupDragVisual()
{
if (_currentDragVisual != null)
{
_dragVisualProvider.ReleaseDragVisual(_currentDragVisual);
_currentDragVisual = null;
}
}
///
public void Dispose()
{
if (!_disposed)
{
UnsubscribeFromEvents();
CleanupDragVisual();
if (_overlayCanvas.Parent is Panel parent)
{
parent.Children.Remove(_overlayCanvas);
}
_disposed = true;
}
GC.SuppressFinalize(this);
}
}