132 lines
4.1 KiB
C#
132 lines
4.1 KiB
C#
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;
|
||
|
||
/// <summary>
|
||
/// Сервис интеграции Drag & Drop с WinUI приложением.
|
||
/// </summary>
|
||
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;
|
||
|
||
/// <summary>
|
||
/// Инициализирует новый экземпляр класса <see cref="WinUIDragDropIntegrationService"/>.
|
||
/// </summary>
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Встраивает оверлей в указанный контейнер.
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc/>
|
||
public void Dispose()
|
||
{
|
||
if (!_disposed)
|
||
{
|
||
UnsubscribeFromEvents();
|
||
CleanupDragVisual();
|
||
|
||
if (_overlayCanvas.Parent is Panel parent)
|
||
{
|
||
parent.Children.Remove(_overlayCanvas);
|
||
}
|
||
|
||
_disposed = true;
|
||
}
|
||
|
||
GC.SuppressFinalize(this);
|
||
}
|
||
} |