using Lattice.UI.DragDrop.WinUI.Controls;
using Lattice.UI.DragDrop.WinUI.Extensions;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
namespace Lattice.UI.DragDrop.WinUI.Services;
///
/// Сервис для настройки перетаскивания с поддержкой различных сценариев.
///
public class DragDropConfigurationService
{
private readonly Dictionary _configurations = new();
private readonly DragDropOverlay _overlay;
///
/// Инициализирует новый экземпляр класса .
///
public DragDropConfigurationService()
{
_overlay = new DragDropOverlay();
}
///
/// Настройка элемента как источника перетаскивания.
///
public void ConfigureAsDragSource(UIElement element, DragSourceConfiguration config)
{
element.MakeDragSource(config.Data);
if (config.AllowedEffects.HasValue)
{
element.SetAllowedEffects(config.AllowedEffects.Value);
}
if (config.VisualOffset.HasValue)
{
element.SetDragVisualOffset(config.VisualOffset.Value.X, config.VisualOffset.Value.Y);
}
_configurations[element] = new Configuration { DragSourceConfig = config };
}
///
/// Настройка элемента как цели сброса.
///
public void ConfigureAsDropTarget(UIElement element, DropTargetConfiguration config)
{
element.MakeDropTarget(
config.AcceptedTypes,
config.Handler,
config.ShowVisualFeedback,
config.FeedbackStyle);
if (!_configurations.ContainsKey(element))
{
_configurations[element] = new Configuration();
}
_configurations[element].DropTargetConfig = config;
}
///
/// Настройка элемента для переупорядочивания в контейнере.
///
public void ConfigureForReorder(UIElement element, Panel container, ReorderConfiguration config)
{
ConfigureAsDragSource(element, new DragSourceConfiguration
{
Data = element,
AllowedEffects = Core.DragDrop.Enums.DragDropEffects.Move,
VisualOffset = new Windows.Foundation.Point(-20, -20)
});
ConfigureAsDropTarget(container, new DropTargetConfiguration
{
AcceptedTypes = new[] { typeof(UIElement) },
ShowVisualFeedback = config.ShowVisualFeedback,
FeedbackStyle = config.FeedbackStyle
});
// Настраиваем логику переупорядочивания
container.Drop += (sender, e) => HandleReorderDrop(sender as Panel, element, e);
}
///
/// Подключает оверлей к указанному контейнеру.
///
public void AttachOverlayTo(Panel container)
{
if (container.Children.Contains(_overlay))
return;
container.Children.Add(_overlay);
}
///
/// Отключает все настройки перетаскивания для элемента.
///
public void DisableDragDrop(UIElement element)
{
element.RemoveDragSource();
element.RemoveDropTarget();
_configurations.Remove(element);
}
///
/// Очищает все настройки.
///
public void Clear()
{
foreach (var element in _configurations.Keys)
{
element.RemoveDragSource();
element.RemoveDropTarget();
}
_configurations.Clear();
}
private void HandleReorderDrop(Panel? container, UIElement draggedElement, Microsoft.UI.Xaml.DragEventArgs e)
{
if (container == null) return;
var position = e.GetPosition(container);
int insertIndex = CalculateInsertIndex(container, position);
if (insertIndex >= 0 && insertIndex < container.Children.Count)
{
container.Children.Remove(draggedElement);
container.Children.Insert(insertIndex, draggedElement);
}
}
private int CalculateInsertIndex(Panel container, Windows.Foundation.Point position)
{
for (int i = 0; i < container.Children.Count; i++)
{
var child = container.Children[i];
if (child is FrameworkElement element)
{
var childBounds = new Windows.Foundation.Rect(
Canvas.GetLeft(element),
Canvas.GetTop(element),
element.ActualWidth,
element.ActualHeight);
if (position.Y < childBounds.Y + childBounds.Height / 2)
{
return i;
}
}
}
return container.Children.Count;
}
private class Configuration
{
public DragSourceConfiguration? DragSourceConfig { get; set; }
public DropTargetConfiguration? DropTargetConfig { get; set; }
}
}
///
/// Конфигурация источника перетаскивания.
///
public class DragSourceConfiguration
{
///
/// Данные для перетаскивания.
///
public required object Data { get; set; }
///
/// Разрешенные эффекты.
///
public Core.DragDrop.Enums.DragDropEffects? AllowedEffects { get; set; }
///
/// Смещение визуального элемента.
///
public Windows.Foundation.Point? VisualOffset { get; set; }
///
/// Пользовательский обработчик.
///
public Action? OnDragStarted { get; set; }
///
/// Пользовательский обработчик завершения.
///
public Action? OnDragCompleted { get; set; }
}
///
/// Конфигурация цели сброса.
///
public class DropTargetConfiguration
{
///
/// Принимаемые типы данных.
///
public Type[]? AcceptedTypes { get; set; }
///
/// Обработчик сброса.
///
public Core.DragDrop.Abstractions.IDropTarget? Handler { get; set; }
///
/// Показывать визуальную обратную связь.
///
public bool ShowVisualFeedback { get; set; } = true;
///
/// Стиль визуальной обратной связи.
///
public Style? FeedbackStyle { get; set; }
///
/// Пользовательский обработчик валидации.
///
public Func