DragAndDrop core
This commit is contained in:
41
Lattice.UI.DragDrop/Abstractions/IDragDropHost.cs
Normal file
41
Lattice.UI.DragDrop/Abstractions/IDragDropHost.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Lattice.Core.Geometry;
|
||||
|
||||
namespace Lattice.UI.DragDrop.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// Хост для отображения визуальных элементов перетаскивания.
|
||||
/// </summary>
|
||||
public interface IDragDropHost
|
||||
{
|
||||
/// <summary>
|
||||
/// Показывает визуальное представление перетаскивания.
|
||||
/// </summary>
|
||||
/// <param name="dragVisual">Визуальное представление.</param>
|
||||
/// <param name="position">Начальная позиция.</param>
|
||||
void ShowDragVisual(object dragVisual, Point position);
|
||||
|
||||
/// <summary>
|
||||
/// Обновляет позицию визуального представления перетаскивания.
|
||||
/// </summary>
|
||||
/// <param name="dragVisual">Визуальное представление.</param>
|
||||
/// <param name="position">Новая позиция.</param>
|
||||
void UpdateDragVisualPosition(object dragVisual, Point position);
|
||||
|
||||
/// <summary>
|
||||
/// Скрывает визуальное представление перетаскивания.
|
||||
/// </summary>
|
||||
/// <param name="dragVisual">Визуальное представление.</param>
|
||||
void HideDragVisual(object dragVisual);
|
||||
|
||||
/// <summary>
|
||||
/// Показывает визуальную обратную связь для цели сброса.
|
||||
/// </summary>
|
||||
/// <param name="adorner">Элемент обратной связи.</param>
|
||||
void ShowDropAdorner(IDropVisualAdorner adorner);
|
||||
|
||||
/// <summary>
|
||||
/// Скрывает визуальную обратную связь для цели сброса.
|
||||
/// </summary>
|
||||
/// <param name="adorner">Элемент обратной связи.</param>
|
||||
void HideDropAdorner(IDropVisualAdorner adorner);
|
||||
}
|
||||
31
Lattice.UI.DragDrop/Abstractions/IDragVisualProvider.cs
Normal file
31
Lattice.UI.DragDrop/Abstractions/IDragVisualProvider.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Lattice.Core.DragDrop.Models;
|
||||
using Lattice.Core.Geometry;
|
||||
|
||||
namespace Lattice.UI.DragDrop.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// Поставщик визуального представления для перетаскиваемого элемента.
|
||||
/// </summary>
|
||||
public interface IDragVisualProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Создает визуальное представление для перетаскивания.
|
||||
/// </summary>
|
||||
/// <param name="dragInfo">Информация о перетаскивании.</param>
|
||||
/// <param name="initialPosition">Начальная позиция в экранных координатах.</param>
|
||||
/// <returns>Объект, представляющий визуальное отображение.</returns>
|
||||
object CreateDragVisual(DragInfo dragInfo, Point initialPosition);
|
||||
|
||||
/// <summary>
|
||||
/// Обновляет позицию визуального представления.
|
||||
/// </summary>
|
||||
/// <param name="dragVisual">Визуальное представление.</param>
|
||||
/// <param name="position">Новая позиция.</param>
|
||||
void UpdateDragVisualPosition(object dragVisual, Point position);
|
||||
|
||||
/// <summary>
|
||||
/// Освобождает ресурсы визуального представления.
|
||||
/// </summary>
|
||||
/// <param name="dragVisual">Визуальное представление.</param>
|
||||
void ReleaseDragVisual(object dragVisual);
|
||||
}
|
||||
28
Lattice.UI.DragDrop/Abstractions/IDropVisualAdorner.cs
Normal file
28
Lattice.UI.DragDrop/Abstractions/IDropVisualAdorner.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Lattice.Core.DragDrop.Models;
|
||||
using Lattice.Core.Geometry;
|
||||
|
||||
namespace Lattice.UI.DragDrop.Abstractions;
|
||||
|
||||
/// <summary>
|
||||
/// Визуальный элемент, показывающий обратную связь при наведении на цель сброса.
|
||||
/// </summary>
|
||||
public interface IDropVisualAdorner
|
||||
{
|
||||
/// <summary>
|
||||
/// Показывает визуальную обратную связь для цели сброса.
|
||||
/// </summary>
|
||||
/// <param name="dropInfo">Информация о сбросе.</param>
|
||||
/// <param name="targetBounds">Границы цели.</param>
|
||||
void Show(DropInfo dropInfo, Rect targetBounds);
|
||||
|
||||
/// <summary>
|
||||
/// Обновляет позицию и состояние визуальной обратной связи.
|
||||
/// </summary>
|
||||
/// <param name="dropInfo">Информация о сбросе.</param>
|
||||
void Update(DropInfo dropInfo);
|
||||
|
||||
/// <summary>
|
||||
/// Скрывает визуальную обратную связь.
|
||||
/// </summary>
|
||||
void Hide();
|
||||
}
|
||||
256
Lattice.UI.DragDrop/Behaviors/DragSourceBehaviorBase.cs
Normal file
256
Lattice.UI.DragDrop/Behaviors/DragSourceBehaviorBase.cs
Normal file
@@ -0,0 +1,256 @@
|
||||
using Lattice.Core.DragDrop.Abstractions;
|
||||
using Lattice.Core.DragDrop.Models;
|
||||
using Lattice.Core.DragDrop.Services;
|
||||
using Lattice.Core.Geometry;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace Lattice.UI.DragDrop.Behaviors;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый класс поведения источника перетаскивания.
|
||||
/// </summary>
|
||||
/// <typeparam name="TElement">Тип UI элемента.</typeparam>
|
||||
public abstract class DragSourceBehaviorBase<TElement> : IDragSource
|
||||
where TElement : class
|
||||
{
|
||||
private IDragDropService? _dragDropService;
|
||||
private Point _dragStartPosition;
|
||||
private bool _isDragging;
|
||||
private TElement? _associatedElement;
|
||||
|
||||
/// <summary>
|
||||
/// Получает или задает связанный элемент.
|
||||
/// </summary>
|
||||
protected TElement? AssociatedElement
|
||||
{
|
||||
get => _associatedElement;
|
||||
set
|
||||
{
|
||||
if (_associatedElement != value)
|
||||
{
|
||||
DetachFromElement();
|
||||
_associatedElement = value;
|
||||
AttachToElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает сервис перетаскивания.
|
||||
/// </summary>
|
||||
protected IDragDropService DragDropService
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dragDropService == null)
|
||||
{
|
||||
_dragDropService = ServiceProvider.GetRequiredService<IDragDropService>();
|
||||
}
|
||||
return _dragDropService;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает провайдер сервисов.
|
||||
/// </summary>
|
||||
protected IServiceProvider ServiceProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Инициализирует новый экземпляр класса <see cref="DragSourceBehaviorBase{TElement}"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">Провайдер сервисов.</param>
|
||||
protected DragSourceBehaviorBase(IServiceProvider serviceProvider)
|
||||
{
|
||||
ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается при прикреплении к элементу.
|
||||
/// </summary>
|
||||
protected virtual void AttachToElement()
|
||||
{
|
||||
if (_associatedElement != null)
|
||||
{
|
||||
SubscribeToEvents(_associatedElement);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается при откреплении от элемента.
|
||||
/// </summary>
|
||||
protected virtual void DetachFromElement()
|
||||
{
|
||||
if (_associatedElement != null)
|
||||
{
|
||||
UnsubscribeFromEvents(_associatedElement);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Подписывается на события элемента.
|
||||
/// </summary>
|
||||
/// <param name="element">Элемент.</param>
|
||||
protected abstract void SubscribeToEvents(TElement element);
|
||||
|
||||
/// <summary>
|
||||
/// Отписывается от событий элемента.
|
||||
/// </summary>
|
||||
/// <param name="element">Элемент.</param>
|
||||
protected abstract void UnsubscribeFromEvents(TElement element);
|
||||
|
||||
/// <summary>
|
||||
/// Обрабатывает начало взаимодействия (например, нажатие мыши).
|
||||
/// </summary>
|
||||
/// <param name="position">Позиция в координатах элемента.</param>
|
||||
protected virtual void OnInteractionStarted(Point position)
|
||||
{
|
||||
if (_isDragging)
|
||||
return;
|
||||
|
||||
_dragStartPosition = position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обрабатывает перемещение во время взаимодействия.
|
||||
/// </summary>
|
||||
/// <param name="position">Позиция в координатах элемента.</param>
|
||||
protected virtual void OnInteractionMoved(Point position)
|
||||
{
|
||||
if (_isDragging)
|
||||
return;
|
||||
|
||||
var distance = CalculateDistance(_dragStartPosition, position);
|
||||
if (distance > DragDropService.DragStartThreshold)
|
||||
{
|
||||
StartDragOperation();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обрабатывает завершение взаимодействия.
|
||||
/// </summary>
|
||||
protected virtual void OnInteractionEnded()
|
||||
{
|
||||
// Сброс состояния, если перетаскивание не началось
|
||||
if (!_isDragging)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обрабатывает отмену взаимодействия.
|
||||
/// </summary>
|
||||
protected virtual void OnInteractionCancelled()
|
||||
{
|
||||
if (_isDragging)
|
||||
{
|
||||
DragDropService.CancelDrag();
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Начинает операцию перетаскивания.
|
||||
/// </summary>
|
||||
protected virtual void StartDragOperation()
|
||||
{
|
||||
if (_isDragging || AssociatedElement == null)
|
||||
return;
|
||||
|
||||
// Получаем начальную позицию в экранных координатах
|
||||
var screenPosition = ConvertToScreenCoordinates(_dragStartPosition);
|
||||
|
||||
// Начинаем перетаскивание
|
||||
_isDragging = DragDropService.StartDrag(this, screenPosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Преобразует координаты элемента в экранные координаты.
|
||||
/// </summary>
|
||||
/// <param name="point">Точка в координатах элемента.</param>
|
||||
/// <returns>Точка в экранных координатах.</returns>
|
||||
protected abstract Point ConvertToScreenCoordinates(Point point);
|
||||
|
||||
/// <summary>
|
||||
/// Вычисляет расстояние между двумя точками.
|
||||
/// </summary>
|
||||
protected virtual double CalculateDistance(Point p1, Point p2)
|
||||
{
|
||||
var dx = p2.X - p1.X;
|
||||
var dy = p2.Y - p1.Y;
|
||||
return Math.Sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Сбрасывает состояние поведения.
|
||||
/// </summary>
|
||||
protected virtual void Reset()
|
||||
{
|
||||
_isDragging = false;
|
||||
_dragStartPosition = default;
|
||||
}
|
||||
|
||||
#region IDragSource Implementation
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract bool CanStartDrag(out DragInfo? dragInfo);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual bool StartDrag(DragInfo dragInfo)
|
||||
{
|
||||
// Базовая реализация всегда разрешает начало перетаскивания
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void DragCompleted(DragInfo dragInfo, Core.DragDrop.Enums.DragDropEffects effects)
|
||||
{
|
||||
_isDragging = false;
|
||||
|
||||
// Оповещаем о завершении перетаскивания
|
||||
OnDragCompleted(dragInfo, effects);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void DragCancelled(DragInfo dragInfo)
|
||||
{
|
||||
_isDragging = false;
|
||||
|
||||
// Оповещаем об отмене перетаскивания
|
||||
OnDragCancelled(dragInfo);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Virtual Methods for Derived Classes
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается при успешном завершении перетаскивания.
|
||||
/// </summary>
|
||||
/// <param name="dragInfo">Информация о перетаскивании.</param>
|
||||
/// <param name="effects">Примененные эффекты.</param>
|
||||
protected virtual void OnDragCompleted(DragInfo dragInfo, Core.DragDrop.Enums.DragDropEffects effects)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается при отмене перетаскивания.
|
||||
/// </summary>
|
||||
/// <param name="dragInfo">Информация о перетаскивании.</param>
|
||||
protected virtual void OnDragCancelled(DragInfo dragInfo)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Освобождает ресурсы.
|
||||
/// </summary>
|
||||
public virtual void Detach()
|
||||
{
|
||||
DetachFromElement();
|
||||
_associatedElement = null;
|
||||
}
|
||||
}
|
||||
214
Lattice.UI.DragDrop/Behaviors/DropTargetBehaviorBase.cs
Normal file
214
Lattice.UI.DragDrop/Behaviors/DropTargetBehaviorBase.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using Lattice.Core.DragDrop.Abstractions;
|
||||
using Lattice.Core.DragDrop.Models;
|
||||
using Lattice.Core.DragDrop.Services;
|
||||
using Lattice.Core.Geometry;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
|
||||
namespace Lattice.UI.DragDrop.Behaviors;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый класс поведения цели сброса.
|
||||
/// </summary>
|
||||
/// <typeparam name="TElement">Тип UI элемента.</typeparam>
|
||||
public abstract class DropTargetBehaviorBase<TElement> : IDropTarget
|
||||
where TElement : class
|
||||
{
|
||||
private IDragDropService? _dragDropService;
|
||||
private string? _registrationId;
|
||||
private TElement? _associatedElement;
|
||||
private Rect _currentBounds;
|
||||
|
||||
/// <summary>
|
||||
/// Получает или задает связанный элемент.
|
||||
/// </summary>
|
||||
protected TElement? AssociatedElement
|
||||
{
|
||||
get => _associatedElement;
|
||||
set
|
||||
{
|
||||
if (_associatedElement != value)
|
||||
{
|
||||
UnregisterFromService();
|
||||
_associatedElement = value;
|
||||
RegisterToService();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает или задает приоритет цели сброса.
|
||||
/// </summary>
|
||||
public int Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Получает или задает группу цели сброса.
|
||||
/// </summary>
|
||||
public string? Group { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Получает сервис перетаскивания.
|
||||
/// </summary>
|
||||
protected IDragDropService DragDropService
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dragDropService == null)
|
||||
{
|
||||
_dragDropService = ServiceProvider.GetRequiredService<IDragDropService>();
|
||||
}
|
||||
return _dragDropService;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает провайдер сервисов.
|
||||
/// </summary>
|
||||
protected IServiceProvider ServiceProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Получает текущие границы элемента в экранных координатах.
|
||||
/// </summary>
|
||||
protected Rect CurrentBounds => _currentBounds;
|
||||
|
||||
/// <summary>
|
||||
/// Инициализирует новый экземпляр класса <see cref="DropTargetBehaviorBase{TElement}"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">Провайдер сервисов.</param>
|
||||
protected DropTargetBehaviorBase(IServiceProvider serviceProvider)
|
||||
{
|
||||
ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается при прикреплении к элементу.
|
||||
/// </summary>
|
||||
protected virtual void AttachToElement()
|
||||
{
|
||||
if (_associatedElement != null)
|
||||
{
|
||||
SubscribeToEvents(_associatedElement);
|
||||
UpdateBounds();
|
||||
RegisterToService();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается при откреплении от элемента.
|
||||
/// </summary>
|
||||
protected virtual void DetachFromElement()
|
||||
{
|
||||
if (_associatedElement != null)
|
||||
{
|
||||
UnsubscribeFromEvents(_associatedElement);
|
||||
UnregisterFromService();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Подписывается на события элемента.
|
||||
/// </summary>
|
||||
/// <param name="element">Элемент.</param>
|
||||
protected abstract void SubscribeToEvents(TElement element);
|
||||
|
||||
/// <summary>
|
||||
/// Отписывается от событий элемента.
|
||||
/// </summary>
|
||||
/// <param name="element">Элемент.</param>
|
||||
protected abstract void UnsubscribeFromEvents(TElement element);
|
||||
|
||||
/// <summary>
|
||||
/// Обновляет границы элемента в экранных координатах.
|
||||
/// </summary>
|
||||
protected virtual void UpdateBounds()
|
||||
{
|
||||
if (_associatedElement != null)
|
||||
{
|
||||
_currentBounds = GetScreenBounds(_associatedElement);
|
||||
|
||||
// Обновляем регистрацию в сервисе
|
||||
if (_registrationId != null)
|
||||
{
|
||||
DragDropService.UpdateDropTargetBounds(_registrationId, _currentBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получает границы элемента в экранных координатах.
|
||||
/// </summary>
|
||||
/// <param name="element">Элемент.</param>
|
||||
/// <returns>Границы в экранных координатах.</returns>
|
||||
protected abstract Rect GetScreenBounds(TElement element);
|
||||
|
||||
/// <summary>
|
||||
/// Регистрирует цель в сервисе перетаскивания.
|
||||
/// </summary>
|
||||
protected virtual void RegisterToService()
|
||||
{
|
||||
if (_associatedElement != null && _registrationId == null)
|
||||
{
|
||||
UpdateBounds();
|
||||
_registrationId = DragDropService.RegisterDropTarget(this, _currentBounds, Priority, Group);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отменяет регистрацию цели в сервисе перетаскивания.
|
||||
/// </summary>
|
||||
protected virtual void UnregisterFromService()
|
||||
{
|
||||
if (_registrationId != null)
|
||||
{
|
||||
DragDropService.UnregisterDropTarget(_registrationId);
|
||||
_registrationId = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Вызывается при изменении размера или позиции элемента.
|
||||
/// </summary>
|
||||
protected virtual void OnElementLayoutChanged()
|
||||
{
|
||||
UpdateBounds();
|
||||
}
|
||||
|
||||
#region IDropTarget Implementation
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract bool CanAcceptDrop(DropInfo dropInfo);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void DragOver(DropInfo dropInfo)
|
||||
{
|
||||
// Базовая реализация устанавливает эффект по умолчанию
|
||||
if (CanAcceptDrop(dropInfo))
|
||||
{
|
||||
dropInfo.SuggestedEffects = Core.DragDrop.Enums.DragDropEffects.Move;
|
||||
}
|
||||
else
|
||||
{
|
||||
dropInfo.SuggestedEffects = Core.DragDrop.Enums.DragDropEffects.None;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract void Drop(DropInfo dropInfo);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual void DragLeave()
|
||||
{
|
||||
// Базовая реализация не делает ничего
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Освобождает ресурсы.
|
||||
/// </summary>
|
||||
public virtual void Detach()
|
||||
{
|
||||
DetachFromElement();
|
||||
_associatedElement = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using Lattice.UI.DragDrop.Abstractions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Lattice.UI.DragDrop.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Методы расширения для регистрации сервисов перетаскивания.
|
||||
/// </summary>
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Добавляет сервисы перетаскивания.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddLatticeDragDrop(this IServiceCollection services)
|
||||
{
|
||||
// Регистрируем абстракции, которые будут реализованы в платформенных проектах
|
||||
services.AddSingleton(typeof(IDragVisualProvider), typeof(DefaultDragVisualProvider));
|
||||
services.AddSingleton(typeof(IDropVisualAdorner), typeof(DefaultDropVisualAdorner));
|
||||
services.AddSingleton(typeof(IDragDropHost), typeof(DefaultDragDropHost));
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Реализация по умолчанию для платформ, которые еще не имеют своей реализации.
|
||||
/// </summary>
|
||||
private class DefaultDragVisualProvider : IDragVisualProvider
|
||||
{
|
||||
public object CreateDragVisual(Core.DragDrop.Models.DragInfo dragInfo, Core.Geometry.Point initialPosition)
|
||||
=> new object();
|
||||
|
||||
public void UpdateDragVisualPosition(object dragVisual, Core.Geometry.Point position) { }
|
||||
|
||||
public void ReleaseDragVisual(object dragVisual) { }
|
||||
}
|
||||
|
||||
private class DefaultDropVisualAdorner : IDropVisualAdorner
|
||||
{
|
||||
public void Show(Core.DragDrop.Models.DropInfo dropInfo, Core.Geometry.Rect targetBounds) { }
|
||||
public void Update(Core.DragDrop.Models.DropInfo dropInfo) { }
|
||||
public void Hide() { }
|
||||
}
|
||||
|
||||
private class DefaultDragDropHost : IDragDropHost
|
||||
{
|
||||
public void ShowDragVisual(object dragVisual, Core.Geometry.Point position) { }
|
||||
public void UpdateDragVisualPosition(object dragVisual, Core.Geometry.Point position) { }
|
||||
public void HideDragVisual(object dragVisual) { }
|
||||
public void ShowDropAdorner(IDropVisualAdorner adorner) { }
|
||||
public void HideDropAdorner(IDropVisualAdorner adorner) { }
|
||||
}
|
||||
}
|
||||
20
Lattice.UI.DragDrop/Lattice.UI.DragDrop.csproj
Normal file
20
Lattice.UI.DragDrop/Lattice.UI.DragDrop.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Lattice.Core.DragDrop\Lattice.Core.DragDrop.csproj" />
|
||||
<ProjectReference Include="..\Lattice.Core.Geometry\Lattice.Core.Geometry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
136
Lattice.UI.DragDrop/README.md
Normal file
136
Lattice.UI.DragDrop/README.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# Lattice.UI.DragDrop
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Кроссплатформенные абстракции для системы перетаскивания в Lattice UI Framework.
|
||||
|
||||
## 📦 О проекте
|
||||
|
||||
`Lattice.UI.DragDrop` предоставляет платформонезависимые интерфейсы и базовые классы для реализации drag-and-drop функциональности.
|
||||
Этот проект служит основой для конкретных реализаций на различных платформах (WinUI, Uno Platform, MAUI и т.д.).
|
||||
|
||||
## 🎯 Особенности
|
||||
|
||||
- **Абстрактные интерфейсы** для источников перетаскивания и целей сброса
|
||||
- **Базовые классы поведения** для упрощения реализации
|
||||
- **Платформонезависимая архитектура**
|
||||
- **Поддержка сложных сценариев** (переупорядочивание, вложенное перетаскивание)
|
||||
- **Расширяемая система событий**
|
||||
|
||||
## 🔧 Интерфейсы
|
||||
|
||||
### IDragVisualProvider
|
||||
```csharp
|
||||
public interface IDragVisualProvider
|
||||
{
|
||||
object CreateDragVisual(DragInfo dragInfo, Point initialPosition);
|
||||
void UpdateDragVisualPosition(object dragVisual, Point position);
|
||||
void ReleaseDragVisual(object dragVisual);
|
||||
}
|
||||
```
|
||||
|
||||
### IDropVisualAdorner
|
||||
```csharp
|
||||
public interface IDropVisualAdorner
|
||||
{
|
||||
void Show(DropInfo dropInfo, Rect targetBounds);
|
||||
void Update(DropInfo dropInfo);
|
||||
void Hide();
|
||||
}
|
||||
```
|
||||
|
||||
## 📦 Установка
|
||||
|
||||
Добавьте проект как ссылку в ваше решение или установите как NuGet пакет:
|
||||
|
||||
```xml
|
||||
<PackageReference Include="Lattice.UI.DragDrop" Version="1.0.0" />
|
||||
```
|
||||
|
||||
## 🔗 Зависимости
|
||||
|
||||
- `Lattice.Core.DragDrop` >= 1.0.0
|
||||
- `Lattice.Core.Geometry` >= 1.0.0
|
||||
- `Microsoft.Extensions.DependencyInjection.Abstractions` >= 8.0.0
|
||||
|
||||
## 🚀 Быстрый старт
|
||||
|
||||
### 1. Регистрация сервисов
|
||||
|
||||
```csharp
|
||||
using Lattice.UI.DragDrop.Extensions;
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLatticeDragDrop();
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Создание кастомного поведения
|
||||
|
||||
```csharp
|
||||
using Lattice.UI.DragDrop.Behaviors;
|
||||
|
||||
public class MyDragSource : DragSourceBehaviorBase<MyElement>
|
||||
{
|
||||
protected override void SubscribeToEvents(MyElement element)
|
||||
{
|
||||
// Подписка на события элемента
|
||||
}
|
||||
|
||||
public override bool CanStartDrag(out DragInfo? dragInfo)
|
||||
{
|
||||
// Реализация проверки возможности перетаскивания
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📚 API Reference
|
||||
|
||||
### Основные типы
|
||||
|
||||
| Тип | Описание |
|
||||
|-----|----------|
|
||||
| `DragSourceBehaviorBase<T>` | Базовый класс для поведения источника |
|
||||
| `DropTargetBehaviorBase<T>` | Базовый класс для поведения цели |
|
||||
| `IDragVisualProvider` | Поставщик визуального представления |
|
||||
| `IDropVisualAdorner` | Визуальный элемент обратной связи |
|
||||
|
||||
### Расширения DI
|
||||
|
||||
- `AddLatticeDragDrop()` - регистрация сервисов перетаскивания
|
||||
|
||||
## 🔄 Интеграция с платформенными проектами
|
||||
|
||||
Этот проект предназначен для наследования платформенными реализациями:
|
||||
|
||||
1. **WinUI**: `Lattice.UI.DragDrop.WinUI`
|
||||
2. **Uno Platform**: `Lattice.UI.DragDrop.Uno` (планируется)
|
||||
3. **MAUI**: `Lattice.UI.DragDrop.Maui` (планируется)
|
||||
|
||||
## 🧪 Тестирование
|
||||
|
||||
Проект включает модульные тесты для всех публичных API:
|
||||
|
||||
```bash
|
||||
dotnet test Lattice.UI.DragDrop.Tests
|
||||
```
|
||||
|
||||
## 📄 Лицензия
|
||||
|
||||
MIT License. Подробности в файле [LICENSE](LICENSE).
|
||||
|
||||
## 🤝 Участие в разработке
|
||||
|
||||
1. Форкните репозиторий
|
||||
2. Создайте ветку для вашей функции
|
||||
3. Сделайте коммит изменений
|
||||
4. Отправьте пул-реквест
|
||||
|
||||
## 📞 Поддержка
|
||||
|
||||
- Документация: [lattice-framework.github.io](https://lattice-framework.github.io)
|
||||
- Issues: [GitHub Issues](https://github.com/lattice-framework/ui-dragdrop/issues)
|
||||
- Обсуждения: [GitHub Discussions](https://github.com/lattice-framework/ui-dragdrop/discussions)
|
||||
Reference in New Issue
Block a user