From 36882961fed857efccdbb11ad493aa6cc15f6fe8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 Nov 2024 14:32:54 +0000 Subject: [PATCH 1/2] Behavior to nudge items out the way during drag drop operations. --- .../ItemsControl/ItemNudgeDropBehavior.cs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/Avalonia.Xaml.Interactions.Custom/ItemsControl/ItemNudgeDropBehavior.cs diff --git a/src/Avalonia.Xaml.Interactions.Custom/ItemsControl/ItemNudgeDropBehavior.cs b/src/Avalonia.Xaml.Interactions.Custom/ItemsControl/ItemNudgeDropBehavior.cs new file mode 100644 index 00000000..19bf5f35 --- /dev/null +++ b/src/Avalonia.Xaml.Interactions.Custom/ItemsControl/ItemNudgeDropBehavior.cs @@ -0,0 +1,88 @@ +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Layout; +using Avalonia.Media.Transformation; +using Avalonia.Xaml.Interactivity; + +namespace Avalonia.Xaml.Interactions.Custom; + +public class ItemNudgeDropBehavior : StyledElementBehavior +{ + public static readonly StyledProperty OrientationProperty = + AvaloniaProperty.Register(nameof(Orientation), + defaultValue: Orientation.Vertical); + + public Orientation Orientation + { + get => GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + + /// + protected override void OnAttachedToVisualTree() + { + AssociatedObject?.AddHandler(DragDrop.DragLeaveEvent, OnDragLeave); + AssociatedObject?.AddHandler(DragDrop.DragOverEvent, OnDragOver); + AssociatedObject?.AddHandler(DragDrop.DropEvent, OnDrop); + } + + /// + protected override void OnDetachedFromVisualTree() + { + AssociatedObject?.RemoveHandler(DragDrop.DragLeaveEvent, OnDragLeave); + AssociatedObject?.RemoveHandler(DragDrop.DragOverEvent, OnDragOver); + AssociatedObject?.RemoveHandler(DragDrop.DropEvent, OnDrop); + } + + private void ApplyTranslation(Control control, double x, double y) + { + var transformBuilder = new TransformOperations.Builder(1); + transformBuilder.AppendTranslate(x, y); + control.RenderTransform = transformBuilder.Build(); + } + + private void RemoveTranslations(object? sender) + { + if (sender is ItemsControl itemsControl) + { + foreach (var container in itemsControl.GetRealizedContainers()) + { + ApplyTranslation(container, 0, 0); + } + } + } + + private void OnDrop(object? sender, DragEventArgs e) + { + RemoveTranslations(sender); + } + + private void OnDragLeave(object? sender, RoutedEventArgs e) + { + RemoveTranslations(sender); + } + + private void OnDragOver(object? sender, DragEventArgs e) + { + if (sender is not ItemsControl itemsControl) return; + + var isHorizontal = Orientation == Orientation.Horizontal; + + var dragPosition = e.GetPosition(itemsControl); + + for (int index = 0; index < itemsControl.ItemCount; index++) + { + var container = itemsControl.ContainerFromIndex(index); + + if (container == null) continue; + + var containerMidPoint = isHorizontal ? container.Bounds.Center.X : container.Bounds.Center.Y; + + var translationX = isHorizontal && dragPosition.X <= containerMidPoint ? container.Bounds.Width : 0; + var translationY = !isHorizontal && dragPosition.Y <= containerMidPoint ? container.Bounds.Height : 0; + + ApplyTranslation(container, translationX, translationY); + } + } +} From fee71e271cac6d10459d1f014d6e4f5638708be7 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 Nov 2024 14:35:58 +0000 Subject: [PATCH 2/2] comments --- .../ItemsControl/ItemNudgeDropBehavior.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Avalonia.Xaml.Interactions.Custom/ItemsControl/ItemNudgeDropBehavior.cs b/src/Avalonia.Xaml.Interactions.Custom/ItemsControl/ItemNudgeDropBehavior.cs index 19bf5f35..9c5b690e 100644 --- a/src/Avalonia.Xaml.Interactions.Custom/ItemsControl/ItemNudgeDropBehavior.cs +++ b/src/Avalonia.Xaml.Interactions.Custom/ItemsControl/ItemNudgeDropBehavior.cs @@ -7,12 +7,21 @@ namespace Avalonia.Xaml.Interactions.Custom; +/// +/// +/// public class ItemNudgeDropBehavior : StyledElementBehavior { + /// + /// + /// public static readonly StyledProperty OrientationProperty = AvaloniaProperty.Register(nameof(Orientation), defaultValue: Orientation.Vertical); + /// + /// + /// public Orientation Orientation { get => GetValue(OrientationProperty);