Browse Source

raise routed events on drag and drop

pull/1417/head
Florian Sundermann 8 years ago
parent
commit
9ae9f6d221
  1. 4
      src/Avalonia.Controls/Application.cs
  2. 90
      src/Avalonia.Controls/DragDrop/DefaultDragDispatcher.cs
  3. 24
      src/Avalonia.Controls/DragDrop/DragDrop.cs
  4. 18
      src/Avalonia.Controls/DragDrop/DragEventArgs.cs
  5. 11
      src/Avalonia.Controls/DragDrop/IDragDispatcher.cs
  6. 1
      src/Avalonia.Controls/Properties/AssemblyInfo.cs
  7. 4
      src/OSX/Avalonia.MonoMac/TopLevelImpl.cs

4
src/Avalonia.Controls/Application.cs

@ -12,6 +12,7 @@ using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.Threading;
using System.Reactive.Concurrency;
using Avalonia.Controls.DragDrop;
namespace Avalonia
{
@ -234,7 +235,8 @@ namespace Avalonia
.Bind<IStyler>().ToConstant(_styler)
.Bind<ILayoutManager>().ToSingleton<LayoutManager>()
.Bind<IApplicationLifecycle>().ToConstant(this)
.Bind<IScheduler>().ToConstant(AvaloniaScheduler.Instance);
.Bind<IScheduler>().ToConstant(AvaloniaScheduler.Instance)
.Bind<IDragDispatcher>().ToConstant(DefaultDragDispatcher.Instance);
}
}
}

90
src/Avalonia.Controls/DragDrop/DefaultDragDispatcher.cs

@ -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;
}
}
}
}

24
src/Avalonia.Controls/DragDrop/DragDrop.cs

@ -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);
}
}
}

18
src/Avalonia.Controls/DragDrop/DragEventArgs.cs

@ -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;
}
}
}

11
src/Avalonia.Controls/DragDrop/IDragDispatcher.cs

@ -2,11 +2,14 @@
namespace Avalonia.Controls.DragDrop
{
/// <summary>
/// Dispatches Drag+Drop events to the correct visual targets, based on the input root and the drag location.
/// </summary>
public interface IDragDispatcher
{
DragOperation DragEnter(IInputRoot inputRoot, Point point, IDragData data, DragOperation operation);
DragOperation DragOver(IInputRoot inputRoot, Point point, IDragData data, DragOperation operation);
void DragLeave(IInputRoot inputRoot);
DragOperation Drop(IInputRoot inputRoot, Point point, IDragData data, DragOperation operation);
DragOperation DragEnter(IInputElement inputRoot, Point point, IDragData data, DragOperation operation);
DragOperation DragOver(IInputElement inputRoot, Point point, IDragData data, DragOperation operation);
void DragLeave(IInputElement inputRoot);
DragOperation Drop(IInputElement inputRoot, Point point, IDragData data, DragOperation operation);
}
}

1
src/Avalonia.Controls/Properties/AssemblyInfo.cs

@ -11,6 +11,7 @@ using Avalonia.Metadata;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.DragDrop")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Embedding")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Presenters")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls.Primitives")]

4
src/OSX/Avalonia.MonoMac/TopLevelImpl.cs

@ -201,7 +201,7 @@ namespace Avalonia.MonoMac
dragOp = _dragDispatcher.DragOver(root, pt, info, dragOp);
return DraggingInfo.ConvertDragOperation(dragOp) != DragOperation.None;
return dragOp != DragOperation.None;
}
public override bool PerformDragOperation(NSDraggingInfo sender)
@ -216,7 +216,7 @@ namespace Avalonia.MonoMac
dragOp = _dragDispatcher.Drop(root, pt, info, dragOp);
return DraggingInfo.ConvertDragOperation(dragOp) != DragOperation.None;
return dragOp != DragOperation.None;
}

Loading…
Cancel
Save