Skip to content

Commit

Permalink
Merge pull request #13 from danwalmsley/item-nudge-behavior
Browse files Browse the repository at this point in the history
Behavior to nudge items out the way during drag drop operations.
  • Loading branch information
wieslawsoltes authored Nov 19, 2024
2 parents 6dda3ca + fee71e2 commit d961dbe
Showing 1 changed file with 97 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
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;

/// <summary>
///
/// </summary>
public class ItemNudgeDropBehavior : StyledElementBehavior<ItemsControl>
{
/// <summary>
///
/// </summary>
public static readonly StyledProperty<Orientation> OrientationProperty =
AvaloniaProperty.Register<ItemNudgeDropBehavior, Orientation>(nameof(Orientation),
defaultValue: Orientation.Vertical);

/// <summary>
///
/// </summary>
public Orientation Orientation
{
get => GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}

/// <inheritdoc />
protected override void OnAttachedToVisualTree()
{
AssociatedObject?.AddHandler(DragDrop.DragLeaveEvent, OnDragLeave);
AssociatedObject?.AddHandler(DragDrop.DragOverEvent, OnDragOver);
AssociatedObject?.AddHandler(DragDrop.DropEvent, OnDrop);
}

/// <inheritdoc />
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);
}
}
}

0 comments on commit d961dbe

Please sign in to comment.