csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.8 KiB
113 lines
3.8 KiB
using Avalonia.Input;
|
|
using Avalonia.Interactivity;
|
|
using Avalonia.VisualTree;
|
|
using System.Linq;
|
|
using Avalonia.Controls.DragDrop.Raw;
|
|
using Avalonia.Input.Raw;
|
|
|
|
namespace Avalonia.Controls.DragDrop
|
|
{
|
|
class DragDropDevice : IDragDropDevice
|
|
{
|
|
public static readonly DragDropDevice Instance = new DragDropDevice();
|
|
|
|
private Interactive _lastTarget = null;
|
|
|
|
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 DragDropEffects RaiseDragEvent(Interactive target, RoutedEvent<DragEventArgs> routedEvent, DragDropEffects operation, IDataObject data)
|
|
{
|
|
if (target == null)
|
|
return DragDropEffects.None;
|
|
var args = new DragEventArgs(routedEvent, data)
|
|
{
|
|
RoutedEvent = routedEvent,
|
|
DragEffects = operation
|
|
};
|
|
target.RaiseEvent(args);
|
|
return args.DragEffects;
|
|
}
|
|
|
|
private DragDropEffects DragEnter(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
|
|
{
|
|
_lastTarget = GetTarget(inputRoot, point);
|
|
return RaiseDragEvent(_lastTarget, DragDrop.DragEnterEvent, effects, data);
|
|
}
|
|
|
|
private DragDropEffects DragOver(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
|
|
{
|
|
var target = GetTarget(inputRoot, point);
|
|
|
|
if (target == _lastTarget)
|
|
return RaiseDragEvent(target, DragDrop.DragOverEvent, effects, data);
|
|
|
|
try
|
|
{
|
|
if (_lastTarget != null)
|
|
_lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent));
|
|
return RaiseDragEvent(target, DragDrop.DragEnterEvent, effects, data);
|
|
}
|
|
finally
|
|
{
|
|
_lastTarget = target;
|
|
}
|
|
}
|
|
|
|
private void DragLeave(IInputElement inputRoot)
|
|
{
|
|
if (_lastTarget == null)
|
|
return;
|
|
try
|
|
{
|
|
_lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent));
|
|
}
|
|
finally
|
|
{
|
|
_lastTarget = null;
|
|
}
|
|
}
|
|
|
|
private DragDropEffects Drop(IInputElement inputRoot, Point point, IDataObject data, DragDropEffects effects)
|
|
{
|
|
try
|
|
{
|
|
return RaiseDragEvent(_lastTarget, DragDrop.DropEvent, effects, data);
|
|
}
|
|
finally
|
|
{
|
|
_lastTarget = null;
|
|
}
|
|
}
|
|
|
|
public void ProcessRawEvent(RawInputEventArgs e)
|
|
{
|
|
if (!e.Handled && e is RawDragEvent margs)
|
|
ProcessRawEvent(margs);
|
|
}
|
|
|
|
private void ProcessRawEvent(RawDragEvent e)
|
|
{
|
|
switch (e.Type)
|
|
{
|
|
case RawDragEventType.DragEnter:
|
|
e.Effects = DragEnter(e.InputRoot, e.Location, e.Data, e.Effects);
|
|
break;
|
|
case RawDragEventType.DragOver:
|
|
e.Effects = DragOver(e.InputRoot, e.Location, e.Data, e.Effects);
|
|
break;
|
|
case RawDragEventType.DragLeave:
|
|
DragLeave(e.InputRoot);
|
|
break;
|
|
case RawDragEventType.Drop:
|
|
e.Effects = Drop(e.InputRoot, e.Location, e.Data, e.Effects);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|