7 changed files with 145 additions and 7 deletions
@ -0,0 +1,90 @@ |
|||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Interactivity; |
||||
|
using Avalonia.VisualTree; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace Avalonia.Controls.DragDrop |
||||
|
{ |
||||
|
class DefaultDragDispatcher : IDragDispatcher |
||||
|
{ |
||||
|
public static readonly DefaultDragDispatcher Instance = new DefaultDragDispatcher(); |
||||
|
|
||||
|
private Interactive _lastTarget = null; |
||||
|
|
||||
|
private DefaultDragDispatcher() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
private Interactive GetTarget(IInputElement root, Point local) |
||||
|
{ |
||||
|
var target = root.InputHitTest(local)?.GetSelfAndVisualAncestors()?.OfType<Interactive>()?.FirstOrDefault(); |
||||
|
if (target != null && DragDrop.GetAcceptDrag(target)) |
||||
|
return target; |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private DragOperation RaiseDragEvent(Interactive target, RoutedEvent<DragEventArgs> routedEvent, DragOperation operation, IDragData data) |
||||
|
{ |
||||
|
if (target == null) |
||||
|
return DragOperation.None; |
||||
|
var args = new DragEventArgs(routedEvent, data) |
||||
|
{ |
||||
|
RoutedEvent = routedEvent, |
||||
|
DragOperation = operation |
||||
|
}; |
||||
|
target.RaiseEvent(args); |
||||
|
return args.DragOperation; |
||||
|
} |
||||
|
|
||||
|
public DragOperation DragEnter(IInputElement inputRoot, Point point, IDragData data, DragOperation operation) |
||||
|
{ |
||||
|
_lastTarget = GetTarget(inputRoot, point); |
||||
|
return RaiseDragEvent(_lastTarget, DragDrop.DragEnterEvent, operation, data); |
||||
|
} |
||||
|
|
||||
|
public DragOperation DragOver(IInputElement inputRoot, Point point, IDragData data, DragOperation operation) |
||||
|
{ |
||||
|
var target = GetTarget(inputRoot, point); |
||||
|
|
||||
|
if (target == _lastTarget) |
||||
|
return RaiseDragEvent(target, DragDrop.DragOverEvent, operation, data); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
if (_lastTarget != null) |
||||
|
_lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent)); |
||||
|
return RaiseDragEvent(target, DragDrop.DragEnterEvent, operation, data); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_lastTarget = target; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void DragLeave(IInputElement inputRoot) |
||||
|
{ |
||||
|
if (_lastTarget == null) |
||||
|
return; |
||||
|
try |
||||
|
{ |
||||
|
_lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent)); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_lastTarget = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public DragOperation Drop(IInputElement inputRoot, Point point, IDragData data, DragOperation operation) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
return RaiseDragEvent(_lastTarget, DragDrop.DropEvent, operation, data); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_lastTarget = null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using Avalonia.Interactivity; |
||||
|
|
||||
|
namespace Avalonia.Controls.DragDrop |
||||
|
{ |
||||
|
public sealed class DragDrop : AvaloniaObject |
||||
|
{ |
||||
|
public static RoutedEvent<DragEventArgs> DragEnterEvent = RoutedEvent.Register<DragEventArgs>("DragEnter", RoutingStrategies.Bubble, typeof(DragDrop)); |
||||
|
public static RoutedEvent<RoutedEventArgs> DragLeaveEvent = RoutedEvent.Register<RoutedEventArgs>("DragLeave", RoutingStrategies.Bubble, typeof(DragDrop)); |
||||
|
public static RoutedEvent<DragEventArgs> DragOverEvent = RoutedEvent.Register<DragEventArgs>("DragOver", RoutingStrategies.Bubble, typeof(DragDrop)); |
||||
|
public static RoutedEvent<DragEventArgs> DropEvent = RoutedEvent.Register<DragEventArgs>("Drop", RoutingStrategies.Bubble, typeof(DragDrop)); |
||||
|
|
||||
|
public static AvaloniaProperty<bool> AcceptDragProperty = AvaloniaProperty.RegisterAttached<Interactive, bool>("AcceptDrag", typeof(DragDrop), inherits: true); |
||||
|
|
||||
|
public static bool GetAcceptDrag(Interactive interactive) |
||||
|
{ |
||||
|
return interactive.GetValue(AcceptDragProperty); |
||||
|
} |
||||
|
|
||||
|
public static void SetAcceptDrag(Interactive interactive, bool value) |
||||
|
{ |
||||
|
interactive.SetValue(AcceptDragProperty, value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Avalonia.Interactivity; |
||||
|
|
||||
|
namespace Avalonia.Controls.DragDrop |
||||
|
{ |
||||
|
public class DragEventArgs : RoutedEventArgs |
||||
|
{ |
||||
|
public DragOperation DragOperation { get; set; } |
||||
|
|
||||
|
public IDragData Data { get; private set; } |
||||
|
|
||||
|
public DragEventArgs(RoutedEvent<DragEventArgs> routedEvent, IDragData data) |
||||
|
: base(routedEvent) |
||||
|
{ |
||||
|
this.Data = data; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue