From 7bfda475729285d70d91bcc210a45e526a9459e6 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 10 Apr 2013 15:34:09 +0200 Subject: [PATCH] Fix moving projects between solution folders. --- .../Debugger.Core/TypeSystemExtensions.cs | 2 +- .../Base/Project/Dom/SimpleModelCollection.cs | 60 +++++++++++-------- .../Gui/Components/ExtTreeView/ExtTreeView.cs | 13 ++-- .../TreeNodes/SolutionFolderNode.cs | 32 +++++----- .../ProjectBrowser/TreeNodes/SolutionNode.cs | 4 +- .../SharpDevelop/Project/SolutionFolder.cs | 14 ++++- 6 files changed, 76 insertions(+), 49 deletions(-) diff --git a/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs b/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs index 2ac02c45bb..3804036706 100644 --- a/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs +++ b/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs @@ -237,7 +237,7 @@ namespace Debugger 0, elementType); } default: - throw new System.Exception("Invalid value for TypeKind"); + throw new System.Exception("Invalid value for TypeKind: " + type.Kind); } } diff --git a/src/Main/Base/Project/Dom/SimpleModelCollection.cs b/src/Main/Base/Project/Dom/SimpleModelCollection.cs index cd2d9e33b0..eb5eb16560 100644 --- a/src/Main/Base/Project/Dom/SimpleModelCollection.cs +++ b/src/Main/Base/Project/Dom/SimpleModelCollection.cs @@ -122,13 +122,39 @@ namespace ICSharpCode.SharpDevelop.Dom #region IMutableModelCollection implementation + /// + /// Called immediately when an item is removed; even within a batch. + /// The collection may be in an invalid state while this method is called. + /// + protected virtual void OnRemove(T item) + { + if (addedItems != null && addedItems.Remove(item)) + return; + if (removedItems == null) + removedItems = new List(); + removedItems.Add(item); + } + + /// + /// Called immediately when an item is added; even within a batch. + /// The collection may be in an invalid state while this method is called. + /// + protected virtual void OnAdd(T item) + { + if (removedItems != null && removedItems.Remove(item)) + return; + if (addedItems == null) + addedItems = new List(); + addedItems.Add(item); + } + public void Clear() { CheckReentrancy(); addedItems = null; - if (removedItems == null) - removedItems = new List(); - removedItems.AddRange(list); + for (int i = 0; i < list.Count; i++) { + OnRemove(list[i]); + } list.Clear(); RaiseEventIfNotInBatch(); } @@ -137,11 +163,7 @@ namespace ICSharpCode.SharpDevelop.Dom { CheckReentrancy(); ValidateItem(item); - if (removedItems != null) - removedItems.Remove(item); - if (addedItems == null) - addedItems = new List(); - addedItems.Add(item); + OnAdd(item); list.Add(item); RaiseEventIfNotInBatch(); } @@ -155,15 +177,9 @@ namespace ICSharpCode.SharpDevelop.Dom for (int i = 0; i < itemsList.Count; i++) { ValidateItem(itemsList[i]); } - if (removedItems != null) { - for (int i = 0; i < itemsList.Count; i++) { - removedItems.Remove(itemsList[i]); - } + for (int i = 0; i < itemsList.Count; i++) { + OnAdd(itemsList[i]); } - if (addedItems != null) - addedItems.AddRange(itemsList); - else - addedItems = itemsList; list.AddRange(itemsList); RaiseEventIfNotInBatch(); } @@ -172,11 +188,7 @@ namespace ICSharpCode.SharpDevelop.Dom { CheckReentrancy(); if (list.Remove(item)) { - if (addedItems != null) - addedItems.Remove(item); - if (removedItems == null) - removedItems = new List(); - removedItems.Add(item); + OnRemove(item); RaiseEventIfNotInBatch(); return true; } else { @@ -190,11 +202,7 @@ namespace ICSharpCode.SharpDevelop.Dom int count = list.RemoveAll( delegate(T obj) { if (predicate(obj)) { - if (addedItems != null) - addedItems.Remove(obj); - if (removedItems == null) - removedItems = new List(); - removedItems.Add(obj); + OnRemove(obj); return true; } else { return false; diff --git a/src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeView.cs b/src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeView.cs index 7d6fe4aab0..2873556aab 100644 --- a/src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeView.cs +++ b/src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeView.cs @@ -416,10 +416,15 @@ namespace ICSharpCode.SharpDevelop.Gui // OnDragDrop raises without OnDragOver for the node. // So we have to call HandleDragOver to ensure that we don't call DoDragDrop for // invalid operations. - HandleDragOver(e, node); - if (e.Effect != DragDropEffects.None) { - node.DoDragDrop(e.Data, e.Effect); - SortParentNodes(node); + try { + HandleDragOver(e, node); + if (e.Effect != DragDropEffects.None) { + node.DoDragDrop(e.Data, e.Effect); + SortParentNodes(node); + } + } catch (Exception ex) { + // WinForms silently discards exceptions in the drag'n'drop events; so we need to catch+report any errors + SD.MessageService.ShowException(ex); } } } diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionFolderNode.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionFolderNode.cs index 9a45292022..13daebeb76 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionFolderNode.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionFolderNode.cs @@ -169,14 +169,7 @@ namespace ICSharpCode.SharpDevelop.Project Guid guid = Guid.Parse(dataObject.GetData(typeof(ISolutionItem).ToString()).ToString()); ISolutionItem solutionItem = folderNode.Solution.GetItemByGuid(guid); if (solutionItem != null) { - // Use a batch update to move the item without causing projects - // be removed from the solution (and thus disposed). - using (solutionItem.ParentFolder.Items.BatchUpdate()) { - using (folderNode.Folder.Items.BatchUpdate()) { - solutionItem.ParentFolder.Items.Remove(solutionItem); - folderNode.Folder.Items.Add(solutionItem); - } - } + MoveItem(solutionItem, folderNode.Folder); ExtTreeView treeView = (ExtTreeView)folderTreeNode.TreeView; foreach (ExtTreeNode node in treeView.CutNodes) { ExtTreeNode oldParent = node.Parent as ExtTreeNode; @@ -192,7 +185,19 @@ namespace ICSharpCode.SharpDevelop.Project } folderTreeNode.Expand(); } - + + internal static void MoveItem(ISolutionItem solutionItem, ISolutionFolder folder) + { + // Use a batch update to move the item without causing projects + // be removed from the solution (and thus disposed). + using (solutionItem.ParentFolder.Items.BatchUpdate()) { + using (folder.Items.BatchUpdate()) { + solutionItem.ParentFolder.Items.Remove(solutionItem); + folder.Items.Add(solutionItem); + } + } + } + public override bool EnablePaste { get { return DoEnablePaste(this); @@ -255,7 +260,8 @@ namespace ICSharpCode.SharpDevelop.Project folderNode.Remove(); folderNode.InsertSorted(this); folderNode.EnsureVisible(); - this.folder.Items.Add(folderNode.Folder); + MoveItem(folderNode.Folder, this.folder); + if (parentNode != null) { parentNode.Refresh(); } @@ -264,9 +270,7 @@ namespace ICSharpCode.SharpDevelop.Project if (dataObject.GetDataPresent(typeof(SolutionItemNode))) { SolutionItemNode solutionItemNode = (SolutionItemNode)dataObject.GetData(typeof(SolutionItemNode)); - ISolutionFolderNode folderNode = (ISolutionFolderNode)solutionItemNode.Parent; - folderNode.Folder.Items.Remove(solutionItemNode.SolutionItem); - Folder.Items.Add(solutionItemNode.SolutionItem); + MoveItem(solutionItemNode.SolutionItem, this.folder); solutionItemNode.Remove(); solutionItemNode.InsertSorted(this); @@ -282,7 +286,7 @@ namespace ICSharpCode.SharpDevelop.Project projectNode.Remove(); projectNode.InsertSorted(this); projectNode.EnsureVisible(); - this.folder.Items.Add(projectNode.Project); + MoveItem(projectNode.Project, this.folder); if (projectNode.Parent != null) { ((ExtTreeNode)projectNode.Parent).Refresh(); diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionNode.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionNode.cs index 69c0a18274..0f489b9fbb 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionNode.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionNode.cs @@ -119,7 +119,7 @@ namespace ICSharpCode.SharpDevelop.Project folderNode.Remove(); folderNode.InsertSorted(this); - this.solution.Items.Add(folderNode.Folder); + SolutionFolderNode.MoveItem(folderNode.Folder, this.solution); } if (dataObject.GetDataPresent(typeof(ProjectNode))) { ProjectNode projectNode = (ProjectNode)dataObject.GetData(typeof(ProjectNode)); @@ -128,7 +128,7 @@ namespace ICSharpCode.SharpDevelop.Project projectNode.Remove(); projectNode.InsertSorted(this); projectNode.EnsureVisible(); - this.solution.Items.Add(projectNode.Project); + SolutionFolderNode.MoveItem(projectNode.Project, this.solution); } if (parentNode != null) { diff --git a/src/Main/SharpDevelop/Project/SolutionFolder.cs b/src/Main/SharpDevelop/Project/SolutionFolder.cs index 14785f45e7..d61b1ec328 100644 --- a/src/Main/SharpDevelop/Project/SolutionFolder.cs +++ b/src/Main/SharpDevelop/Project/SolutionFolder.cs @@ -68,15 +68,25 @@ namespace ICSharpCode.SharpDevelop.Project return new CompositeDisposable(base.BatchUpdate(), folder.parentSolution.ReportBatch()); } + protected override void OnAdd(ISolutionItem item) + { + base.OnAdd(item); + item.ParentFolder = folder; + } + + protected override void OnRemove(ISolutionItem item) + { + base.OnRemove(item); + item.ParentFolder = null; + } + protected override void OnCollectionChanged(IReadOnlyCollection removedItems, IReadOnlyCollection addedItems) { using (folder.parentSolution.ReportBatch()) { foreach (ISolutionItem item in removedItems) { folder.parentSolution.ReportRemovedItem(item); - item.ParentFolder = null; } foreach (ISolutionItem item in addedItems) { - item.ParentFolder = folder; folder.parentSolution.ReportAddedItem(item); } }