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? CustomValidation { get; set; } /// /// Пользовательский обработчик сброса. /// public Action? OnDrop { get; set; } } /// /// Конфигурация переупорядочивания. /// public class ReorderConfiguration { /// /// Показывать визуальную обратную связь. /// public bool ShowVisualFeedback { get; set; } = true; /// /// Стиль визуальной обратной связи. /// public Style? FeedbackStyle { get; set; } /// /// Включать анимацию при переупорядочивании. /// public bool EnableAnimation { get; set; } = true; /// /// Порог для начала перетаскивания (в пикселях). /// public double DragThreshold { get; set; } = 5.0; }