diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index 9518e0dcff..ba84eabbcd 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -307,6 +307,7 @@
+
diff --git a/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectTemplate.cs b/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectTemplate.cs
index f16e12e80f..2e8d75c0e7 100644
--- a/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectTemplate.cs
+++ b/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectTemplate.cs
@@ -302,9 +302,10 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
} else if (projectDescriptor != null) {
bool createNewSolution = projectCreateInformation.Solution == null;
if (createNewSolution) {
- projectCreateInformation.Solution = new Solution();
+ string fileName = Path.Combine(projectCreateInformation.SolutionPath, projectCreateInformation.SolutionName + ".sln");
+ projectCreateInformation.Solution = new Solution(new ProjectChangeWatcher(fileName));
projectCreateInformation.Solution.Name = projectCreateInformation.SolutionName;
- projectCreateInformation.Solution.FileName = Path.Combine(projectCreateInformation.SolutionPath, projectCreateInformation.SolutionName + ".sln");
+ projectCreateInformation.Solution.FileName = fileName;
}
IProject project = projectDescriptor.CreateProject(projectCreateInformation, this.languagename);
if (project != null) {
diff --git a/src/Main/Base/Project/Src/Internal/Templates/Project/SolutionDescriptor.cs b/src/Main/Base/Project/Src/Internal/Templates/Project/SolutionDescriptor.cs
index 64f9691b01..f72d24ec49 100644
--- a/src/Main/Base/Project/Src/Internal/Templates/Project/SolutionDescriptor.cs
+++ b/src/Main/Base/Project/Src/Internal/Templates/Project/SolutionDescriptor.cs
@@ -90,15 +90,6 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
public string CreateSolution(ProjectCreateInformation projectCreateInformation, string defaultLanguage)
{
- Solution newSolution = new Solution();
- projectCreateInformation.Solution = newSolution;
-
- string newSolutionName = StringParser.Parse(name, new string[,] {
- {"ProjectName", projectCreateInformation.SolutionName}
- });
-
- newSolution.Name = newSolutionName;
-
string oldSolutionPath = projectCreateInformation.SolutionPath;
string oldProjectPath = projectCreateInformation.ProjectBasePath;
if (relativeDirectory != null && relativeDirectory.Length > 0 && relativeDirectory != ".") {
@@ -115,12 +106,22 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
projectCreateInformation.SolutionPath = oldSolutionPath;
projectCreateInformation.ProjectBasePath = oldProjectPath;
+ string newSolutionName = StringParser.Parse(name, new string[,] {
+ {"ProjectName", projectCreateInformation.SolutionName}
+ });
+
+ string solutionLocation = Path.Combine(projectCreateInformation.SolutionPath, newSolutionName + ".sln");
+
+ Solution newSolution = new Solution(new ProjectChangeWatcher(solutionLocation));
+ projectCreateInformation.Solution = newSolution;
+
+ newSolution.Name = newSolutionName;
+
if (!mainFolder.AddContents(newSolution, projectCreateInformation, defaultLanguage, newSolution)) {
newSolution.Dispose();
return null;
}
- string solutionLocation = Path.Combine(projectCreateInformation.SolutionPath, newSolutionName + ".sln");
// Save solution
if (File.Exists(solutionLocation)) {
diff --git a/src/Main/Base/Project/Src/Project/ProjectChangeWatcher.cs b/src/Main/Base/Project/Src/Project/ProjectChangeWatcher.cs
new file mode 100644
index 0000000000..b38cce950e
--- /dev/null
+++ b/src/Main/Base/Project/Src/Project/ProjectChangeWatcher.cs
@@ -0,0 +1,133 @@
+// 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.IO;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Gui;
+
+namespace ICSharpCode.SharpDevelop.Project
+{
+ public sealed class ProjectChangeWatcher : IDisposable
+ {
+ FileSystemWatcher watcher;
+ string fileName;
+ bool enabled = true;
+
+ public ProjectChangeWatcher(string fileName)
+ {
+ this.fileName = fileName;
+ WorkbenchSingleton.MainWindow.Activated += MainFormActivated;
+ }
+
+ public void Enable()
+ {
+ enabled = true;
+ SetWatcher();
+ }
+
+ public void Disable()
+ {
+ enabled = false;
+ SetWatcher();
+ }
+
+ public void Rename(string newFileName)
+ {
+ fileName = newFileName;
+ }
+
+ void SetWatcher()
+ {
+ WorkbenchSingleton.AssertMainThread();
+
+ if (watcher != null) {
+ watcher.EnableRaisingEvents = false;
+ }
+
+ if (!enabled)
+ return;
+
+ if (string.IsNullOrEmpty(fileName))
+ return;
+ if (FileUtility.IsUrl(fileName))
+ return;
+ if (!Path.IsPathRooted(fileName))
+ return;
+
+ try {
+ if (watcher == null) {
+ watcher = new FileSystemWatcher();
+ if (WorkbenchSingleton.Workbench != null)
+ watcher.SynchronizingObject = WorkbenchSingleton.Workbench.SynchronizingObject;
+ watcher.Changed += OnFileChangedEvent;
+ watcher.Created += OnFileChangedEvent;
+ watcher.Renamed += OnFileChangedEvent;
+ }
+ watcher.Path = Path.GetDirectoryName(fileName);
+ watcher.Filter = Path.GetFileName(fileName);
+ watcher.EnableRaisingEvents = true;
+ } catch (PlatformNotSupportedException) {
+ if (watcher != null) {
+ watcher.Dispose();
+ }
+ watcher = null;
+ } catch (FileNotFoundException) {
+ // can occur if directory was deleted externally
+ if (watcher != null) {
+ watcher.Dispose();
+ }
+ watcher = null;
+ } catch (ArgumentException) {
+ // can occur if parent directory was deleted externally
+ if (watcher != null) {
+ watcher.Dispose();
+ }
+ watcher = null;
+ }
+ }
+
+ bool wasChangedExternally;
+
+ void OnFileChangedEvent(object sender, FileSystemEventArgs e)
+ {
+ LoggingService.Debug("Solution was changed externally: " + e.ChangeType);
+ if (!wasChangedExternally) {
+ wasChangedExternally = true;
+ if (WorkbenchSingleton.Workbench.IsActiveWindow) {
+ // delay reloading message a bit, prevents showing two messages
+ // when the file changes twice in quick succession; and prevents
+ // trying to reload the file while it is still being written
+ WorkbenchSingleton.CallLater(
+ TimeSpan.FromSeconds(0.5),
+ delegate { MainFormActivated(this, EventArgs.Empty); } );
+ }
+ }
+ }
+
+ void MainFormActivated(object sender, EventArgs e)
+ {
+ if (wasChangedExternally) {
+ wasChangedExternally = false;
+
+ if (MessageService.ShowCustomDialog(
+ MessageService.DefaultMessageBoxTitle,
+ "${res:ICSharpCode.SharpDevelop.Project.SolutionAlteredExternallyMessage}", 0, 1,
+ "${res:ICSharpCode.SharpDevelop.Project.ReloadSolution}", "${res:ICSharpCode.SharpDevelop.Project.KeepOldSolution}")
+ == 0)
+ {
+ ProjectService.LoadSolution(ProjectService.OpenSolution.FileName);
+ }
+ }
+ }
+
+ bool disposed;
+
+ public void Dispose()
+ {
+ if (!disposed) {
+ WorkbenchSingleton.MainWindow.Activated -= MainFormActivated;
+ }
+ disposed = true;
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Project/Solution/Solution.cs b/src/Main/Base/Project/Src/Project/Solution/Solution.cs
index 5fe6e31ce2..cb33801e3a 100644
--- a/src/Main/Base/Project/Src/Project/Solution/Solution.cs
+++ b/src/Main/Base/Project/Src/Project/Solution/Solution.cs
@@ -25,11 +25,13 @@ namespace ICSharpCode.SharpDevelop.Project
bool isLoading;
string fileName = String.Empty;
+ ProjectChangeWatcher changeWatcher;
- public Solution()
+ public Solution(ProjectChangeWatcher changeWatcher)
{
preferences = new SolutionPreferences(this);
this.MSBuildProjectCollection = new Microsoft.Build.Evaluation.ProjectCollection();
+ this.changeWatcher = changeWatcher;
}
public Microsoft.Build.Evaluation.ProjectCollection MSBuildProjectCollection { get; private set; }
@@ -183,7 +185,10 @@ namespace ICSharpCode.SharpDevelop.Project
return fileName;
}
set {
+ changeWatcher.Disable();
fileName = value;
+ changeWatcher.Rename(fileName);
+ changeWatcher.Enable();
}
}
@@ -288,8 +293,9 @@ namespace ICSharpCode.SharpDevelop.Project
public void Save()
{
try {
+ changeWatcher.Disable();
Save(fileName);
- return;
+ changeWatcher.Enable();
} catch (IOException ex) {
MessageService.ShowErrorFormatted("${res:SharpDevelop.Solution.CannotSave.IOException}", fileName, ex.Message);
} catch (UnauthorizedAccessException ex) {
@@ -307,6 +313,8 @@ namespace ICSharpCode.SharpDevelop.Project
public void Save(string fileName)
{
+ changeWatcher.Disable();
+ changeWatcher.Rename(fileName);
this.fileName = fileName;
string outputDirectory = Path.GetDirectoryName(fileName);
if (!System.IO.Directory.Exists(outputDirectory)) {
@@ -415,6 +423,7 @@ namespace ICSharpCode.SharpDevelop.Project
sw.WriteLine("EndGlobal");
}
+ changeWatcher.Enable();
}
static void SaveProjectSections(IEnumerable sections, StringBuilder projectSection)
@@ -1159,7 +1168,7 @@ namespace ICSharpCode.SharpDevelop.Project
public static Solution Load(string fileName)
{
- Solution newSolution = new Solution();
+ Solution newSolution = new Solution(new ProjectChangeWatcher(fileName));
solutionBeingLoaded = newSolution;
newSolution.Name = Path.GetFileNameWithoutExtension(fileName);
diff --git a/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs b/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs
index acbebe16b7..09ab6250ad 100644
--- a/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs
+++ b/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs
@@ -378,7 +378,7 @@ namespace ICSharpCode.SharpDevelop.Project
return;
}
}
- Solution solution = new Solution();
+ Solution solution = new Solution(new ProjectChangeWatcher(solutionFile));
solution.Name = Path.GetFileNameWithoutExtension(fileName);
IProjectBinding binding = ProjectBindingService.GetBindingPerProjectFile(fileName);
IProject project;
diff --git a/src/Main/Base/Test/WebReferences/WebReferenceTestHelper.cs b/src/Main/Base/Test/WebReferences/WebReferenceTestHelper.cs
index b2f9bd8276..b9940b0c54 100644
--- a/src/Main/Base/Test/WebReferences/WebReferenceTestHelper.cs
+++ b/src/Main/Base/Test/WebReferences/WebReferenceTestHelper.cs
@@ -26,7 +26,7 @@ namespace ICSharpCode.SharpDevelop.Tests.WebReferences
public TestProject(string languageName)
: base(new ProjectCreateInformation {
- Solution = new Solution(),
+ Solution = new Solution(new ProjectChangeWatcher("c:\\temp\\TestProject.csproj")),
ProjectName = "TestProject",
OutputProjectFileName = "c:\\temp\\TestProject.csproj"
})