|
1 |
| -namespace Rubberduck.UI.Refactorings.ReorderParameters |
| 1 | +using System; |
| 2 | +using System.Windows; |
| 3 | +using System.Windows.Controls; |
| 4 | +using System.Windows.Documents; |
| 5 | +using System.Windows.Input; |
| 6 | +using System.Windows.Media; |
| 7 | +using Rubberduck.Refactorings.ReorderParameters; |
| 8 | + |
| 9 | +namespace Rubberduck.UI.Refactorings.ReorderParameters |
2 | 10 | {
|
3 | 11 | public partial class ReorderParametersView
|
4 | 12 | {
|
| 13 | + // borrowed the drag/drop from https://fxmax.wordpress.com/2010/10/05/wpf/ |
| 14 | + private Point _startPoint; |
| 15 | + private DragAdorner _adorner; |
| 16 | + private AdornerLayer _layer; |
| 17 | + |
| 18 | + private ReorderParametersViewModel ViewModel => (ReorderParametersViewModel)DataContext; |
| 19 | + |
5 | 20 | public ReorderParametersView()
|
6 | 21 | {
|
7 | 22 | InitializeComponent();
|
8 | 23 | }
|
| 24 | + |
| 25 | + private void ParameterGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) |
| 26 | + { |
| 27 | + _startPoint = e.GetPosition(ParameterGrid); |
| 28 | + } |
| 29 | + |
| 30 | + private void ParameterGrid_PreviewMouseMove(object sender, MouseEventArgs e) |
| 31 | + { |
| 32 | + if (e.LeftButton == MouseButtonState.Pressed) |
| 33 | + { |
| 34 | + var position = e.GetPosition(null); |
| 35 | + |
| 36 | + if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance || |
| 37 | + Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance) |
| 38 | + { |
| 39 | + BeginDrag(e); |
| 40 | + } |
| 41 | + } |
| 42 | + } |
| 43 | + |
| 44 | + private void BeginDrag(MouseEventArgs e) |
| 45 | + { |
| 46 | + var listViewItem = FindAncestor<ListViewItem>((DependencyObject)e.OriginalSource); |
| 47 | + |
| 48 | + if (listViewItem == null) { return; } |
| 49 | + |
| 50 | + // get the data for the ListViewItem |
| 51 | + var parameter = (Parameter)ParameterGrid.ItemContainerGenerator.ItemFromContainer(listViewItem); |
| 52 | + |
| 53 | + //setup the drag adorner. |
| 54 | + InitialiseAdorner(listViewItem); |
| 55 | + |
| 56 | + //add handles to update the adorner. |
| 57 | + ParameterGrid.PreviewDragOver += ParameterGrid_DragOver; |
| 58 | + ParameterGrid.DragLeave += ParameterGrid_DragLeave; |
| 59 | + ParameterGrid.DragEnter += ParameterGrid_DragEnter; |
| 60 | + |
| 61 | + var data = new DataObject(typeof(Parameter), parameter); |
| 62 | + DragDrop.DoDragDrop(ParameterGrid, data, DragDropEffects.Move); |
| 63 | + |
| 64 | + //cleanup |
| 65 | + ParameterGrid.PreviewDragOver -= ParameterGrid_DragOver; |
| 66 | + ParameterGrid.DragLeave -= ParameterGrid_DragLeave; |
| 67 | + ParameterGrid.DragEnter -= ParameterGrid_DragEnter; |
| 68 | + |
| 69 | + if (_adorner != null) |
| 70 | + { |
| 71 | + AdornerLayer.GetAdornerLayer(ParameterGrid).Remove(_adorner); |
| 72 | + _adorner = null; |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + private void ParameterGrid_DragEnter(object sender, DragEventArgs e) |
| 77 | + { |
| 78 | + if (!e.Data.GetDataPresent(typeof(Parameter)) || |
| 79 | + sender == e.Source) |
| 80 | + { |
| 81 | + e.Effects = DragDropEffects.None; |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + |
| 86 | + private void ParameterGrid_Drop(object sender, DragEventArgs e) |
| 87 | + { |
| 88 | + if (e.Data.GetDataPresent(typeof(Parameter))) |
| 89 | + { |
| 90 | + var parameter = e.Data.GetData(typeof(Parameter)) as Parameter; |
| 91 | + var listViewItem = FindAncestor<ListViewItem>((DependencyObject)e.OriginalSource); |
| 92 | + |
| 93 | + if (listViewItem != null) |
| 94 | + { |
| 95 | + var parameterToReplace = (Parameter)ParameterGrid.ItemContainerGenerator.ItemFromContainer(listViewItem); |
| 96 | + var index = ParameterGrid.Items.IndexOf(parameterToReplace); |
| 97 | + |
| 98 | + if (index >= 0) |
| 99 | + { |
| 100 | + ViewModel.Parameters.Move(ViewModel.Parameters.IndexOf(parameter), index); |
| 101 | + } |
| 102 | + } |
| 103 | + else |
| 104 | + { |
| 105 | + ViewModel.Parameters.Move(ViewModel.Parameters.IndexOf(parameter), ViewModel.Parameters.Count - 1); |
| 106 | + } |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + private void InitialiseAdorner(ListViewItem listViewItem) |
| 111 | + { |
| 112 | + var brush = new VisualBrush(listViewItem); |
| 113 | + _adorner = new DragAdorner(listViewItem, listViewItem.RenderSize, brush) {Opacity = 0.5}; |
| 114 | + _layer = AdornerLayer.GetAdornerLayer(ParameterGrid); |
| 115 | + _layer.Add(_adorner); |
| 116 | + } |
| 117 | + |
| 118 | + void ParameterGrid_DragLeave(object sender, DragEventArgs e) |
| 119 | + { |
| 120 | + if (e.OriginalSource == ParameterGrid) |
| 121 | + { |
| 122 | + var p = e.GetPosition(ParameterGrid); |
| 123 | + var r = VisualTreeHelper.GetContentBounds(ParameterGrid); |
| 124 | + if (!r.Contains(p)) |
| 125 | + { |
| 126 | + e.Handled = true; |
| 127 | + } |
| 128 | + } |
| 129 | + } |
| 130 | + |
| 131 | + void ParameterGrid_DragOver(object sender, DragEventArgs args) |
| 132 | + { |
| 133 | + if (_adorner == null) { return; } |
| 134 | + |
| 135 | + _adorner.OffsetLeft = args.GetPosition(ParameterGrid).X; |
| 136 | + _adorner.OffsetTop = args.GetPosition(ParameterGrid).Y - _startPoint.Y; |
| 137 | + } |
| 138 | + |
| 139 | + // Helper to search up the VisualTree |
| 140 | + private static T FindAncestor<T>(DependencyObject current) |
| 141 | + where T : DependencyObject |
| 142 | + { |
| 143 | + do |
| 144 | + { |
| 145 | + if (current is T) |
| 146 | + { |
| 147 | + return (T)current; |
| 148 | + } |
| 149 | + current = VisualTreeHelper.GetParent(current); |
| 150 | + } |
| 151 | + while (current != null); |
| 152 | + return null; |
| 153 | + } |
9 | 154 | }
|
10 | 155 | }
|
0 commit comments