/
DragBehavior.cs
109 lines (91 loc) · 3.86 KB
/
DragBehavior.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Xaml.Interactivity;
namespace Dock.Avalonia
{
public sealed class DragBehavior : Behavior<Control>
{
private Point _dragStartPoint;
private bool _pointerPressed;
private bool _doDragDrop;
public static double MinimumHorizontalDragDistance = 4;
public static double MinimumVerticalDragDistance = 4;
public static readonly AvaloniaProperty ContextProperty =
AvaloniaProperty.Register<DragBehavior, object>(nameof(Context));
public static readonly AvaloniaProperty IsTunneledProperty =
AvaloniaProperty.Register<DragBehavior, bool>(nameof(IsTunneled), false);
public object Context
{
get => (object)GetValue(ContextProperty);
set => SetValue(ContextProperty, value);
}
public bool IsTunneled
{
get => (bool)GetValue(IsTunneledProperty);
set => SetValue(IsTunneledProperty, value);
}
protected override void OnAttached()
{
base.OnAttached();
var routes = RoutingStrategies.Direct | RoutingStrategies.Bubble;
if (IsTunneled)
{
routes |= RoutingStrategies.Tunnel;
}
AssociatedObject.AddHandler(InputElement.PointerPressedEvent, PointerPressed, routes);
AssociatedObject.AddHandler(InputElement.PointerReleasedEvent, PointerReleased, routes);
AssociatedObject.AddHandler(InputElement.PointerMovedEvent, PointerMoved, routes);
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.RemoveHandler(InputElement.PointerPressedEvent, PointerPressed);
AssociatedObject.RemoveHandler(InputElement.PointerReleasedEvent, PointerReleased);
AssociatedObject.RemoveHandler(InputElement.PointerMovedEvent, PointerMoved);
}
private void PointerPressed(object sender, PointerPressedEventArgs e)
{
if (e.MouseButton == MouseButton.Left)
{
_dragStartPoint = e.GetPosition(AssociatedObject);
_pointerPressed = true;
_doDragDrop = false;
}
}
private void PointerReleased(object sender, PointerReleasedEventArgs e)
{
if (e.MouseButton == MouseButton.Left)
{
_pointerPressed = false;
_doDragDrop = false;
}
}
private async void PointerMoved(object sender, PointerEventArgs e)
{
Point point = e.GetPosition(AssociatedObject);
Vector diff = _dragStartPoint - point;
bool min = (Math.Abs(diff.X) > MinimumHorizontalDragDistance || Math.Abs(diff.Y) > MinimumVerticalDragDistance);
if (_pointerPressed == true && _doDragDrop == false && min == true)
{
_doDragDrop = true;
var data = new DataObject();
data.Set(DragDataFormats.Context, Context);
var effect = DragDropEffects.None;
if (e.InputModifiers.HasFlag(InputModifiers.Alt))
effect |= DragDropEffects.Link;
else if (e.InputModifiers.HasFlag(InputModifiers.Shift))
effect |= DragDropEffects.Move;
else if (e.InputModifiers.HasFlag(InputModifiers.Control))
effect |= DragDropEffects.Copy;
else
effect |= DragDropEffects.Move;
var result = await DragDrop.DoDragDrop(data, effect);
}
}
}
}