From 57ee4dee4012db74d2f390ffa7bee37f2225de48 Mon Sep 17 00:00:00 2001 From: BAndysc Date: Mon, 11 Jan 2021 03:26:53 +0000 Subject: [PATCH] [SolutionExplorer] Implemented proper drag and drop in solution explorer --- .../ViewModels/SolutionExplorerViewModel.cs | 94 +++++++++++++++++-- .../ViewModels/SolutionItemViewModel.cs | 43 +++++++-- .../Explorer/Views/SolutionExplorerView.xaml | 33 ++++++- WoWDatabaseEditor/Themes/BlueTheme.xaml | 15 +++ 4 files changed, 164 insertions(+), 21 deletions(-) diff --git a/WDE.Solutions/Explorer/ViewModels/SolutionExplorerViewModel.cs b/WDE.Solutions/Explorer/ViewModels/SolutionExplorerViewModel.cs index d0d644434..95b1aa842 100644 --- a/WDE.Solutions/Explorer/ViewModels/SolutionExplorerViewModel.cs +++ b/WDE.Solutions/Explorer/ViewModels/SolutionExplorerViewModel.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Windows; using System.Windows.Controls; +using GongSolutions.Wpf.DragDrop; using Prism.Events; using WDE.Common; using WDE.Common.Events; @@ -15,11 +16,12 @@ namespace WDE.Solutions.Explorer.ViewModels { - public class SolutionExplorerViewModel : BindableBase, ITool + public class SolutionExplorerViewModel : BindableBase, ITool, IDropTarget { private readonly ISolutionItemNameRegistry itemNameRegistry; private readonly ISolutionManager _solutionManager; private readonly IEventAggregator _ea; + private readonly IStatusBar _statusBar; private ObservableCollection _firstGeneration; public ObservableCollection Root => _firstGeneration; @@ -33,11 +35,17 @@ public class SolutionExplorerViewModel : BindableBase, ITool private SolutionItemViewModel _selected; private Dictionary _itemToViewmodel; - public SolutionExplorerViewModel(ISolutionItemNameRegistry itemNameRegistry, ISolutionManager solutionManager, IEventAggregator ea, INewItemService newItemService, ISolutionItemSqlGeneratorRegistry sqlGeneratorRegistry) + public SolutionExplorerViewModel(ISolutionItemNameRegistry itemNameRegistry, + ISolutionManager solutionManager, + IEventAggregator ea, + INewItemService newItemService, + IStatusBar statusBar, + ISolutionItemSqlGeneratorRegistry sqlGeneratorRegistry) { this.itemNameRegistry = itemNameRegistry; _solutionManager = solutionManager; _ea = ea; + _statusBar = statusBar; _firstGeneration = new ObservableCollection(); _itemToViewmodel = new Dictionary(); @@ -50,8 +58,14 @@ public SolutionExplorerViewModel(ISolutionItemNameRegistry itemNameRegistry, ISo _solutionManager.Items.CollectionChanged += (sender, args) => { if (args.NewItems != null) + { + int i = 0; foreach (var obj in args.NewItems) - AddItemToRoot(obj as ISolutionItem); + { + AddItemToRoot(obj as ISolutionItem, args.NewStartingIndex + i); + i++; + } + } if (args.OldItems != null) foreach (var obj in args.OldItems) @@ -108,11 +122,16 @@ public SolutionExplorerViewModel(ISolutionItemNameRegistry itemNameRegistry, ISo }); } - private void AddItemToRoot(ISolutionItem item) + private void AddItemToRoot(ISolutionItem item, int index = -1) { - var viewModel = new SolutionItemViewModel(itemNameRegistry, item); - _itemToViewmodel.Add(item, viewModel); - Root.Add(viewModel); + if (!_itemToViewmodel.TryGetValue(item, out var viewModel)) + { + viewModel = new SolutionItemViewModel(itemNameRegistry, item); + _itemToViewmodel[item] = viewModel; + } + else + viewModel.Parent = null; + Root.Insert(index < 0 ? Root.Count : index, viewModel); } public string Title { get; } = "Solution explorer"; @@ -122,5 +141,66 @@ public Visibility Visibility get => _visibility; set => SetProperty(ref _visibility, value); } + + public void DragOver(IDropInfo dropInfo) + { + SolutionItemViewModel sourceItem = dropInfo.Data as SolutionItemViewModel; + SolutionItemViewModel targetItem = dropInfo.TargetItem as SolutionItemViewModel; + + if (sourceItem != null) + { + var highlight = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter) && + (targetItem?.IsContainer ?? false); + + dropInfo.DropTargetAdorner = highlight ? DropTargetAdorners.Highlight : DropTargetAdorners.Insert; + dropInfo.Effects = DragDropEffects.Move; + } + } + + public void Drop(IDropInfo dropInfo) + { + SolutionItemViewModel sourceItem = dropInfo.Data as SolutionItemViewModel; + SolutionItemViewModel targetItem = dropInfo.TargetItem as SolutionItemViewModel; + + if (sourceItem == null) + return; + + int prevPosition = 0; + var sourceList = sourceItem.Parent == null ? _solutionManager.Items : sourceItem.Parent.Item.Items; + var destListOwner = (dropInfo.DropTargetAdorner == DropTargetAdorners.Highlight) + ? targetItem + : targetItem?.Parent; + var destList = destListOwner?.Item?.Items ?? _solutionManager.Items; + + while (destListOwner != null) + { + if (sourceItem.Item == destListOwner.Item) + return; + destListOwner = destListOwner.Parent; + } + + prevPosition = sourceList.IndexOf(sourceItem.Item); + if (prevPosition >= 0) + sourceList.RemoveAt(prevPosition); + + if (dropInfo.DropTargetAdorner == DropTargetAdorners.Highlight) + { + targetItem.AddViewModel(sourceItem); + targetItem.Item.Items.Add(sourceItem.Item); + } + else + { + if (targetItem == null || targetItem.Parent == null) + _itemToViewmodel[sourceItem.Item] = sourceItem; + else + targetItem.Parent.AddViewModel(sourceItem); + + var destPosition = dropInfo.InsertIndex; + if (destList == sourceList && dropInfo.InsertIndex >= prevPosition) + destPosition--; + + destList.Insert(destPosition, sourceItem.Item); + } + } } } diff --git a/WDE.Solutions/Explorer/ViewModels/SolutionItemViewModel.cs b/WDE.Solutions/Explorer/ViewModels/SolutionItemViewModel.cs index c7161fb69..285af74df 100644 --- a/WDE.Solutions/Explorer/ViewModels/SolutionItemViewModel.cs +++ b/WDE.Solutions/Explorer/ViewModels/SolutionItemViewModel.cs @@ -14,7 +14,7 @@ public class SolutionItemViewModel : BindableBase private ISolutionItemNameRegistry itemNameRegistry; private readonly ISolutionItem _item; - private readonly SolutionItemViewModel _parent; + private SolutionItemViewModel _parent; private readonly ObservableCollection _children; public ObservableCollection Children => _children; @@ -26,14 +26,24 @@ public class SolutionItemViewModel : BindableBase public bool IsContainer => _item.IsContainer; public bool IsExportable => _item.IsExportable; public ISolutionItem Item => _item; - public SolutionItemViewModel Parent => _parent; + public SolutionItemViewModel Parent + { + get => _parent; + set => _parent = value; + } private bool _isSelected; - public bool IsSelected { - get { return _isSelected; } - set { SetProperty(ref _isSelected, value); } + get => _isSelected; + set => SetProperty(ref _isSelected, value); + } + + private bool _isExpanded; + public bool IsExpanded + { + get => _isExpanded; + set => SetProperty(ref _isExpanded, value); } public SolutionItemViewModel(ISolutionItemNameRegistry itemNameRegistry, ISolutionItem item) : this(itemNameRegistry, item, null) @@ -58,8 +68,11 @@ public SolutionItemViewModel(ISolutionItemNameRegistry itemNameRegistry, ISoluti item.Items.CollectionChanged += (sender, args) => { if (args.NewItems != null) + { + int i = 0; foreach (object obj in args.NewItems) - AddItem(obj as ISolutionItem); + AddItem(obj as ISolutionItem, args.NewStartingIndex + i); + } if (args.OldItems != null) foreach (object obj in args.OldItems) @@ -72,11 +85,21 @@ public SolutionItemViewModel(ISolutionItemNameRegistry itemNameRegistry, ISoluti } } - private void AddItem(ISolutionItem item) + private void AddItem(ISolutionItem item, int index = -1) + { + if (!_itemToViewmodel.TryGetValue(item, out var viewModel)) + { + viewModel = new SolutionItemViewModel(itemNameRegistry, item, this); + _itemToViewmodel[item] = viewModel; + } + else + viewModel.Parent = this; + _children.Insert(index < 0 ? _children.Count : index, viewModel); + } + + public void AddViewModel(SolutionItemViewModel sourceItem) { - var viewModel = new SolutionItemViewModel(itemNameRegistry, item, this); - _children.Add(viewModel); - _itemToViewmodel.Add(item, viewModel); + _itemToViewmodel[sourceItem.Item] = sourceItem; } } } diff --git a/WDE.Solutions/Explorer/Views/SolutionExplorerView.xaml b/WDE.Solutions/Explorer/Views/SolutionExplorerView.xaml index 960aeb1eb..55ad418f5 100644 --- a/WDE.Solutions/Explorer/Views/SolutionExplorerView.xaml +++ b/WDE.Solutions/Explorer/Views/SolutionExplorerView.xaml @@ -6,6 +6,7 @@ xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:dd="urn:gong-wpf-dragdrop" xmlns:helpers="clr-namespace:WDE.Solutions.Explorer.Helpers" + xmlns:system="clr-namespace:System;assembly=System.Runtime" prism:ViewModelLocator.AutoWireViewModel="True" x:Name="UC"> @@ -190,7 +191,7 @@ - + @@ -204,6 +205,8 @@ + + + +