Browse Source

Implemented SD2-1296: Watch files for external changes

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2996 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 18 years ago
parent
commit
7e345cff99
  1. 103
      src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs
  2. 11
      src/Main/Base/Project/Src/Services/File/OpenedFile.cs
  3. 8
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

103
src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs

@ -9,31 +9,24 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Windows.Forms;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.Core; using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
{ {
internal sealed class FileChangeWatcher //: IDisposable internal sealed class FileChangeWatcher : IDisposable
{ {
/*FileSystemWatcher watcher;
bool wasChangedExternally = false;
string fileName;
AbstractViewContent viewContent;
public FileChangeWatcher(AbstractViewContent viewContent)
{
this.viewContent = viewContent;
WorkbenchSingleton.MainForm.Activated += GotFocusEvent;
}
*/
public static bool DetectExternalChangesOption { public static bool DetectExternalChangesOption {
get { get {
return PropertyService.Get("SharpDevelop.FileChangeWatcher.DetectExternalChanges", true); return PropertyService.Get("SharpDevelop.FileChangeWatcher.DetectExternalChanges", true);
} }
set { set {
WorkbenchSingleton.AssertMainThread();
PropertyService.Set("SharpDevelop.FileChangeWatcher.DetectExternalChanges", value); PropertyService.Set("SharpDevelop.FileChangeWatcher.DetectExternalChanges", value);
foreach (FileChangeWatcher watcher in activeWatchers) {
watcher.SetWatcher();
}
} }
} }
@ -46,39 +39,69 @@ namespace ICSharpCode.SharpDevelop
} }
} }
/* static Set<FileChangeWatcher> activeWatchers = new Set<FileChangeWatcher>();
FileSystemWatcher watcher;
bool wasChangedExternally = false;
OpenedFile file;
public FileChangeWatcher(OpenedFile file)
{
if (file == null)
throw new ArgumentNullException("file");
WorkbenchSingleton.AssertMainThread();
this.file = file;
WorkbenchSingleton.MainForm.Activated += MainForm_Activated;
file.FileNameChanged += file_FileNameChanged;
activeWatchers.Add(this);
SetWatcher();
}
void file_FileNameChanged(object sender, EventArgs e)
{
SetWatcher();
}
public void Dispose() public void Dispose()
{ {
WorkbenchSingleton.MainForm.Activated -= GotFocusEvent; WorkbenchSingleton.AssertMainThread();
activeWatchers.Remove(this);
if (file != null) {
WorkbenchSingleton.MainForm.Activated -= MainForm_Activated;
file.FileNameChanged -= file_FileNameChanged;
file = null;
}
if (watcher != null) { if (watcher != null) {
watcher.Dispose(); watcher.Dispose();
watcher = null;
} }
} }
public void Disable() void SetWatcher()
{ {
if (watcher != null) { if (watcher != null) {
watcher.EnableRaisingEvents = false; watcher.EnableRaisingEvents = false;
} }
}
public void SetWatcher(string fileName)
{
this.fileName = fileName;
if (DetectExternalChangesOption == false) if (DetectExternalChangesOption == false)
return; return;
string fileName = file.FileName;
if (FileUtility.IsUrl(fileName))
return;
if (!Path.IsPathRooted(fileName))
return;
try { try {
if (this.watcher == null) { if (watcher == null) {
this.watcher = new FileSystemWatcher(); watcher = new FileSystemWatcher();
this.watcher.SynchronizingObject = WorkbenchSingleton.MainForm; watcher.SynchronizingObject = WorkbenchSingleton.MainForm;
this.watcher.Changed += new FileSystemEventHandler(this.OnFileChangedEvent); watcher.Changed += new FileSystemEventHandler(this.OnFileChangedEvent);
} else {
this.watcher.EnableRaisingEvents = false;
} }
this.watcher.Path = Path.GetDirectoryName(fileName); watcher.Path = Path.GetDirectoryName(fileName);
this.watcher.Filter = Path.GetFileName(fileName); watcher.Filter = Path.GetFileName(fileName);
this.watcher.NotifyFilter = NotifyFilters.LastWrite; watcher.NotifyFilter = NotifyFilters.LastWrite;
this.watcher.EnableRaisingEvents = true; watcher.EnableRaisingEvents = true;
} catch (PlatformNotSupportedException) { } catch (PlatformNotSupportedException) {
if (watcher != null) { if (watcher != null) {
watcher.Dispose(); watcher.Dispose();
@ -91,34 +114,38 @@ namespace ICSharpCode.SharpDevelop
{ {
if (e.ChangeType != WatcherChangeTypes.Deleted) { if (e.ChangeType != WatcherChangeTypes.Deleted) {
wasChangedExternally = true; wasChangedExternally = true;
if (ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.Workbench.IsActiveWindow) { if (WorkbenchSingleton.Workbench.IsActiveWindow) {
// delay showing message a bit, prevents showing two messages // delay showing message a bit, prevents showing two messages
// when the file changes twice in quick succession // when the file changes twice in quick succession
WorkbenchSingleton.SafeThreadAsyncCall(GotFocusEvent, this, EventArgs.Empty); WorkbenchSingleton.SafeThreadAsyncCall(MainForm_Activated, this, EventArgs.Empty);
} }
} }
} }
void GotFocusEvent(object sender, EventArgs e) void MainForm_Activated(object sender, EventArgs e)
{ {
if (wasChangedExternally) { if (wasChangedExternally) {
wasChangedExternally = false; wasChangedExternally = false;
if (file == null)
return;
string fileName = file.FileName;
string message = StringParser.Parse("${res:ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.TextEditorDisplayBinding.FileAlteredMessage}", new string[,] {{"File", Path.GetFullPath(fileName)}}); string message = StringParser.Parse("${res:ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.TextEditorDisplayBinding.FileAlteredMessage}", new string[,] {{"File", Path.GetFullPath(fileName)}});
if ((AutoLoadExternalChangesOption && viewContent.IsDirty == false) if ((AutoLoadExternalChangesOption && file.IsDirty == false)
|| MessageBox.Show(message, || MessageBox.Show(message,
StringParser.Parse("${res:MainWindow.DialogName}"), StringParser.Parse("${res:MainWindow.DialogName}"),
MessageBoxButtons.YesNo, MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.Yes) MessageBoxIcon.Question) == DialogResult.Yes)
{ {
if (File.Exists(fileName)) { if (File.Exists(fileName)) {
viewContent.Load(fileName); file.ReloadFromDisk();
} }
} else { } else {
viewContent.IsDirty = true; file.MakeDirty();
} }
} }
} }
*/
} }
} }

11
src/Main/Base/Project/Src/Services/File/OpenedFile.cs

@ -299,6 +299,7 @@ namespace ICSharpCode.SharpDevelop
using (Stream sourceStream = OpenRead()) { using (Stream sourceStream = OpenRead()) {
currentView.Load(this, sourceStream); currentView.Load(this, sourceStream);
} }
IsDirty = false;
} finally { } finally {
inLoadOperation = false; inLoadOperation = false;
} }
@ -309,6 +310,7 @@ namespace ICSharpCode.SharpDevelop
sealed class FileServiceOpenedFile : OpenedFile sealed class FileServiceOpenedFile : OpenedFile
{ {
List<IViewContent> registeredViews = new List<IViewContent>(); List<IViewContent> registeredViews = new List<IViewContent>();
FileChangeWatcher fileChangeWatcher;
protected override void ChangeFileName(string newValue) protected override void ChangeFileName(string newValue)
{ {
@ -320,6 +322,7 @@ namespace ICSharpCode.SharpDevelop
{ {
this.FileName = fileName; this.FileName = fileName;
IsUntitled = false; IsUntitled = false;
fileChangeWatcher = new FileChangeWatcher(this);
} }
internal FileServiceOpenedFile(byte[] fileData) internal FileServiceOpenedFile(byte[] fileData)
@ -328,6 +331,7 @@ namespace ICSharpCode.SharpDevelop
SetData(fileData); SetData(fileData);
IsUntitled = true; IsUntitled = true;
MakeDirty(); MakeDirty();
fileChangeWatcher = new FileChangeWatcher(this);
} }
/// <summary> /// <summary>
@ -388,7 +392,7 @@ namespace ICSharpCode.SharpDevelop
} }
} else { } else {
// all views to the file were closed // all views to the file were closed
FileService.OpenedFileClosed(this); CloseIfAllViewsClosed();
} }
} }
@ -396,6 +400,11 @@ namespace ICSharpCode.SharpDevelop
{ {
if (registeredViews.Count == 0) { if (registeredViews.Count == 0) {
FileService.OpenedFileClosed(this); FileService.OpenedFileClosed(this);
if (fileChangeWatcher != null) {
fileChangeWatcher.Dispose();
fileChangeWatcher = null;
}
} }
} }

8
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -173,7 +173,8 @@ namespace ICSharpCode.SharpDevelop
} }
WorkbenchSingleton.SafeThreadAsyncCall(ProjectService.ParserServiceCreatedProjectContents); WorkbenchSingleton.SafeThreadAsyncCall(ProjectService.ParserServiceCreatedProjectContents);
try { try {
progressMonitor.BeginTask("Loading references...", createdContents.Count, false); // multiply Count with 2 so that the progress bar is only at 50% when references are done
progressMonitor.BeginTask("Loading references...", createdContents.Count * 2, false);
int workAmount = 0; int workAmount = 0;
for (int i = 0; i < createdContents.Count; i++) { for (int i = 0; i < createdContents.Count; i++) {
if (abortLoadSolutionProjectsThread) return; if (abortLoadSolutionProjectsThread) return;
@ -186,7 +187,10 @@ namespace ICSharpCode.SharpDevelop
MessageService.ShowError(e, "Error while initializing project references:" + newContent); MessageService.ShowError(e, "Error while initializing project references:" + newContent);
} }
} }
progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount, false); // multiply workamount with two and start at workAmount so that the progress bar continues
// from 50% towards 100%.
progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount * 2, false);
progressMonitor.WorkDone = workAmount;
foreach (ParseProjectContent newContent in createdContents) { foreach (ParseProjectContent newContent in createdContents) {
if (abortLoadSolutionProjectsThread) return; if (abortLoadSolutionProjectsThread) return;
try { try {

Loading…
Cancel
Save