diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj
index 39507f9ed5..532257cbd9 100644
--- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj
+++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj
@@ -130,6 +130,7 @@
+
@@ -225,6 +226,7 @@
+
@@ -381,6 +383,7 @@
+
@@ -427,6 +430,7 @@
+
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs
index 5bbb903496..c41a7742fd 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/Design/FakePackageManagementProjectService.cs
@@ -85,5 +85,12 @@ namespace ICSharpCode.PackageManagement.Design
{
return new DefaultProjectContent();
}
+
+ public IProjectBrowserUpdater ProjectBrowserUpdater;
+
+ public IProjectBrowserUpdater CreateProjectBrowserUpdater()
+ {
+ return ProjectBrowserUpdater;
+ }
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/Project.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/Project.cs
index 7da23c5ee2..dff3cde73b 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/Project.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/Project.cs
@@ -256,5 +256,10 @@ namespace ICSharpCode.PackageManagement.EnvDTE
{
return FileUtility.GetRelativePath(MSBuildProject.Directory, path);
}
+
+ internal IProjectBrowserUpdater CreateProjectBrowserUpdater()
+ {
+ return projectService.CreateProjectBrowserUpdater();
+ }
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/ProjectItems.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/ProjectItems.cs
index eef0ab2cc3..5474a667e3 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/ProjectItems.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/ProjectItems.cs
@@ -89,17 +89,21 @@ namespace ICSharpCode.PackageManagement.EnvDTE
public virtual ProjectItem AddFromDirectory(string directory)
{
- ProjectItem directoryItem = project.AddDirectoryProjectItemUsingFullPath(directory);
- project.Save();
- return directoryItem;
+ using (IProjectBrowserUpdater updater = project.CreateProjectBrowserUpdater()) {
+ ProjectItem directoryItem = project.AddDirectoryProjectItemUsingFullPath(directory);
+ project.Save();
+ return directoryItem;
+ }
}
public virtual ProjectItem AddFromFile(string fileName)
{
- ProjectItem projectItem = project.AddFileProjectItemUsingFullPath(fileName);
- project.Save();
- fileService.ParseFile(fileName);
- return projectItem;
+ using (IProjectBrowserUpdater updater = project.CreateProjectBrowserUpdater()) {
+ ProjectItem projectItem = project.AddFileProjectItemUsingFullPath(fileName);
+ project.Save();
+ fileService.ParseFile(fileName);
+ return projectItem;
+ }
}
public virtual int Count {
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProjectService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProjectService.cs
index a692a977d1..1a85ff0827 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProjectService.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/IPackageManagementProjectService.cs
@@ -25,6 +25,8 @@ namespace ICSharpCode.PackageManagement
IEnumerable GetOpenProjects();
- IProjectContent GetProjectContent(IProject project);
+ IProjectContent GetProjectContent(IProject project);
+
+ IProjectBrowserUpdater CreateProjectBrowserUpdater();
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/IProjectBrowserUpdater.cs b/src/AddIns/Misc/PackageManagement/Project/Src/IProjectBrowserUpdater.cs
new file mode 100644
index 0000000000..f855cdb80a
--- /dev/null
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/IProjectBrowserUpdater.cs
@@ -0,0 +1,11 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+
+namespace ICSharpCode.PackageManagement
+{
+ public interface IProjectBrowserUpdater : IDisposable
+ {
+ }
+}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProjectService.cs b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProjectService.cs
index 63ad28d556..3bc8a20ff0 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProjectService.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/PackageManagementProjectService.cs
@@ -94,5 +94,10 @@ namespace ICSharpCode.PackageManagement
add { ProjectService.SolutionFolderRemoved += value; }
remove { ProjectService.SolutionFolderRemoved -= value; }
}
+
+ public IProjectBrowserUpdater CreateProjectBrowserUpdater()
+ {
+ return new ThreadSafeProjectBrowserUpdater();
+ }
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/ProjectBrowserUpdater.cs b/src/AddIns/Misc/PackageManagement/Project/Src/ProjectBrowserUpdater.cs
new file mode 100644
index 0000000000..c28730f8d9
--- /dev/null
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/ProjectBrowserUpdater.cs
@@ -0,0 +1,44 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.PackageManagement
+{
+ public class ProjectBrowserUpdater : IProjectBrowserUpdater
+ {
+ ProjectBrowserControl projectBrowser;
+
+ public ProjectBrowserUpdater()
+ : this(ProjectBrowserPad.Instance.ProjectBrowserControl)
+ {
+ }
+
+ public ProjectBrowserUpdater(ProjectBrowserControl projectBrowser)
+ {
+ this.projectBrowser = projectBrowser;
+ ProjectService.ProjectItemAdded += ProjectItemAdded;
+ }
+
+ protected virtual void ProjectItemAdded(object sender, ProjectItemEventArgs e)
+ {
+ if (e.ProjectItem is FileProjectItem) {
+ AddFileProjectItemToProjectBrowser(e);
+ }
+ }
+
+ void AddFileProjectItemToProjectBrowser(ProjectItemEventArgs e)
+ {
+ var visitor = new UpdateProjectBrowserFileNodesVisitor(e);
+ foreach (AbstractProjectBrowserTreeNode node in projectBrowser.TreeView.Nodes) {
+ node.AcceptVisitor(visitor, null);
+ }
+ }
+
+ public void Dispose()
+ {
+ ProjectService.ProjectItemAdded -= ProjectItemAdded;
+ }
+ }
+}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/ThreadSafeProjectBrowserUpdater.cs b/src/AddIns/Misc/PackageManagement/Project/Src/ThreadSafeProjectBrowserUpdater.cs
new file mode 100644
index 0000000000..e551f89aee
--- /dev/null
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/ThreadSafeProjectBrowserUpdater.cs
@@ -0,0 +1,31 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.PackageManagement
+{
+ public class ThreadSafeProjectBrowserUpdater : ProjectBrowserUpdater
+ {
+ public ThreadSafeProjectBrowserUpdater()
+ : base(GetProjectBrowserControl())
+ {
+ }
+
+ static ProjectBrowserControl GetProjectBrowserControl()
+ {
+ if (WorkbenchSingleton.InvokeRequired) {
+ return WorkbenchSingleton.SafeThreadFunction(() => GetProjectBrowserControl());
+ } else {
+ return ProjectBrowserPad.Instance.ProjectBrowserControl;
+ }
+ }
+
+ protected override void ProjectItemAdded(object sender, ProjectItemEventArgs e)
+ {
+ WorkbenchSingleton.SafeThreadAsyncCall(() => base.ProjectItemAdded(sender, e));
+ }
+ }
+}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/UpdateProjectBrowserFileNodesVisitor.cs b/src/AddIns/Misc/PackageManagement/Project/Src/UpdateProjectBrowserFileNodesVisitor.cs
new file mode 100644
index 0000000000..30778b8566
--- /dev/null
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/UpdateProjectBrowserFileNodesVisitor.cs
@@ -0,0 +1,141 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Windows.Forms;
+
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.PackageManagement
+{
+ public class UpdateProjectBrowserFileNodesVisitor : ProjectBrowserTreeNodeVisitor
+ {
+ ProjectItemEventArgs projectItemEventArgs;
+ FileProjectItem newFileAddedToProject;
+ string directoryForNewFileAddedToProject;
+
+ public UpdateProjectBrowserFileNodesVisitor(ProjectItemEventArgs projectItemEventArgs)
+ {
+ this.projectItemEventArgs = projectItemEventArgs;
+ this.newFileAddedToProject = projectItemEventArgs.ProjectItem as FileProjectItem;
+ }
+
+ string DirectoryForNewFileAddedToProject {
+ get {
+ if (directoryForNewFileAddedToProject == null) {
+ directoryForNewFileAddedToProject = Path.GetDirectoryName(newFileAddedToProject.FileName);
+ }
+ return directoryForNewFileAddedToProject;
+ }
+ }
+
+ public override object Visit(ProjectNode projectNode, object data)
+ {
+ if (IsFileAddedInProject(projectNode)) {
+ return Visit((DirectoryNode)projectNode, data);
+ }
+ return null;
+ }
+
+ public override object Visit(DirectoryNode directoryNode, object data)
+ {
+ if (!ShouldVisitDirectoryNode(directoryNode))
+ return null;
+
+ if (IsImmediateParentForNewFile(directoryNode)) {
+ AddFileNodeTo(directoryNode);
+ } else if (IsChildDirectoryNodeMissingForNewFile(directoryNode)) {
+ AddChildDirectoryNodeForNewFileTo(directoryNode);
+ } else {
+ return base.Visit(directoryNode, data);
+ }
+ return null;
+ }
+
+ bool ShouldVisitDirectoryNode(DirectoryNode directoryNode)
+ {
+ return directoryNode.IsInitialized && IsNewFileInsideDirectory(directoryNode);
+ }
+
+ bool IsNewFileInsideDirectory(DirectoryNode directoryNode)
+ {
+ return FileUtility.IsBaseDirectory(directoryNode.Directory, DirectoryForNewFileAddedToProject);
+ }
+
+ bool IsFileAddedInProject(ProjectNode projectNode)
+ {
+ return projectNode.Project == newFileAddedToProject.Project;
+ }
+
+ bool IsImmediateParentForNewFile(DirectoryNode directoryNode)
+ {
+ return FileUtility.IsBaseDirectory(DirectoryForNewFileAddedToProject, directoryNode.Directory);
+ }
+
+ string GetDirectoryForFileAddedToProject()
+ {
+ return Path.GetDirectoryName(newFileAddedToProject.FileName);
+ }
+
+ void AddChildDirectoryNodeForNewFileTo(DirectoryNode parentNode)
+ {
+ string childDirectory = GetMissingChildDirectory(parentNode.Directory);
+ AddDirectoryNodeTo(parentNode, childDirectory);
+ }
+
+ string GetMissingChildDirectory(string parentDirectory)
+ {
+ string relativeDirectoryForNewFile = GetRelativeDirectoryForNewFile(parentDirectory);
+ string childDirectoryName = GetFirstChildDirectoryName(relativeDirectoryForNewFile);
+ return Path.Combine(parentDirectory, childDirectoryName);
+ }
+
+ string GetRelativeDirectoryForNewFile(string baseDirectory)
+ {
+ return FileUtility.GetRelativePath(baseDirectory, DirectoryForNewFileAddedToProject);
+ }
+
+ string GetFirstChildDirectoryName(string fullSubFolderPath)
+ {
+ return fullSubFolderPath.Split('\\').First();
+ }
+
+ void AddDirectoryNodeTo(TreeNode parentNode, string directory)
+ {
+ var directoryNode = new DirectoryNode(directory, FileNodeStatus.InProject);
+ directoryNode.InsertSorted(parentNode);
+ }
+
+ void AddFileNodeTo(TreeNode node)
+ {
+ var fileNode = new FileNode(newFileAddedToProject.FileName, FileNodeStatus.InProject);
+ fileNode.InsertSorted(node);
+ }
+
+ bool IsChildDirectoryNodeMissingForNewFile(DirectoryNode parentDirectoryNode)
+ {
+ return !IsChildDirectoryNodeAlreadyAddedForNewFile(parentDirectoryNode);
+ }
+
+ bool IsChildDirectoryNodeAlreadyAddedForNewFile(DirectoryNode parentDirectoryNode)
+ {
+ return GetChildDirectoryNodes(parentDirectoryNode)
+ .Any(childDirectoryNode => DirectoryOfNewFileStartsWith(childDirectoryNode));
+ }
+
+ bool DirectoryOfNewFileStartsWith(DirectoryNode directoryNode)
+ {
+ return FileUtility.IsBaseDirectory(directoryNode.Directory, DirectoryForNewFileAddedToProject);
+ }
+
+ IEnumerable GetChildDirectoryNodes(ExtTreeNode parentNode)
+ {
+ return parentNode.AllNodes.OfType();
+ }
+ }
+}
diff --git a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj
index 316a22e976..9a9ac5b54e 100644
--- a/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj
+++ b/src/AddIns/Misc/PackageManagement/Test/PackageManagement.Tests.csproj
@@ -185,6 +185,7 @@
+
@@ -361,6 +362,10 @@
+
+ SharpDevelop.exe
+ Always
+
diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/ProjectItemsTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/ProjectItemsTests.cs
index 65d735e9c5..711716a17e 100644
--- a/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/ProjectItemsTests.cs
+++ b/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/ProjectItemsTests.cs
@@ -10,6 +10,7 @@ using ICSharpCode.PackageManagement.EnvDTE;
using ICSharpCode.SharpDevelop.Project;
using NUnit.Framework;
using PackageManagement.Tests.Helpers;
+using Rhino.Mocks;
using DTE = ICSharpCode.PackageManagement.EnvDTE;
namespace PackageManagement.Tests.EnvDTE
@@ -40,6 +41,13 @@ namespace PackageManagement.Tests.EnvDTE
fakeFileService.AddDirectoryToFakeFileSystem(parentDirectory, childDirectory);
}
+ IProjectBrowserUpdater CreateProjectBrowserUpdater()
+ {
+ IProjectBrowserUpdater projectBrowserUpdater = MockRepository.GenerateStub();
+ project.FakeProjectService.ProjectBrowserUpdater = projectBrowserUpdater;
+ return projectBrowserUpdater;
+ }
+
[Test]
public void AddFromFileCopy_AddFileNameOutsideProjectFolder_FileIsIncludedInProjectInProjectFolder()
{
@@ -604,5 +612,34 @@ namespace PackageManagement.Tests.EnvDTE
Assert.AreEqual(@"d:\projects\myproject\tools\packages\a.txt", item.FileName);
Assert.AreEqual(1, msbuildProject.Items.Count);
}
+
+ [Test]
+ public void AddFromFile_FullFileNameIsInsideProject_ProjectBrowserUpdaterIsDisposed()
+ {
+ CreateProjectItems();
+ IProjectBrowserUpdater projectBrowserUpdater = CreateProjectBrowserUpdater();
+ msbuildProject.FileName = @"d:\projects\myproject\myproject.csproj";
+ string fileName = @"d:\projects\myproject\tools\test.cs";
+
+ msbuildProject.ItemTypeToReturnFromGetDefaultItemType = ItemType.Page;
+ projectItems.AddFromFile(fileName);
+
+ projectBrowserUpdater.AssertWasCalled(updater => updater.Dispose());
+ }
+
+ [Test]
+ public void AddFromDirectory_EmptyDirectoryInsideProject_ProjectBrowserUpdaterIsDisposed()
+ {
+ CreateProjectItems();
+ IProjectBrowserUpdater projectBrowserUpdater = CreateProjectBrowserUpdater();
+ msbuildProject.FileName = @"d:\projects\myproject\myproject.csproj";
+ string directory = @"d:\projects\myproject\tools";
+
+ projectItems.AddFromDirectory(directory);
+
+ bool saved = msbuildProject.IsSaved;
+
+ projectBrowserUpdater.AssertWasCalled(updater => updater.Dispose());
+ }
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ProjectHelper.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ProjectHelper.cs
index 924a5dc878..ad6ad3c20d 100644
--- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ProjectHelper.cs
+++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ProjectHelper.cs
@@ -28,6 +28,7 @@ namespace PackageManagement.Tests.Helpers
var project = new TestableProject(createInfo);
project.Parent = solution;
+ solution.AddFolder(project);
return project;
}
diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/ProjectBrowserUpdaterTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/ProjectBrowserUpdaterTests.cs
new file mode 100644
index 0000000000..6dc80c8aa7
--- /dev/null
+++ b/src/AddIns/Misc/PackageManagement/Test/Src/ProjectBrowserUpdaterTests.cs
@@ -0,0 +1,435 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Resources;
+using ICSharpCode.Core;
+using ICSharpCode.PackageManagement;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Project;
+using NUnit.Framework;
+using PackageManagement.Tests.Helpers;
+
+namespace PackageManagement.Tests
+{
+ [TestFixture]
+ public class ProjectBrowserUpdaterTests
+ {
+ ProjectBrowserControl projectBrowser;
+ ProjectBrowserUpdater projectBrowserUpdater;
+ TestableProject project;
+
+ [TestFixtureSetUp]
+ public void InitFixture()
+ {
+ PropertyService.InitializeServiceForUnitTests();
+
+ Assembly assembly = Assembly.Load("SharpDevelop");
+ ResourceService.RegisterNeutralImages(new ResourceManager("Resources.BitmapResources", assembly));
+ ResourceService.RegisterNeutralStrings(new ResourceManager("Resources.StringResources", assembly));
+
+ AddDefaultDotNetNodeBuilderToAddinTree();
+ }
+
+ void AddDefaultDotNetNodeBuilderToAddinTree()
+ {
+ string xml =
+ "\r\n" +
+ " \r\n" +
+ " \r\n" +
+ " \r\n" +
+ " \r\n" +
+ " \r\n" +
+ " \r\n" +
+ "";
+
+ var addin = AddIn.Load(new StringReader(xml), String.Empty, null);
+ addin.Enabled = true;
+ AddInTree.InsertAddIn(addin);
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ projectBrowser.Dispose();
+ }
+
+ FileNode GetFirstFileChildNode(ExtTreeNode node)
+ {
+ return GetFirstChildNode(node, childNode => childNode is FileNode) as FileNode;
+ }
+
+ ExtTreeNode GetFirstChildNode(ExtTreeNode node, Func predicate)
+ {
+ return node.AllNodes.FirstOrDefault(predicate);
+ }
+
+ DirectoryNode GetFirstDirectoryChildNode(ExtTreeNode node)
+ {
+ return GetFirstChildNode(node, childNode => childNode is DirectoryNode) as DirectoryNode;
+ }
+
+ void AddFileToUnknownProject(string fileName)
+ {
+ TestableProject unknownProject = ProjectHelper.CreateTestProject();
+ var fileProjectItem = new FileProjectItem(unknownProject, ItemType.Compile);
+ fileProjectItem.FileName = fileName;
+ ProjectService.AddProjectItem(unknownProject, fileProjectItem);
+ }
+
+ void CreateProjectBrowserUpdater()
+ {
+ CreateProjectBrowserControl();
+ CreateProjectBrowserUpdater(projectBrowser);
+ }
+
+ void CreateProjectBrowserControl()
+ {
+ projectBrowser = new ProjectBrowserControl();
+ }
+
+ void CreateProjectBrowserUpdater(ProjectBrowserControl control)
+ {
+ projectBrowserUpdater = new ProjectBrowserUpdater(control);
+ }
+
+ ProjectNode AddProjectToProjectBrowser(string projectFileName)
+ {
+ project = ProjectHelper.CreateTestProject();
+ project.FileName = projectFileName;
+
+ projectBrowser.ViewSolution(project.ParentSolution);
+ var solutionNode = projectBrowser.RootNode as SolutionNode;
+ return solutionNode.FirstNode as ProjectNode;
+ }
+
+ void AddFileToProject(string fileName)
+ {
+ var fileProjectItem = new FileProjectItem(project, ItemType.Compile) {
+ FileName = fileName
+ };
+ AddProjectItemToProject(fileProjectItem);
+ }
+
+ void AddReferenceToProject(string name)
+ {
+ var reference = new ReferenceProjectItem(project, name);
+ AddProjectItemToProject(reference);
+ }
+
+ void AddProjectItemToProject(ProjectItem item)
+ {
+ ProjectService.AddProjectItem(project, item);
+ }
+
+ FileNode GetFileChildNodeAtIndex(ExtTreeNode node, int index)
+ {
+ return GetChildNodesOfType(node).ElementAt(index);
+ }
+
+ IEnumerable GetChildNodesOfType(ExtTreeNode parentNode)
+ {
+ return parentNode.AllNodes.OfType();
+ }
+
+ DirectoryNode GetDirectoryChildNodeAtIndex(ProjectNode projectNode, int index)
+ {
+ return GetChildNodesOfType(projectNode).ElementAt(index);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithNoFilesAndFileAddedToProjectRootDirectory_FileNodeAddedToProjectBrowser()
+ {
+ CreateProjectBrowserUpdater();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ projectNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\test.cs");
+
+ FileNode fileNode = GetFirstFileChildNode(projectNode);
+ Assert.AreEqual(@"d:\projects\MyProject\test.cs", fileNode.FileName);
+ Assert.AreEqual(FileNodeStatus.InProject, fileNode.FileNodeStatus);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithNoFilesAndReferenceAddedToProject_ReferenceIgnoredByProjectBrowserUpdater()
+ {
+ CreateProjectBrowserUpdater();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ projectNode.Expanding();
+
+ AddReferenceToProject("System.Xml");
+
+ FileNode fileNode = GetFirstFileChildNode(projectNode);
+ Assert.IsNull(fileNode);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithNoFilesAndFileAddedToUnknownProject_FileProjectItemAddedIsIgnored()
+ {
+ CreateProjectBrowserUpdater();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ projectNode.Expanding();
+
+ AddFileToUnknownProject(@"d:\projects\AnotherProject\test.cs");
+
+ FileNode fileNode = GetFirstFileChildNode(projectNode);
+ Assert.IsNull(fileNode);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithNoFilesAndFileAddedInSubDirectory_DirectoryNodeAddedToProjectNode()
+ {
+ CreateProjectBrowserUpdater();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ projectNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\Subfolder\test.cs");
+
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ Assert.AreEqual(@"d:\projects\MyProject\Subfolder", directoryNode.Directory);
+ Assert.AreEqual("Subfolder", directoryNode.Text);
+ Assert.AreEqual(FileNodeStatus.InProject, directoryNode.FileNodeStatus);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithNoFilesAndFileAddedTwoSubFoldersBelowProjectRootDirectory_DirectoryNodeForFirstSubFolderAddedToProjectNode()
+ {
+ CreateProjectBrowserUpdater();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ projectNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\Subfolder1\Subfolder2\test.cs");
+
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ Assert.AreEqual(@"d:\projects\MyProject\Subfolder1", directoryNode.Directory);
+ Assert.AreEqual(FileNodeStatus.InProject, directoryNode.FileNodeStatus);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithNoFilesAndFileAddedInSubdirectory_NoFileNodeAddedToProjectNode()
+ {
+ CreateProjectBrowserUpdater();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ projectNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\Subfolder\test.cs");
+
+ FileNode fileNode = GetFirstFileChildNode(projectNode);
+ Assert.IsNull(fileNode);
+ }
+
+ [Test]
+ public void Constructor_ProjectNodeHasNeverBeenExpandedAndFileAddedToProject_FileNodeNotAdded()
+ {
+ CreateProjectBrowserUpdater();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+
+ AddFileToProject(@"d:\projects\MyProject\test.cs");
+
+ FileNode fileNode = GetFirstFileChildNode(projectNode);
+ Assert.IsNull(fileNode);
+ }
+
+ [Test]
+ public void Dispose_ProjectWithNoFilesAndFileAddedToProjectRootDirectoryAfterUpdaterDisposed_NoFileNodeAdded()
+ {
+ CreateProjectBrowserUpdater();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ projectNode.Expanding();
+
+ projectBrowserUpdater.Dispose();
+
+ AddFileToProject(@"d:\projects\MyProject\test.cs");
+ FileNode fileNode = GetFirstFileChildNode(projectNode);
+ Assert.IsNull(fileNode);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithTwoFilesAndFileAddedToProjectRootDirectory_FileNodeAddedToProjectBrowserInAlphabeticalOrder()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a.cs");
+ AddFileToProject(@"d:\projects\MyProject\c.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\b.cs");
+
+ FileNode fileNode = GetFileChildNodeAtIndex(projectNode, 1);
+ Assert.AreEqual(@"d:\projects\MyProject\b.cs", fileNode.FileName);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithTwoFoldersAndFileInSubFolderAddedToProject_FileDirectoryNodeAddedToProjectBrowserInAlphabeticalOrder()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\a.cs");
+ AddFileToProject(@"d:\projects\MyProject\c\a.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\b\test.cs");
+
+ DirectoryNode directoryNode = GetDirectoryChildNodeAtIndex(projectNode, 1);
+ Assert.AreEqual(@"d:\projects\MyProject\b", directoryNode.Directory);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithOneFileInSubFolderAndNewFileAddedToSubFolder_DirectoryNodeNotAddedToProjectSinceItAlreadyExists()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\a.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\a\test.cs");
+
+ int count = GetChildNodesOfType(projectNode).Count();
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ FileNode fileNode = GetFirstFileChildNode(directoryNode);
+ Assert.AreEqual(1, count);
+ Assert.IsNull(fileNode);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithDirectoryNodeExpandedAndNewFileAddedToDirectory_FileAddedToDirectory()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\a.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ directoryNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\a\test.cs");
+
+ FileNode fileNode = GetFileChildNodeAtIndex(directoryNode, 1);
+ Assert.AreEqual(@"d:\projects\MyProject\a\test.cs", fileNode.FileName);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithDirectoryNodeExpandedAndNewFileAddedToSubFolderOfExpandedDirectory_NoNewFileNodedAdded()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\a.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ directoryNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\a\b\test.cs");
+
+ int childFileNodesCount = GetChildNodesOfType(directoryNode).Count();
+ FileNode fileNode = GetFirstFileChildNode(directoryNode);
+ Assert.AreEqual(1, childFileNodesCount);
+ Assert.AreEqual(@"d:\projects\MyProject\a\a.cs", fileNode.FileName);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithDirectoryNodeExpandedAndNewFileAddedToSubFolderOfExpandedDirectory_DirectoryNodeAddedToDirectoryNode()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\a.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ directoryNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\a\b\test.cs");
+
+ DirectoryNode childDirectoryNode = GetFirstDirectoryChildNode(directoryNode);
+ Assert.AreEqual(@"d:\projects\MyProject\a\b", childDirectoryNode.Directory);
+ Assert.AreEqual(FileNodeStatus.InProject, childDirectoryNode.FileNodeStatus);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithDirectoryNodeExpandedAndNewFileAddedToSubFolderTwoLevelsBelowExpandedDirectory_DirectoryNodeAddedForChildSubFolder()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\a.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ directoryNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\a\b\c\test.cs");
+
+ DirectoryNode childDirectoryNode = GetFirstDirectoryChildNode(directoryNode);
+ Assert.AreEqual(@"d:\projects\MyProject\a\b", childDirectoryNode.Directory);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithDirectoryNodeExpandedAndNewFileAddedToSubFolderWhichAlreadyExistsInExpandedDirectory_NewDirectoryNodeNotAdded()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\a.cs");
+ AddFileToProject(@"d:\projects\MyProject\a\b\b.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ directoryNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\a\b\test.cs");
+
+ int directoryNodeCount = GetChildNodesOfType(directoryNode).Count();
+ DirectoryNode childDirectoryNode = GetFirstDirectoryChildNode(directoryNode);
+ Assert.AreEqual(1, directoryNodeCount);
+ Assert.AreEqual(@"d:\projects\MyProject\a\b", childDirectoryNode.Directory);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithDirectoryNodeTwoLevelsDeepExpandedAndNewFileAddedToSubFolderOfExpandedDirectory_DirectoryNodeAddedToDirectoryNode()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\b\a.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+ DirectoryNode topLevelDirectoryNode = GetFirstDirectoryChildNode(projectNode);
+ topLevelDirectoryNode.Expanding();
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(topLevelDirectoryNode);
+ directoryNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\a\b\test.cs");
+
+ FileNode fileNode = GetFileChildNodeAtIndex(directoryNode, 1);
+ Assert.AreEqual(@"d:\projects\MyProject\a\b\test.cs", fileNode.FileName);
+ Assert.AreEqual(FileNodeStatus.InProject, fileNode.FileNodeStatus);
+ }
+
+ [Test]
+ public void Constructor_ProjectWithTwoDirectoryNodesExpandedAndNewFileAddedToFirstExpandedDirectory_SecondDirectoryNodeIsNotAffected()
+ {
+ CreateProjectBrowserControl();
+ ProjectNode projectNode = AddProjectToProjectBrowser(@"d:\projects\MyProject\MyProject.csproj");
+ AddFileToProject(@"d:\projects\MyProject\a\a.cs");
+ AddFileToProject(@"d:\projects\MyProject\b\b.cs");
+ CreateProjectBrowserUpdater(projectBrowser);
+ projectNode.Expanding();
+ DirectoryNode directoryNode = GetFirstDirectoryChildNode(projectNode);
+ directoryNode.Expanding();
+ DirectoryNode secondDirectoryNode = GetDirectoryChildNodeAtIndex(projectNode, 1);
+ secondDirectoryNode.Expanding();
+
+ AddFileToProject(@"d:\projects\MyProject\a\test.cs");
+
+ FileNode fileNode = GetFirstFileChildNode(secondDirectoryNode);
+ Assert.AreEqual(1, secondDirectoryNode.Nodes.Count);
+ Assert.AreEqual(@"d:\projects\MyProject\b\b.cs", fileNode.FileName);
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeNode.cs b/src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeNode.cs
index 7046216122..6487f566d0 100644
--- a/src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeNode.cs
+++ b/src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeNode.cs
@@ -16,7 +16,7 @@ namespace ICSharpCode.SharpDevelop.Gui
protected bool isInitialized = false;
string image = null;
- internal bool IsInitialized {
+ public bool IsInitialized {
get {
return isInitialized;
}